]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
This commit was generated by cvs2svn to track changes on a CVS vendor
authorK. Richard Pixley <rich@cygnus>
Thu, 4 Apr 1991 18:19:55 +0000 (18:19 +0000)
committerK. Richard Pixley <rich@cygnus>
Thu, 4 Apr 1991 18:19:55 +0000 (18:19 +0000)
branch.

436 files changed:
bfd/COPYING [new file with mode: 0644]
bfd/ChangeLog [new file with mode: 0644]
bfd/Makefile [new file with mode: 0755]
bfd/TODO [new file with mode: 0644]
bfd/VERSION [new file with mode: 0644]
bfd/aout.c [new file with mode: 0755]
bfd/archive.c [new file with mode: 0644]
bfd/archures.c [new file with mode: 0644]
bfd/archures.h [new file with mode: 0755]
bfd/bfd.c [new file with mode: 0644]
bfd/bfd.doc [new file with mode: 0755]
bfd/cache.c [new file with mode: 0644]
bfd/coff-code.h [new file with mode: 0755]
bfd/coff-i960.c [new file with mode: 0644]
bfd/coff-m88k.c [new file with mode: 0644]
bfd/cplus-dem.c [new file with mode: 0755]
bfd/filemode.c [new file with mode: 0644]
bfd/hosts/dgux.h [new file with mode: 0644]
bfd/hosts/sparc.h [new file with mode: 0644]
bfd/hosts/sun3.h [new file with mode: 0644]
bfd/ieee.c [new file with mode: 0644]
bfd/libaout.h [new file with mode: 0644]
bfd/libbfd.c [new file with mode: 0644]
bfd/libbfd.h [new file with mode: 0644]
bfd/libcoff.h [new file with mode: 0644]
bfd/libieee.h [new file with mode: 0644]
bfd/liboasys.h [new file with mode: 0644]
bfd/misc.c [new file with mode: 0755]
bfd/misc.h [new file with mode: 0755]
bfd/oasys.c [new file with mode: 0644]
bfd/obstack.c [new file with mode: 0755]
bfd/obstack.h [new file with mode: 0755]
bfd/opncls.c [new file with mode: 0644]
bfd/srec.c [new file with mode: 0644]
bfd/sunos.c [new file with mode: 0644]
bfd/targets.c [new file with mode: 0644]
binutils/TODO [new file with mode: 0644]
binutils/alloca.c [new file with mode: 0644]
binutils/ar.c [new file with mode: 0644]
binutils/bucomm.c [new file with mode: 0644]
binutils/copy.c [new file with mode: 0644]
binutils/cplus-dem.c [new file with mode: 0644]
binutils/filemode.c [new file with mode: 0644]
binutils/gmalloc.c [new file with mode: 0644]
binutils/i960-pinsn.c [new file with mode: 0644]
binutils/m68k-pinsn.c [new file with mode: 0644]
binutils/nm.c [new file with mode: 0644]
binutils/objdump.c [new file with mode: 0644]
binutils/ostrip.c [new file with mode: 0755]
binutils/size.c [new file with mode: 0644]
binutils/sparc-pinsn.c [new file with mode: 0644]
binutils/strip.c [new file with mode: 0755]
binutils/version.c [new file with mode: 0644]
gas/Makefile-intel [new file with mode: 0755]
gas/Makefile.generic [new file with mode: 0755]
gas/a.out.gnu.h [new file with mode: 0755]
gas/config/a.out.h [new file with mode: 0755]
gas/config/coff.gnu.h [new file with mode: 0755]
gas/config/ho-ansi.h [new file with mode: 0644]
gas/config/ho-cygnus.h [new file with mode: 0755]
gas/config/ho-generic.h [new file with mode: 0644]
gas/config/ho-hpux.h [new file with mode: 0644]
gas/config/ho-i386.h [new file with mode: 0644]
gas/config/ho-sun3.h [new file with mode: 0644]
gas/config/ho-sun386.h [new file with mode: 0644]
gas/config/ho-sun4.h [new file with mode: 0644]
gas/config/ho-sunos.h [new file with mode: 0644]
gas/config/ho-sysv.h [new file with mode: 0644]
gas/configure.was [new file with mode: 0755]
gas/doc/a29k.m4 [new file with mode: 0644]
gas/doc/as.texinfo
gas/doc/i80386.m4 [new file with mode: 0644]
gas/doc/i960.m4 [new file with mode: 0644]
gas/doc/m680x0.m4 [new file with mode: 0644]
gas/doc/none.m4 [new file with mode: 0644]
gas/doc/pretex.m4 [new file with mode: 0644]
gas/doc/sparc.m4 [new file with mode: 0644]
gas/doc/vax.m4 [new file with mode: 0644]
gas/flonum-const.c [new file with mode: 0755]
gas/hex-value.c [new file with mode: 0644]
gas/strstr.c [new file with mode: 0644]
gas/testscripts/doboth [new file with mode: 0755]
gas/testscripts/doobjcmp [new file with mode: 0755]
gas/testscripts/dostriptest [new file with mode: 0755]
gas/testscripts/dotest [new file with mode: 0755]
gas/testscripts/dounsortreloc [new file with mode: 0755]
gas/testscripts/dounsortsymbols [new file with mode: 0755]
gas/xmalloc.c [new file with mode: 0644]
gas/xrealloc.c [new file with mode: 0644]
gdb/.gdbinit [new file with mode: 0644]
gdb/COPYING [new file with mode: 0644]
gdb/ChangeLog [new file with mode: 0644]
gdb/ChangeLog-3.x [new file with mode: 0644]
gdb/Convex.notes [new file with mode: 0644]
gdb/Makefile.dist [new file with mode: 0755]
gdb/Makefile.in [new file with mode: 0644]
gdb/Makefile.srcdir [new file with mode: 0755]
gdb/Projects [new file with mode: 0644]
gdb/README [new file with mode: 0644]
gdb/TODO [new file with mode: 0644]
gdb/WHATS.NEW [new file with mode: 0755]
gdb/alldeps.mak [new file with mode: 0644]
gdb/alloca.c [new file with mode: 0644]
gdb/altos-xdep.c [new file with mode: 0644]
gdb/am29k-opcode.h [new file with mode: 0644]
gdb/am29k-pinsn.c [new file with mode: 0644]
gdb/am29k-tdep.c [new file with mode: 0644]
gdb/ansidecl.h [new file with mode: 0755]
gdb/arm-convert.s [new file with mode: 0644]
gdb/arm-pinsn.c [new file with mode: 0644]
gdb/arm-tdep.c [new file with mode: 0644]
gdb/arm-xdep.c [new file with mode: 0644]
gdb/blockframe.c [new file with mode: 0644]
gdb/breakpoint.c [new file with mode: 0644]
gdb/breakpoint.h [new file with mode: 0644]
gdb/coffread.c [new file with mode: 0644]
gdb/command.c [new file with mode: 0644]
gdb/command.h [new file with mode: 0644]
gdb/config.gdb [new file with mode: 0755]
gdb/config.status [new file with mode: 0755]
gdb/config/3b1.mh [new file with mode: 0644]
gdb/config/3b1.mt [new file with mode: 0644]
gdb/config/altos.mh [new file with mode: 0644]
gdb/config/altos.mt [new file with mode: 0644]
gdb/config/altosgas.mh [new file with mode: 0644]
gdb/config/altosgas.mt [new file with mode: 0644]
gdb/config/am29k [new file with mode: 0755]
gdb/config/arm.mh [new file with mode: 0644]
gdb/config/arm.mt [new file with mode: 0644]
gdb/config/bigmips.mh [new file with mode: 0644]
gdb/config/bigmips.mt [new file with mode: 0644]
gdb/config/convex.mh [new file with mode: 0644]
gdb/config/convex.mt [new file with mode: 0644]
gdb/config/hp300bsd.mh [new file with mode: 0644]
gdb/config/hp300bsd.mt [new file with mode: 0644]
gdb/config/hp300hpux.mh [new file with mode: 0644]
gdb/config/hp300hpux.mt [new file with mode: 0644]
gdb/config/i386v-g.mh [new file with mode: 0644]
gdb/config/i386v-g.mt [new file with mode: 0644]
gdb/config/i386v.mh [new file with mode: 0644]
gdb/config/i386v.mt [new file with mode: 0644]
gdb/config/i386v32-g.mh [new file with mode: 0644]
gdb/config/i386v32-g.mt [new file with mode: 0644]
gdb/config/i386v32.mh [new file with mode: 0644]
gdb/config/i386v32.mt [new file with mode: 0644]
gdb/config/i960.mt [new file with mode: 0644]
gdb/config/isi.mh [new file with mode: 0644]
gdb/config/isi.mt [new file with mode: 0644]
gdb/config/littlemips.mh [new file with mode: 0644]
gdb/config/littlemips.mt [new file with mode: 0644]
gdb/config/m88k.mh [new file with mode: 0644]
gdb/config/m88k.mt [new file with mode: 0644]
gdb/config/merlin.mh [new file with mode: 0644]
gdb/config/merlin.mt [new file with mode: 0644]
gdb/config/mh-vax [new file with mode: 0755]
gdb/config/news.mh [new file with mode: 0644]
gdb/config/news.mt [new file with mode: 0644]
gdb/config/news1000.mh [new file with mode: 0644]
gdb/config/news1000.mt [new file with mode: 0644]
gdb/config/nindy960.mt [new file with mode: 0644]
gdb/config/none.mh [new file with mode: 0644]
gdb/config/none.mt [new file with mode: 0644]
gdb/config/np1.mh [new file with mode: 0644]
gdb/config/np1.mt [new file with mode: 0644]
gdb/config/pn.mh [new file with mode: 0644]
gdb/config/pn.mt [new file with mode: 0644]
gdb/config/pyramid.mh [new file with mode: 0644]
gdb/config/pyramid.mt [new file with mode: 0644]
gdb/config/sun2os3.mh [new file with mode: 0644]
gdb/config/sun2os3.mt [new file with mode: 0644]
gdb/config/sun2os4.mh [new file with mode: 0644]
gdb/config/sun2os4.mt [new file with mode: 0644]
gdb/config/sun3.mh [new file with mode: 0644]
gdb/config/sun3.mt [new file with mode: 0644]
gdb/config/sun386.mh [new file with mode: 0644]
gdb/config/sun386.mt [new file with mode: 0644]
gdb/config/sun3os3.mh [new file with mode: 0644]
gdb/config/sun3os3.mt [new file with mode: 0644]
gdb/config/sun3os4.mh [new file with mode: 0644]
gdb/config/sun3os4.mt [new file with mode: 0644]
gdb/config/sun4.mh [new file with mode: 0644]
gdb/config/sun4.mt [new file with mode: 0644]
gdb/config/sun4os3.mh [new file with mode: 0644]
gdb/config/sun4os3.mt [new file with mode: 0644]
gdb/config/sun4os4.mh [new file with mode: 0644]
gdb/config/sun4os4.mt [new file with mode: 0644]
gdb/config/symmetry.mh [new file with mode: 0644]
gdb/config/symmetry.mt [new file with mode: 0644]
gdb/config/umax.mh [new file with mode: 0644]
gdb/config/umax.mt [new file with mode: 0644]
gdb/config/vax.mt [new file with mode: 0644]
gdb/config/vxworks68.mt [new file with mode: 0644]
gdb/config/vxworks960.mt [new file with mode: 0644]
gdb/convex-opcode.h [new file with mode: 0755]
gdb/convex-pinsn.c [new file with mode: 0644]
gdb/convex-tdep.c [new file with mode: 0644]
gdb/convex-xdep.c [new file with mode: 0644]
gdb/copying.awk [new file with mode: 0644]
gdb/copying.c [new file with mode: 0644]
gdb/core.c [new file with mode: 0644]
gdb/coredep.c [new file with mode: 0644]
gdb/cplus-dem.c [new file with mode: 0644]
gdb/createtags [new file with mode: 0755]
gdb/dbxread.c [new file with mode: 0644]
gdb/defs.h [new file with mode: 0644]
gdb/depend [new file with mode: 0755]
gdb/doc/gdb.texinfo [new file with mode: 0644]
gdb/doc/gdbint.texinfo [new file with mode: 0644]
gdb/doc/refcard.tex [new file with mode: 0644]
gdb/doc/threecol.tex [new file with mode: 0755]
gdb/environ.c [new file with mode: 0644]
gdb/environ.h [new file with mode: 0644]
gdb/eval.c [new file with mode: 0644]
gdb/exec.c [new file with mode: 0644]
gdb/expprint.c [new file with mode: 0644]
gdb/expread.tab.c [new file with mode: 0755]
gdb/expread.y [new file with mode: 0755]
gdb/expression.h [new file with mode: 0644]
gdb/findvar.c [new file with mode: 0644]
gdb/frame.h [new file with mode: 0644]
gdb/gdb-int.texinfo [new file with mode: 0755]
gdb/gdbcmd.h [new file with mode: 0644]
gdb/gdbcore.h [new file with mode: 0644]
gdb/getpagesize.h [new file with mode: 0755]
gdb/gmalloc.c [new file with mode: 0755]
gdb/gmalloc.h [new file with mode: 0755]
gdb/gould-pinsn.c [new file with mode: 0644]
gdb/gould-xdep.c [new file with mode: 0644]
gdb/hp300hpux-xdep.c [new file with mode: 0755]
gdb/i386-pinsn.c [new file with mode: 0644]
gdb/i386-tdep.c [new file with mode: 0644]
gdb/i386-xdep.c [new file with mode: 0644]
gdb/i960-pinsn.c [new file with mode: 0644]
gdb/i960-tdep.c [new file with mode: 0644]
gdb/ieee-float.c [new file with mode: 0644]
gdb/ieee-float.h [new file with mode: 0644]
gdb/infcmd.c [new file with mode: 0644]
gdb/inferior.h [new file with mode: 0644]
gdb/inflow.c [new file with mode: 0644]
gdb/infptrace.c [new file with mode: 0644]
gdb/infrun.c [new file with mode: 0644]
gdb/inftarg.c [new file with mode: 0644]
gdb/kdb-start.c [new file with mode: 0644]
gdb/m68k-opcode.h [new file with mode: 0755]
gdb/m68k-pinsn.c [new file with mode: 0644]
gdb/m68k-tdep.c [new file with mode: 0644]
gdb/main.c [new file with mode: 0644]
gdb/mcheck.c [new file with mode: 0755]
gdb/mem-break.c [new file with mode: 0644]
gdb/mips-opcode.h [new file with mode: 0755]
gdb/mips-pinsn.c [new file with mode: 0644]
gdb/mips-tdep.c [new file with mode: 0644]
gdb/mips-xdep.c [new file with mode: 0644]
gdb/mipsread.c [new file with mode: 0644]
gdb/munch [new file with mode: 0755]
gdb/news-xdep.c [new file with mode: 0644]
gdb/nindy-tdep.c [new file with mode: 0644]
gdb/np1-opcode.h [new file with mode: 0755]
gdb/ns32k-opcode.h [new file with mode: 0644]
gdb/ns32k-pinsn.c [new file with mode: 0644]
gdb/obstack.c [new file with mode: 0755]
gdb/obstack.h [new file with mode: 0755]
gdb/param-no-tm.h [new file with mode: 0755]
gdb/param.h [new file with mode: 0755]
gdb/pn-opcode.h [new file with mode: 0755]
gdb/printcmd.c [new file with mode: 0644]
gdb/pyr-opcode.h [new file with mode: 0755]
gdb/pyr-pinsn.c [new file with mode: 0644]
gdb/pyr-tdep.c [new file with mode: 0644]
gdb/pyr-xdep.c [new file with mode: 0644]
gdb/regex.c [new file with mode: 0644]
gdb/regex.h [new file with mode: 0644]
gdb/remote-eb.c [new file with mode: 0644]
gdb/remote-multi.shar [new file with mode: 0755]
gdb/remote-nindy.c [new file with mode: 0644]
gdb/remote-sa.m68k.shar [new file with mode: 0755]
gdb/remote-vx.c [new file with mode: 0644]
gdb/remote.c [new file with mode: 0644]
gdb/saber.suppress [new file with mode: 0644]
gdb/signals.h [new file with mode: 0644]
gdb/signame.c [new file with mode: 0755]
gdb/signame.h [new file with mode: 0755]
gdb/solib.c [new file with mode: 0644]
gdb/source.c [new file with mode: 0644]
gdb/sparc-opcode.h [new file with mode: 0755]
gdb/sparc-pinsn.c [new file with mode: 0644]
gdb/sparc-tdep.c [new file with mode: 0644]
gdb/sparc-xdep.c [new file with mode: 0644]
gdb/stab.def [new file with mode: 0755]
gdb/stack.c [new file with mode: 0644]
gdb/standalone.c [new file with mode: 0644]
gdb/stddef.h [new file with mode: 0755]
gdb/stdlib.h [new file with mode: 0755]
gdb/stuff.c [new file with mode: 0644]
gdb/sun3-xdep.c [new file with mode: 0644]
gdb/sun386-xdep.c [new file with mode: 0644]
gdb/symfile.c [new file with mode: 0644]
gdb/symfile.h [new file with mode: 0644]
gdb/symmetry-tdep.c [new file with mode: 0755]
gdb/symmetry-xdep.c [new file with mode: 0755]
gdb/symmisc.c [new file with mode: 0644]
gdb/symtab.c [new file with mode: 0644]
gdb/symtab.h [new file with mode: 0644]
gdb/target.c [new file with mode: 0644]
gdb/target.h [new file with mode: 0644]
gdb/tdesc.c [new file with mode: 0755]
gdb/tdesc.h [new file with mode: 0755]
gdb/terminal.h [new file with mode: 0644]
gdb/tm-29k.h [new file with mode: 0644]
gdb/tm-3b1.h [new file with mode: 0644]
gdb/tm-68k.h [new file with mode: 0644]
gdb/tm-altos.h [new file with mode: 0644]
gdb/tm-altosgas.h [new file with mode: 0644]
gdb/tm-arm.h [new file with mode: 0644]
gdb/tm-bigmips.h [new file with mode: 0644]
gdb/tm-convex.h [new file with mode: 0644]
gdb/tm-hp300bsd.h [new file with mode: 0644]
gdb/tm-hp300hpux.h [new file with mode: 0644]
gdb/tm-i386v-g.h [new file with mode: 0644]
gdb/tm-i386v.h [new file with mode: 0644]
gdb/tm-i960.h [new file with mode: 0644]
gdb/tm-isi.h [new file with mode: 0644]
gdb/tm-m88k.h [new file with mode: 0644]
gdb/tm-merlin.h [new file with mode: 0644]
gdb/tm-mips.h [new file with mode: 0644]
gdb/tm-news.h [new file with mode: 0644]
gdb/tm-nindy960.h [new file with mode: 0644]
gdb/tm-np1.h [new file with mode: 0644]
gdb/tm-pn.h [new file with mode: 0644]
gdb/tm-pyr.h [new file with mode: 0644]
gdb/tm-sparc.h [new file with mode: 0644]
gdb/tm-sun2.h [new file with mode: 0644]
gdb/tm-sun2os4.h [new file with mode: 0644]
gdb/tm-sun3.h [new file with mode: 0644]
gdb/tm-sun386.h [new file with mode: 0644]
gdb/tm-sun3os4.h [new file with mode: 0644]
gdb/tm-sun4os4.h [new file with mode: 0644]
gdb/tm-sunos.h [new file with mode: 0644]
gdb/tm-symmetry.h [new file with mode: 0644]
gdb/tm-umax.h [new file with mode: 0644]
gdb/tm-vax.h [new file with mode: 0644]
gdb/tm-vxworks68.h [new file with mode: 0755]
gdb/tm-vxworks960.h [new file with mode: 0755]
gdb/umax-xdep.c [new file with mode: 0644]
gdb/utils.c [new file with mode: 0644]
gdb/valarith.c [new file with mode: 0644]
gdb/valops.c [new file with mode: 0644]
gdb/valprint.c [new file with mode: 0644]
gdb/value.h [new file with mode: 0644]
gdb/values.c [new file with mode: 0644]
gdb/vax-opcode.h [new file with mode: 0755]
gdb/vax-pinsn.c [new file with mode: 0644]
gdb/vx-share/dbgRpcLib.h [new file with mode: 0644]
gdb/vx-share/ptrace.h [new file with mode: 0644]
gdb/vx-share/reg.h [new file with mode: 0644]
gdb/vx-share/vxTypes.h [new file with mode: 0644]
gdb/vx-share/vxWorks.h [new file with mode: 0644]
gdb/vx-share/wait.h [new file with mode: 0644]
gdb/vx-share/xdr_ld.c [new file with mode: 0644]
gdb/vx-share/xdr_ld.h [new file with mode: 0644]
gdb/vx-share/xdr_ptrace.c [new file with mode: 0644]
gdb/vx-share/xdr_ptrace.h [new file with mode: 0644]
gdb/vx-share/xdr_rdb.c [new file with mode: 0644]
gdb/vx-share/xdr_rdb.h [new file with mode: 0644]
gdb/vx-share/xdr_regs.c [new file with mode: 0644]
gdb/vx-share/xdr_regs.h [new file with mode: 0644]
gdb/xm-3b1.h [new file with mode: 0644]
gdb/xm-altos.h [new file with mode: 0644]
gdb/xm-arm.h [new file with mode: 0644]
gdb/xm-bigmips.h [new file with mode: 0644]
gdb/xm-convex.h [new file with mode: 0644]
gdb/xm-hp300bsd.h [new file with mode: 0644]
gdb/xm-hp300hpux.h [new file with mode: 0644]
gdb/xm-i386v.h [new file with mode: 0644]
gdb/xm-i386v32.h [new file with mode: 0644]
gdb/xm-isi.h [new file with mode: 0644]
gdb/xm-m88k.h [new file with mode: 0644]
gdb/xm-merlin.h [new file with mode: 0644]
gdb/xm-mips.h [new file with mode: 0644]
gdb/xm-news.h [new file with mode: 0644]
gdb/xm-news1000.h [new file with mode: 0644]
gdb/xm-np1.h [new file with mode: 0644]
gdb/xm-pn.h [new file with mode: 0644]
gdb/xm-pyr.h [new file with mode: 0644]
gdb/xm-sparc.h [new file with mode: 0644]
gdb/xm-sun2.h [new file with mode: 0644]
gdb/xm-sun3.h [new file with mode: 0644]
gdb/xm-sun386.h [new file with mode: 0644]
gdb/xm-sun3os4.h [new file with mode: 0644]
gdb/xm-sun4os4.h [new file with mode: 0644]
gdb/xm-symmetry.h [new file with mode: 0644]
gdb/xm-umax.h [new file with mode: 0644]
gdb/xm-vax.h [new file with mode: 0644]
include/a.out.encap.h [new file with mode: 0755]
include/a.out.hp.h [new file with mode: 0755]
include/gdbm.h [new file with mode: 0644]
include/getopt.h [new file with mode: 0644]
include/ranlib.h [new file with mode: 0755]
include/stab.def [new file with mode: 0755]
include/stab.gnu.h [new file with mode: 0755]
ld/Makefile [new file with mode: 0755]
ld/config.h [new file with mode: 0644]
ld/ld-emul.c [new file with mode: 0755]
ld/ld-gld.c [new file with mode: 0755]
ld/ld-gld68k.c [new file with mode: 0755]
ld/ld-gld960.c [new file with mode: 0755]
ld/ld-lnk960.c [new file with mode: 0755]
ld/ld.tex [new file with mode: 0755]
ld/ldexp.h
ld/ldgram.y
ld/ldlang.c
ld/ldlex.l
ld/ldmain.c
ld/ldmisc.c
ld/ldsym.c [new file with mode: 0644]
ld/ldsym.h [new file with mode: 0644]
ld/ldwarn.h [new file with mode: 0644]
ld/ldwrite.c
readline/COPYING [new file with mode: 0644]
readline/ChangeLog [new file with mode: 0644]
readline/Makefile.in [new file with mode: 0644]
readline/chardefs.h [new file with mode: 0644]
readline/emacs_keymap.c [new file with mode: 0644]
readline/funmap.c [new file with mode: 0644]
readline/history.c [new file with mode: 0644]
readline/history.h [new file with mode: 0644]
readline/history.texinfo [new file with mode: 0755]
readline/inc-history.texinfo [new file with mode: 0755]
readline/inc-readline.texinfo [new file with mode: 0755]
readline/keymaps.c [new file with mode: 0644]
readline/keymaps.h [new file with mode: 0644]
readline/readline.c [new file with mode: 0644]
readline/readline.h [new file with mode: 0644]
readline/readline.texinfo [new file with mode: 0755]
readline/vi_keymap.c [new file with mode: 0644]
readline/vi_mode.c [new file with mode: 0644]

diff --git a/bfd/COPYING b/bfd/COPYING
new file mode 100644 (file)
index 0000000..9a17037
--- /dev/null
@@ -0,0 +1,249 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
new file mode 100644 (file)
index 0000000..e9d10f6
--- /dev/null
@@ -0,0 +1,314 @@
+Tue Mar  5 01:47:57 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * coff-code.h (bfd_coff_swap_sym, bfd_coff_swap_aux,
+       bfd_coff_swap_lineno):  Export the routines that byte-swap COFF
+       symbol tables if necessary when reading them in, so gdb can use
+       them.  Add "bfd_coff_" to the names so they won't conflict with
+       names in calling programs.  FIXME-soon:  if coff-code.h is
+       included in two BFD modules, this will cause duplicate
+       definitions; the routines should be exported to a separate,
+       common, module (probably along with a mess of other ones).
+
+Sat Mar  2 12:11:26 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Improve modtime support.
+
+       * bfd.h:  Add boolean mtime_set, and declare bfd_get_mtime.
+       Remove #define for bfd_get_mtime.  Remove gratuitous comment.
+       * bfd.c (bfd_get_mtime):  New fn, caches mtime, gets if not cached.
+       BUG:  archive members still do not get correct mod times.
+
+       Improve floating point support for core files.
+
+       * sunos.c (struct core):  Change void *fpa_dummy to double fp_stuff.
+       (sunos4_core_file_p):  Create a second registers section in the
+       core file, called ".reg2", for the float registers.
+
+Thu Feb 14 15:49:06 1991  Gumby Vinayak Wallace  (gumby at cygint.cygnus.com)
+
+       * many changes to improve archive handling; found a logic flaw in
+         bfd_check_format which only just happened to work by cooncidence.
+
+Thu Feb 14 07:53:16 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+
+       * bfd.c (bfd_perform_relocation): fixed to use output_offsets
+       correctly.
+       
+       * bfd.h: changed type of udata in asymbol to void *, like it
+       should be. Added bfd_reloc_dangerous enum member.
+
+       * coff-code.h: Fixed it so that internally generated symbols get
+       their values relocated correctly in all cases. Removed calls to
+       xmalloc.
+
+       * icoff.c: Not understanding the destination symbol of a reloc is
+       not a failure any more, just 'dangerous'. This allows linking of
+       b.out and coff images.
+
+       * sunos.c: Cleaned up the way that ZMAGIC section sizes are
+       calculated.
+
+
+Tue Feb 12 13:25:46 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+
+       * sunos.c (translate_to_native_sym_flags): fixed
+       sym_pointer->n_value so that symbols on the way out get their
+       section relative values calculated correctly.
+
+       * coff-code.h (mangle_symbols): fixed problem where tags were not
+       being relocated for structs, enums, unions. Also various lints.
+
+Mon Feb 11 19:52:26 1991  Gumby Vinayak Wallace  (gumby at cygint.cygnus.com)
+
+       * archive.c (get_elt_at_filepos): system_call_error returned
+         incorrectly.
+
+Sun Feb 10 23:18:40 1991  Gumby Vinayak Wallace  (gumby at cygint.cygnus.com)
+
+       * Resolve the use of no_error and system_call_error.
+         The bfd library itself now will never set bfd_error to
+         no_error.
+
+         The code still needs to be combed to make sure all the error
+         codes are correct.  I suspect they are not always set correctly.
+
+       * The names of all the messages have _ prepended because the sun
+         bundled compiler can't distinguish from a macro which takes an
+         argument and the same identifier in a non-macro context.
+
+       * The reason for the above being that entry points which used to
+         be trampoline functions are now just macros which expand to a
+         direct call through the bfd's xfer vector.
+
+       * (../include/intel-coff.h) F_AR32WR: fix this constant.  Why
+         must gas have its own version of everything (the gas version
+         had the correct value)
+
+Tue Feb  5 11:46:53 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+
+       * b.out.c: Added patches supplied by chrisb@mipon2.intel.com to
+       properly support i960 architecture and output correct reloc stuff.
+
+       * bfd.h: added prototype for bfd_printable_arch_mach, added
+       BFD_FAIL
+
+       * coff-code.h: Applied patches from chrisb to support i960
+       architecture, zero relocs and swap them correcly and conditionally
+       compiled the timestamp.
+
+       * sunos.c: Made the default section alignment 2^3 so that doubles
+       are done properly. Fixed the same reloc bug that was in b.out.c
+
+       * sysdep.h: Now compiles on a Posix box
+
+Wed Jan 30 21:36:26 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * icoff.c:  Fix comment on big-endian version.
+       * coff-code.h:  Make HAS_RELOC really work (it's backwards from
+       F_RELFLG).  Set F_AR32WR in output files if little endian
+       architecture.
+
+Tue Jan 29 20:56:10 PST 1991 steve@cygnus.com
+       
+       * archures.c fixed =/== typo
+       
+       * sunos.c added architecture stuff for output. Fixed
+       bug where files where vma(data) != size(text) 
+       were processed wrong.
+
+       * coff-code.h added a lint cast
+
+       * (../include/a.out.sun4.h) fixed it so zmagic
+       worked
+
+Mon Jan 28 19:15:29 PST 1991 steve@cygnus.com
+
+       * archive.c removed loads of includes, and fixed bug where string
+       table didn't have a null at the end.
+
+       * bfd.c fixed includes, added symbols argument to 
+       canonicalize_reloc entry point.
+
+       * libbfd.c fixed includes and added some lint patches.
+       
+       * targets.c added both sorts of intel coff.
+
+       * b.out.c fixed included, changed was the canonical
+       relocs were done.
+
+       * icoff.c added support for callj and big and little
+       enidian tables.
+
+       * opncls.c added chmod+xing for files with EXEC_P set.
+
+       * sunos.c fixed includes. Changed default section
+       alignement to words. Fixed relocation stuff to work with
+       new scheme
+
+       * bfd.h various new types added, prototype for new
+       reloc calls, changed bfd->iostream to a void *
+       to including files don't need stdio.h.
+
+       * libcoff.h added conversion table to tie relocs to
+       canonical symbols
+               
+       * sysdep.h created
+
+       * coff-code.h fixed includes. Added code to support
+       big and little endian formats. Various lints. Better
+       processing of symbols. Changed reloc stuff to new
+       order
+
+       * libbfd.h fixed includes
+
+
+Mon Jan 21 11:53:51 PST 1991 steve@cygnus.com
+       
+       * bfd.h changed name of alignment entry in sec_struct to
+       alignment_power, because of conflicting uses within bfd.
+       Now it should be obvious that it's a 2**n alignment
+       specifier. Removed start_pad, end_alignment, block, minsize,
+       output_file_alignment, subsection_alignment and original_vma fields.
+       Added align_power() macro. Fixed bfd_section_alignment
+       acessor macros. Added bfd_symbol_same_target macro.
+
+       * b.out.c (b_out_write_object_contents) fixed to use
+       new alignment member. Fixed (callj_callback) to use section
+       relative symbols properly.
+
+       * sunos.c (sunos4_object_p) fixed to use new alignment_power.
+       Fixed (translate_from_native_sym_flags) to correctly make       
+       symbols section relative.
+
+       * bfd.c (bfd_errmsg) fixed various enum cast problems. 
+       (bfd_make_section) took out initialization of obsolete members.
+       (bfd_print_symbol_vandf) added
+
+       * opncls.c (bfd_create) created.
+
+       * coff-code.h (coff_new_section_hook) took away refs
+       to obsolete members. (make_a_section_from_file) added
+       conversion between alignment types. (coff_symbol_from)
+       added. (coff_count_linenumbers) only counts linenumbers
+       if symbol is of coff-type. (coff_mangle_symbols) only
+       heavily mangles symbols if symbol is coff-type.
+       (coff_write_symbols) various lints. (coff_write_object_contents)
+       various lints and modification for alignment conversion.
+       (coff_slurp_relocs) fixed for use with new asection shape.
+
+Sat Jan 19 16:10:42 PST 1991 steve@cygnus.com
+
+       * archive.c lots of lint
+
+       * b.out.c added callj relocation support, upgrated reloc howto.
+       Fixed so that asymbol and reloc records are output 
+       correctly.
+
+       * bfd.c lots of lint, support for new bfd entry point
+       bfd_print_symbol.
+
+       * bfd.h changed definition of asymbol to contain pointer to
+       owning bfd, removed target dependencies.
+
+       * cache.c took out print statements, put in BFD_ASSERT calls.
+
+       * coff-code.h various lints, corrected linenumber output
+       functionality. Added support for new style asymbols and
+       bfd_print_symbol. Fixed so that asymbol and
+       reloc records are handled correctly. Added timestamp.
+
+       * icoff.c Added support for new howto shape.
+       
+       * liba.out.h Added support for new asymbol shape
+
+       * libbfd.c various lints
+
+       * libbfd.h various lints
+
+       * libcoff.h added support for new asymbol shape.
+
+       * sunos.c  various lints. Added support for new asymbol shape
+       and bfd_print_symbol.
+
+Wed Jan 16 21:38:09 PST 1991 steve@cygnus.com
+
+       * b.out.c removed prototype of sunos4_ennativate_symtab, lots of
+       pointer lint. Added support for callj relocation. Fixed bug where
+       the last 32 bytes of the text section were overwritten by data. Fixed bug
+       where archives of b.out didn't work due bfd_slurp_extended_name_table
+       returning false.
+
+       * sunos.c added support for n_other field. Braced the howto table so
+       that it won't be affected by any lengthing of the howto struct typedef.
+       Various lints
+
+       * bfd.h added support for n_other field, added special_function         
+       reloc type, modified bfd_perform_relocation prototype. Added bfd_h_get_x
+       macros.
+
+       * bfd.c upgraded bfd_perform_relocation, various lints.
+
+Wed Jan 16 01:55:53 1991  John Gilmore  (gnu at rtl)
+
+       * ChangeLog:  Started ChangeLog for BFD.
+       * ToDo:  Create file for suggestions.
+
+       * Makefile:  Support easy loading into Saber C.
+       Add dependencies for icoff.o and bcs88kcoff.o.
+       Rename coff.c to coff-code.h.  Change callers.
+
+       * bfd.c (bfd_check_format):  Allow the check_format routines
+       to return the desired target vector, rather than just a Boolean.
+       bfd.h (bfd_check_format):  Change function pointer return type.
+       archive.c (bfd_generic_archive_p):  change callee.
+       b.out.c (b_out_little_object_p, b_out_big_object_p,
+       b_out_real_object_p):  change callee.
+       libbfd.c (_bfd_dummy_target):  Dummy routine replacing bfd_false
+       in check_format transfer vectors that need a filler.
+       libbfd.h (bfd_generic_archive_p, _bfd_dummy_target):  Fix decls.
+       bcs88kcoff.c:  change callee.
+       coff-code.h (coff_real_object_p, coff_big_object_p):  change callee.
+       icoff.c:  change callee.
+       sunos.c (sunos4_object_p, sunos4_core_file_p):  change callee.
+
+       * libbfd.c (zalloc):  It should actually zero the storage!
+       This was commented out for some reason.
+
+       * libbfd.h:  Add malloc, xmalloc, memcpy, and fatal decls.
+       This is so callers can avoid <stdlib.h> which doesn't exist
+       on older systems.
+
+       * bfd.c (map_over_sections):  Add debugging code, since I
+       noticed the section count for sunos core files was bad, but only
+       GDB had detected the problem.
+       (bfd_set_section_lineno_size, bfd_set_section_linenos,
+       bfd_get_section_linenos):  Remove obsolete functions.
+       (bfd_apply_relocations):  Use longs, not ints, for the math.
+
+       * bfd.h:  Declare enum boolean and struct bfd_target as well
+       as typedefs for them.  Remove obsolete
+       bfd_get_section_lineno_size.
+
+       * cache.c:  Make the "fdopen" support work.  Keep better track
+       of how many files are open.  Centralize the opening of files
+       and be sure bfd_open[rw] actually try to open the file.  Evade
+       linked list initialization problems.
+
+       * b.out.c, coff-code.h, opncls.c, sunos.c:  lint.
+
+       * coff-code.h (coff_slurp_symbol_table):  Null-terminate symtab names.
+
+       * cplus-dem.c:  Delete file, since it is not part of BFD.
+
+       * opncls.c (bfd_openr):  Eliminate misplaced #if 0 code.
+       (bfd_openr, bfd_openw):  Actually open the file, give error now.
+       
+       * sunos.c (sunos4_core_file_p):  Set section count.
+       (sunos4_set_section_linenos, stab_names, fprint_name):  Eliminiate
+       obsolete definitions.
+       (_write_symbol_table):  Initialize <idx> counter.
+       (foop):  Eliminate debugging code.
+
+
+
+
diff --git a/bfd/Makefile b/bfd/Makefile
new file mode 100755 (executable)
index 0000000..b20e954
--- /dev/null
@@ -0,0 +1,149 @@
+#
+# Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+#
+# This file is part of BFD, the Binary File Diddler.
+#
+# BFD 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 1, or (at your option)
+# any later version.
+#
+# BFD 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 BFD; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+# $Id$
+
+srcdir=../common
+VPATH=../common
+RANLIB = ranlib
+CSWITCHES = -g  # -Wall
+CC=gcc -Wall
+#__sun4__#CDEFINES=-DHOST_SYS=SUN4_SYS
+#__sun3__#CDEFINES=-DHOST_SYS=SUN3_SYS
+#__dgux__#CDEFINES=-DHOST_SYS=DGUX_SYS
+#__dgux__#RANLIB=echo 
+INCDIR = ${srcdir}/../../include-cygnus
+CSEARCH = -I$(INCDIR)
+
+TARG = libbfd.a
+CFLAGS = $(CDEFINES) $(CSEARCH) $(CSWITCHES) 
+
+
+BFD_LIBS = libbfd.o opncls.o bfd.o archive.o targets.o cache.o archures.o obstack.o
+
+BFD_BACKENDS = oasys.o ieee.o srec.o  sunos.o icoff.o b.out.o m88k-bcs.o
+
+BFD_H=$(INCDIR)/bfd.h
+SYSDEP_H=$(INCDIR)/sysdep.h
+
+# C source files that correspond to .o's.
+CFILES = libbfd.c opncls.c bfd.c archive.c targets.c cache.c archures.c \
+        sunos.c icoff.c b.out.c  srec.c oasys.c ieee.c m88k-bcs.c
+
+all: $(TARG) 
+
+POINTOS = $(BFD_LIBS) $(BFD_BACKENDS)
+
+$(TARG): $(POINTOS)
+        rm -f $(TARG)
+        ar clq $(TARG) $(BFD_LIBS) $(BFD_BACKENDS)
+        $(RANLIB) $(TARG)
+
+tags etags: TAGS
+
+TAGS: .force
+       etags $(INCDIR)/*.h *.h *.c
+
+clean:
+       rm -f $(BFD_LIBS) $(BFD_BACKENDS) *~ core libbfd.a
+
+clobber realclean: clean
+       rm -f libbfd.a TAGS
+
+$(BFD_LIBS) $(BFD_BACKENDS):  libbfd.h $(BFD_H)
+
+archive.o : archive.c libbfd.h $(BFD_H) $(SYSDEP_H)  
+archures.o : archures.c $(BFD_H) $(SYSDEP_H) archures.h 
+b.out.o : b.out.c libbfd.h $(BFD_H) $(SYSDEP_H) liba.out.h archures.h 
+m88k-bcs.o: m88k-bcs.c libbfd.h $(BFD_H) $(SYSDEP_H) libcoff.h coff-code.h archures.h 
+bfd.o : bfd.c libbfd.h $(BFD_H) $(SYSDEP_H)     
+cache.o : cache.c libbfd.h $(BFD_H) $(SYSDEP_H)     
+coff.o : coff.c  
+cplus-dem.o : cplus-dem.c  
+filemode.o : filemode.c 
+icoff.o : icoff.c libbfd.h $(BFD_H) $(SYSDEP_H) libcoff.h coff-code.h archures.h 
+libbfd.o : libbfd.c libbfd.h $(BFD_H) $(SYSDEP_H)      
+misc.o : misc.c 
+opncls.o : opncls.c libbfd.h $(BFD_H) $(SYSDEP_H)     
+sunos.o : sunos.c libbfd.h $(BFD_H) $(SYSDEP_H) liba.out.h
+targets.o : targets.c libbfd.h $(BFD_H) $(SYSDEP_H)      
+obstack.o:obstack.c
+ieee.o:ieee.c
+oasys.o:oasys.c
+srec.o:srec.c
+
+
+
+version.c: FORCE
+       rm -f version.c
+       echo "char ${TARG}_ver[]= \"${TARG} `cat VERSION`, `date`\";" > version.c
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+       @V=`cat VERSION`                ; \
+       MAJ=`sed 's/\..*//' VERSION`    ; \
+       MIN=`sed 's/.*\.//' VERSION`    ; \
+       V=$$MAJ.`expr $$MIN + 1`        ; \
+       rm -f VERSION                   ; \
+       echo $$V >VERSION               ; \
+       echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+.force:
+FORCE:
+
+# 'G960BASE' will be defined at invocation
+install:
+       make ${TARG} OPT=-O
+
+# Target to uncomment host-specific lines in this makefile.  Such lines must
+# have the following string beginning in column 1: #__<hostname>__#
+# Original Makefile is backed up as 'Makefile.old'.
+#
+# Invoke with:  make make HOST=xxx
+#
+make:
+       -@if test $(HOST)x = x ; then \
+               echo '\aSpecify "make make HOST=???"'; \
+               exit 1; \
+       fi ; \
+       grep -s "^#The next line was generated by 'make make'" Makefile; \
+       if test $$? = 0 ; then  \
+               echo "\aMakefile has already been processed with 'make make'";\
+               exit 1; \
+       fi ; \
+       mv -f Makefile Makefile.old; \
+       echo "# " >Makefile ;\
+       echo "# " >>Makefile  ;\
+       echo "#   D A N G E R"  >>Makefile ;\
+       echo "# " >>Makefile ;\
+       echo "#   This file was created by make make, change the source in ../common" >>Makefile ; \
+       echo "#The next line was generated by 'make make'"       >>Makefile ; \
+       echo "HOST=$(HOST)"                                     >>Makefile ; \
+       echo                                                    >>Makefile ; \
+       sed "s/^#__$(HOST)__#//" < Makefile.old                 >>Makefile
+
+Makefile: ../common/Makefile
+       mv Makefile Makefile.backup
+       cp ../common/Makefile .
+       $(MAKE) "HOST=$(HOST)" make
diff --git a/bfd/TODO b/bfd/TODO
new file mode 100644 (file)
index 0000000..45cf905
--- /dev/null
+++ b/bfd/TODO
@@ -0,0 +1,49 @@
+Things that still need to be handled: -*- Text -*-
+
+ o - check all the swapping code.
+ o - change the memory usage to reflect the message which follows the
+     page break.
+ o - implement bfd_abort, which should close the bfd but not alter the
+     filesystem.
+ o - remove the following obsolete functions:
+        bfd_symbol_value
+        bfd_symbol_name
+        bfd_get_first_symbol
+        bfd_get_next_symbol
+        bfd_classify_symbol
+        bfd_symbol_hasclass
+ o - update the bfd doc; write a how-to-write-a-backend doc.
+ o - change reloc handling as per Steve's suggestion.
+
+\f
+Changing the way bfd uses memory.  The new convention is simple: 
+
+ o - bfd will never write into user-supplied memory, nor attempt to
+     free it.
+ o - closing a bfd may reclaim all bfd-allocated memory associated
+     with that bfd.
+ - - bfd_target_list will be the one exception; you must reclaim the
+     returned vector yourself.
+
+Interface implications are minor (get_symcount_upper_bound will go
+away; bfd_cannicalize_symtab will allocate its own memory, etc).
+
+Certain operations consume a lot of memory; for them manual
+reclaimation is available:
+
+ o - bfd_canonicalize_symtab will return a pointer to a
+     null-terminated vector of symbols.  Subsequent calls may or may
+     not return the same pointer.
+     bfd_canonicalize_relocs will do the same; returning a pointer to
+     an array of arelocs.  Calling this function will read symbols in
+     too.
+
+ o - bfd_reclaim_relocs will free the memory used by these relocs.
+     the symbols will be untouched.
+     bfd_reclaim_symtab (ne bfd_reclaim_symbol_table) will free the
+     memory allocated by canonialize_symtab.  
+     Since relocations point to symbols, any relocations obtained by a
+     call to bfd_canonicalize_relocs will be reclaimed as well.
+
+ o - if you don't call the reclaim_ functions, the memory will be
+     reclaimed at bfd_close time.
diff --git a/bfd/VERSION b/bfd/VERSION
new file mode 100644 (file)
index 0000000..ba66466
--- /dev/null
@@ -0,0 +1 @@
+0.0
diff --git a/bfd/aout.c b/bfd/aout.c
new file mode 100755 (executable)
index 0000000..9b554b6
--- /dev/null
@@ -0,0 +1,2119 @@
+/*** bfd backend for sunos binaries */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$
+ *
+ */
+
+#define TARGET_BYTE_ORDER_BIG_P 1
+
+#include <ansidecl.h>
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+void (*bfd_error_trap)();
+/*SUPPRESS558*/
+/*SUPPRESS529*/
+
+
+
+
+typedef void generic_symbol_type;
+/* These values are correct for the SPARC.  I dunno about anything else */
+#define PAGE_SIZE 0x02000
+#define SEGMENT_SIZE PAGE_SIZE
+#define TEXT_START_ADDR PAGE_SIZE
+#include "a.out.gnu.h"
+#include "stab.gnu.h"
+#include "ar.h"
+#include "liba.out.h"           /* BFD a.out internal data structures */
+
+#include "a.out.sun4.h"
+
+#define CTOR_TABLE_RELOC_IDX 2
+static CONST reloc_howto_type howto_table_ext[] = 
+{
+  /* type                   rs   size bsz  pcrel bitpos  abs ovrf sf name partial inplace mask*/
+{ (unsigned int) RELOC_8,      0,  0,          8,  false, 0, true,  true,0,"8",        false, 0x000000ff},
+{ (unsigned int) RELOC_16,     0,  1,  16, false, 0, true,  true,0,"16",       false, 0x0000ffff},
+{ (unsigned int) RELOC_32,     0,  2,  32, false, 0, true,  true,0,"32",       false,  0xffffffff},
+{ (unsigned int) RELOC_DISP8,  0,  0,  8,  true,  0, false, true,0,"DISP8",    false, 0x000000ff},
+{ (unsigned int) RELOC_DISP16, 0,  1,  16, true,  0, false, true,0,"DISP16",   false, 0x0000ffff},
+{ (unsigned int) RELOC_DISP32, 0,  2,  32, true,  0, false, true,0,"DISP32",   false, 0xffffffff},
+{ (unsigned int) RELOC_WDISP30,2,  2,  30, true,  0, false, true,0,"WDISP30",  false, 0x3fffffff},
+{ (unsigned int) RELOC_WDISP22,2,  2,  22, true,  0, false, true,0,"WDISP22",  false, 0x003fffff},
+{ (unsigned int) RELOC_HI22,   10, 2,  22, false, 0, false, true,0,"HI22",     false, 0x003fffff},
+{ (unsigned int) RELOC_22,      0, 2,  22, false, 0, false, true,0,"22",       false, 0x003fffff},
+{ (unsigned int) RELOC_13,     0, 2,   13, false, 0, false, true,0,"13",       false, 0x00001fff},
+{ (unsigned int) RELOC_LO10,   0, 2,   10, false, 0, false, true,0,"LO10",     false, 0x000003ff},
+{ (unsigned int) RELOC_SFA_BASE,0, 2,  32, false, 0, false, true,0,"SFA_BASE", false, 0xffffffff},
+{ (unsigned int) RELOC_SFA_OFF13,0,2,  32, false, 0, false, true,0,"SFA_OFF13",false, 0xffffffff},
+{ (unsigned int) RELOC_BASE10, 0,  2,  16, false, 0, false, true,0,"BASE10",   false, 0x0000ffff},
+{ (unsigned int) RELOC_BASE13, 0,  2,  13, false, 0, false, true,0,"BASE13",   false, 0x00001fff},
+{ (unsigned int) RELOC_BASE22, 0,  2,  0,  false, 0, false, true,0,"BASE22",   false, 0x00000000},
+{ (unsigned int) RELOC_PC10,   0,  2,  10, false, 0, false, true,0,"PC10",     false, 0x000003ff},
+{ (unsigned int) RELOC_PC22,   0,  2,  22, false, 0, false, true,0,"PC22",     false, 0x003fffff},
+{ (unsigned int) RELOC_JMP_TBL,0,  2,  32, false, 0, false, true,0,"JMP_TBL",  false, 0xffffffff},
+{ (unsigned int) RELOC_SEGOFF16,0, 2,  0,  false, 0, false, true,0,"SEGOFF16", false, 0x00000000},
+{ (unsigned int) RELOC_GLOB_DAT,0, 2,  0,  false, 0, false, true,0,"GLOB_DAT", false, 0x00000000},
+{ (unsigned int) RELOC_JMP_SLOT,0, 2,  0,  false, 0, false, true,0,"JMP_SLOT", false, 0x00000000},
+{ (unsigned int) RELOC_RELATIVE,0, 2,  0,  false, 0, false, true,0,"RELATIVE", false, 0x00000000},
+{ (unsigned int) RELOC_JUMPTARG,2, 13, 16, true,  0, false, true,0,"JUMPTARG", false, 0x0000ffff},
+{ (unsigned int) RELOC_CONST,  0, 13,  16, false, 0, false, true,0,"CONST",    false, 0x0000ffff},
+{ (unsigned int) RELOC_CONSTH, 16, 13, 16, false, 0, false, true,0,"CONSTH",   false, 0x0000ffff},
+};
+
+/* Convert standard reloc records to "arelent" format (incl byte swap).  */
+
+static CONST reloc_howto_type howto_table_std[] = {
+  /* type                   rs   size bsz  pcrel bitpos  abs ovrf sf name*/
+{ (unsigned int) 0,           0,  0,   8,  false, 0, true,  true,0,"8",        true, 0x000000ff},
+{ (unsigned int) 1,           0,  1,   16, false, 0, true,  true,0,"16",       true, 0x0000ffff},
+{ (unsigned int) 2,           0,  2,   32, false, 0, true,  true,0,"32",       true, 0xffffffff},
+{ (unsigned int) 3,           0,  3,   64, false, 0, true,  true,0,"64",       true, 0xdeaddead},
+{ (unsigned int) 4,           0,  0,   8,  true,  0, false, true,0,"DISP8",    true, 0x000000ff},
+{ (unsigned int) 5,           0,  1,   16, true,  0, false, true,0,"DISP16",   true, 0x0000ffff},
+{ (unsigned int) 6,           0,  2,   32, true,  0, false, true,0,"DISP32",   true, 0xffffffff},
+{ (unsigned int) 7,           0,  3,   64, true,  0, false, true,0,"DISP64",   true, 0xfeedface},
+};
+
+/** a.out files */
+
+
+PROTO (void , sunos4_write_syms, ());
+PROTO (static boolean,sunos4_squirt_out_relocs,(bfd *abfd, asection *section));
+
+
+static size_t
+reloc_size_func(abfd)
+bfd *abfd;
+{
+  switch (bfd_get_architecture (abfd)) {
+  case bfd_arch_sparc:
+  case bfd_arch_a29k:
+    return  RELOC_EXT_SIZE;
+  default:
+    return  RELOC_STD_SIZE;
+  }
+}
+
+void
+bfd_aout_swap_exec_header_in (abfd, raw_bytes, execp)
+     bfd *abfd;
+     unsigned char *raw_bytes;
+     struct exec *execp;
+{
+  struct exec_bytes *bytes = (struct exec_bytes *)raw_bytes;
+
+  /* Now fill in fields in the execp, from the bytes in the raw data.  */
+  execp->a_info   = bfd_h_getlong (abfd, bytes->a_info);
+  execp->a_text   = bfd_h_getlong (abfd, bytes->a_text);
+  execp->a_data   = bfd_h_getlong (abfd, bytes->a_data);
+  execp->a_bss    = bfd_h_getlong (abfd, bytes->a_bss);
+  execp->a_syms   = bfd_h_getlong (abfd, bytes->a_syms);
+  execp->a_entry  = bfd_h_getlong (abfd, bytes->a_entry);
+  execp->a_trsize = bfd_h_getlong (abfd, bytes->a_trsize);
+  execp->a_drsize = bfd_h_getlong (abfd, bytes->a_drsize);
+}
+
+void
+bfd_aout_swap_exec_header_out (abfd, execp, raw_bytes)
+     bfd *abfd;
+     struct exec *execp;
+     unsigned char *raw_bytes;
+{
+  struct exec_bytes *bytes = (struct exec_bytes *)raw_bytes;
+
+  /* Now fill in fields in the raw data, from the fields in the exec struct. */
+  bfd_h_putlong (abfd, execp->a_info  , bytes->a_info);
+  bfd_h_putlong (abfd, execp->a_text  , bytes->a_text);
+  bfd_h_putlong (abfd, execp->a_data  , bytes->a_data);
+  bfd_h_putlong (abfd, execp->a_bss   , bytes->a_bss);
+  bfd_h_putlong (abfd, execp->a_syms  , bytes->a_syms);
+  bfd_h_putlong (abfd, execp->a_entry , bytes->a_entry);
+  bfd_h_putlong (abfd, execp->a_trsize, bytes->a_trsize);
+  bfd_h_putlong (abfd, execp->a_drsize, bytes->a_drsize);
+}
+
+/* Steve wants some way to frob this stuff from Saber while he's debugging
+   ld, so we have these funny shadow functions */
+/* ZMAGIC's start at 0 (making the exec part of the text section),
+  other formats start after the exec
+*/
+static unsigned int n_txtoff(ptr)
+struct exec *ptr;
+{return N_MAGIC(*ptr)== ZMAGIC ? 0: sizeof(struct exec);}
+
+static unsigned int n_datoff(ptr)
+struct exec *ptr;
+{return n_txtoff(ptr) + ptr->a_text;}
+
+static unsigned int n_treloff(ptr)
+struct exec *ptr;
+{return n_datoff(ptr) + ptr->a_data;}
+
+static unsigned int n_dreloff(ptr)
+struct exec *ptr;
+{return n_treloff(ptr) + ptr->a_trsize;}
+
+static unsigned int n_symoff(ptr)
+struct exec *ptr;
+{return n_dreloff(ptr) + ptr->a_drsize;}
+
+static unsigned int n_stroff(ptr)
+struct exec *ptr;
+{return n_symoff(ptr) + ptr->a_syms;}
+
+unsigned int n_badmag(ptr)
+     struct exec *ptr;
+{
+  switch (N_MAGIC(*ptr)) {
+  case OMAGIC: case NMAGIC: case ZMAGIC: return 0;
+  default: return 1;
+  }
+}
+
+bfd_target *
+sunos4_object_p (abfd)
+     bfd *abfd;
+{
+  unsigned char magicbuf[4];   /* Raw bytes of magic number from file */
+  unsigned long magic;         /* Swapped magic number */
+  unsigned char exec_bytes[EXEC_BYTES_SIZE];   /* Raw bytes of exec hdr */
+  struct exec *execp;
+  void *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)magicbuf, 1, sizeof (magicbuf), abfd) !=
+      sizeof (magicbuf))
+    return 0;
+  magic = bfd_h_getlong (abfd, magicbuf);
+
+  /* Baroque syntax to mask deficiencies of the Sun compiler */
+  /* if (N_BADMAG (*((struct exec *) &magic))) return 0; */
+  if (n_badmag ((struct exec *) &magic)) return 0;
+
+  if (bfd_seek (abfd, 0L, false) < 0) return 0;
+
+  if (bfd_read ((void *) exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+      != EXEC_BYTES_SIZE) {
+    bfd_error = wrong_format;
+    return 0;
+  }
+
+  /* Use an intermediate variable for clarity */
+  rawptr = (void *) zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  set_tdata (abfd, ((struct sunexdata *) rawptr));
+  exec_hdr (abfd) = execp =
+    (struct exec *) ((char *)rawptr + sizeof (struct sunexdata));
+
+  bfd_aout_swap_exec_header_in (abfd, exec_bytes, execp);
+
+  /* Set the file flags */
+  abfd->flags = NO_FLAGS;
+  if (execp->a_drsize || execp->a_trsize)
+    abfd->flags |= HAS_RELOC;
+  if (execp->a_entry) 
+    abfd->flags |= EXEC_P;
+  if (execp->a_syms) 
+    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+
+  if (N_MAGIC (*execp) == ZMAGIC) abfd->flags |= D_PAGED;
+  if (N_MAGIC (*execp) == NMAGIC) abfd->flags |= WP_TEXT;
+
+  /* Determine the architecture and machine type of the object file.  */
+  abfd->obj_arch = bfd_arch_unknown;   /* Default values */
+  abfd->obj_machine = 0;
+  switch (N_MACHTYPE (*execp)) {
+
+  case M_UNKNOWN:
+       break;
+
+  case M_68010:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68010;
+       break;
+
+  case M_68020:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68020;
+       break;
+
+  case M_SPARC:
+       abfd->obj_arch = bfd_arch_sparc;
+       break;
+
+  case M_386:
+       abfd->obj_arch = bfd_arch_i386;
+       break;
+
+  case M_29K:
+       abfd->obj_arch = bfd_arch_a29k;
+       break;
+
+  default:
+       abfd->obj_arch = bfd_arch_obscure;
+       break;
+  }
+
+  bfd_get_start_address (abfd) = execp->a_entry;
+
+  /* Remember the positions of the string table and symbol table.  */
+  obj_str_filepos (abfd) = n_stroff (execp);
+  obj_sym_filepos (abfd) = n_symoff (execp);
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  obj_aout_symbols(abfd) = (aout_symbol_type *)NULL;
+  (void)bfd_make_section(abfd, ".text");
+  (void)bfd_make_section(abfd, ".data");
+  (void)bfd_make_section(abfd, ".bss");
+
+  obj_datasec (abfd)->size = execp->a_data;
+  obj_bsssec (abfd)->size = execp->a_bss;
+  obj_textsec (abfd)->size = execp->a_text;
+  obj_datasec (abfd)->vma = N_DATADDR(*execp);
+  obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
+  obj_textsec (abfd)->vma = N_TXTADDR(*execp);
+
+  obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
+  obj_datasec (abfd)->filepos = N_DATOFF(*execp);
+
+  obj_textsec (abfd)->rel_filepos = N_TROFF(*execp);
+  obj_datasec (abfd)->rel_filepos = N_DROFF(*execp);
+
+  obj_textsec (abfd)->flags = (execp->a_trsize != 0 ?
+                               (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
+                               (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
+  obj_datasec (abfd)->flags = (execp->a_drsize != 0 ?
+                               (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
+                               (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
+  obj_bsssec (abfd)->flags = SEC_ALLOC;
+
+  abfd->sections = obj_textsec (abfd);
+  obj_textsec (abfd)->next = obj_datasec (abfd);
+  obj_datasec (abfd)->next = obj_bsssec (abfd);
+  return abfd->xvec;
+}
+
+
+boolean
+sunos4_mkobject (abfd)
+     bfd *abfd;
+{
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  /* Use an intermediate variable for clarity */
+  rawptr =  zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  abfd->tdata = (void *)((struct sunexdata *) rawptr);
+  exec_hdr (abfd) = (struct exec *) (rawptr + sizeof (struct sunexdata));
+
+  /* For simplicity's sake we just make all the sections right here. */
+
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  bfd_make_section (abfd, ".text");
+  bfd_make_section (abfd, ".data");
+  bfd_make_section (abfd, ".bss");
+
+  return true;
+}
+
+/* Keep track of machine architecture and machine type for a.out's.
+   Return the machine_type for a particular arch&machine, or M_UNKNOWN
+   if that exact arch&machine can't be represented in a.out format.
+
+   If the architecture is understood, machine type 0 (default) should
+   always be understood.  */
+
+static enum machine_type
+aout_machine_type (arch, machine)
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  enum machine_type arch_flags;
+
+  arch_flags = M_UNKNOWN;
+
+  switch (arch) {
+  case bfd_arch_sparc:
+       if (machine == 0)       arch_flags = M_SPARC;
+       break;
+
+  case bfd_arch_m68k:
+       switch (machine) {
+       case 0:                 arch_flags = M_UNKNOWN; break;
+       case 68000:             arch_flags = M_UNKNOWN; break;
+       case 68010:             arch_flags = M_68010; break;
+       case 68020:             arch_flags = M_68020; break;
+       default:                arch_flags = M_UNKNOWN; break;
+       }
+       break;
+
+  case bfd_arch_i386:
+       if (machine == 0)       arch_flags = M_386;
+       break;
+
+  case bfd_arch_a29k:
+       if (machine == 0)       arch_flags = M_29K;
+       break;
+
+  default:
+       arch_flags = M_UNKNOWN;
+       break;
+  }
+  return arch_flags;
+}
+
+boolean
+sunos4_set_arch_mach (abfd, arch, machine)
+     bfd *abfd;
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  if (arch != bfd_arch_unknown &&
+      aout_machine_type (arch, machine) == M_UNKNOWN)
+    return false;              /* We can't represent this type */
+  return true;                 /* We're easy ... */
+}
+
+boolean
+sunos4_write_object_contents (abfd)
+     bfd *abfd;
+{
+  unsigned int data_pad = 0;
+  unsigned char exec_bytes[EXEC_BYTES_SIZE];
+  struct exec *execp = exec_hdr (abfd);
+
+  execp->a_text = obj_textsec (abfd)->size;
+
+  /* Magic number, maestro, please!  */
+  switch (bfd_get_architecture(abfd)) {
+  case bfd_arch_m68k:
+    switch (bfd_get_machine(abfd)) {
+    case 68010:
+      N_SET_MACHTYPE(*execp, M_68010);
+      break;
+    default:
+    case 68020:
+      N_SET_MACHTYPE(*execp, M_68020);
+      break;
+    }
+    break;
+  case bfd_arch_sparc:
+    N_SET_MACHTYPE(*execp, M_SPARC);
+    break;
+  case bfd_arch_i386:
+    N_SET_MACHTYPE(*execp, M_386);
+    break;
+  case bfd_arch_a29k:
+    N_SET_MACHTYPE(*execp, M_29K);
+    break;
+  default:
+    N_SET_MACHTYPE(*execp, M_UNKNOWN);
+  }
+
+  N_SET_MAGIC (*execp, OMAGIC);
+  if (abfd->flags & D_PAGED) {
+    execp->a_text = obj_textsec (abfd)->size + sizeof(struct exec);
+    N_SET_MAGIC (*execp, ZMAGIC);
+  } else if (abfd->flags & WP_TEXT) {
+    N_SET_MAGIC (*execp, NMAGIC);
+  }
+  N_SET_FLAGS (*execp, 0x1);   /* copied from ld.c; who the hell knows? */
+
+  if (abfd->flags & D_PAGED) 
+    {
+      data_pad = ((obj_datasec(abfd)->size + PAGE_SIZE -1)
+                 & (- PAGE_SIZE)) - obj_datasec(abfd)->size;
+
+      if (data_pad > obj_bsssec(abfd)->size)
+       execp->a_bss = 0;
+      else 
+       execp->a_bss = obj_bsssec(abfd)->size - data_pad;
+      execp->a_data = obj_datasec(abfd)->size + data_pad;
+
+    }
+  else {
+    execp->a_data = obj_datasec (abfd)->size;
+    execp->a_bss = obj_bsssec (abfd)->size;
+  }
+
+  execp->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
+  execp->a_entry = bfd_get_start_address (abfd);
+
+  execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
+                    reloc_size_func(abfd));
+                      
+  execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
+                    reloc_size_func(abfd));
+
+  bfd_aout_swap_exec_header_out (abfd, execp, exec_bytes);
+
+  bfd_seek (abfd, 0L, false);
+  bfd_write ((void *) exec_bytes, 1, EXEC_BYTES_SIZE, abfd);
+
+  /* Now write out reloc info, followed by syms and strings */
+
+  if (bfd_get_symcount (abfd) != 0) 
+    {
+      bfd_seek (abfd,
+               (long)(N_SYMOFF(*execp)), false);
+
+      sunos4_write_syms (abfd);
+
+      bfd_seek (abfd,  (long)(N_TROFF(*execp)), false);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
+      bfd_seek (abfd, (long)(N_DROFF(*execp)), false);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
+    }
+  return true;
+}
+
+/** core files */
+/** core files */
+
+#define CORE_MAGIC 0x080456
+#define CORE_NAMELEN 16
+
+/* The core structure is taken from the Sun documentation.
+   Unfortunately, they don't document the FPA structure, or at least I
+   can't find it easily.  Fortunately the core header contains its own
+   length.  So this shouldn't cause problems, except for c_ucode, which
+   so far we don't use but is easy to find with a little arithmetic. */
+
+/* But the reg structure can be gotten from the SPARC processor handbook.
+   This really should be in a GNU include file though so that gdb can use
+   the same info. */
+struct regs {
+  int r_psr;
+  int r_pc;
+  int r_npc;
+  int r_y;
+  int r_g1;
+  int r_g2;
+  int r_g3;
+  int r_g4;
+  int r_g5;
+  int r_g6;
+  int r_g7;
+  int r_o0;
+  int r_o1;
+  int r_o2;
+  int r_o3;
+  int r_o4;
+  int r_o5;
+  int r_o6;
+  int r_o7;
+};
+
+/* Taken from Sun documentation: */
+
+/* FIXME:  It's worse than we expect.  This struct contains TWO substructs
+   neither of whose size we know, WITH STUFF IN BETWEEN THEM!  We can't
+   even portably access the stuff in between!  */
+
+struct core {
+  int c_magic;                 /* Corefile magic number */
+  int c_len;                   /* Sizeof (struct core) */
+  struct regs c_regs;          /* General purpose registers */
+  struct exec c_aouthdr;       /* A.out header */
+  int c_signo;                 /* Killing signal, if any */
+  int c_tsize;                 /* Text size (bytes) */
+  int c_dsize;                 /* Data size (bytes) */
+  int c_ssize;                 /* Stack size (bytes) */
+  char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+  double fp_stuff[1];          /* external FPU state (size unknown by us) */
+               /* The type "double" is critical here, for alignment.
+                  SunOS declares a struct here, but the struct's alignment
+                  is double since it contains doubles.  */
+  int c_ucode;                 /* Exception no. from u_code */
+               /* (this member is not accessible by name since we don't
+                   portably know the size of fp_stuff.) */
+};
+
+/* Supposedly the user stack grows downward from the bottom of kernel memory.
+   Presuming that this remains true, this definition will work. */
+#define USRSTACK (-(128*1024*1024))
+
+PROTO (static void, swapcore, (bfd *abfd, struct core *core));
+
+/* need this cast b/c ptr is really void * */
+#define core_hdr(bfd) (((struct suncordata *) (bfd->tdata))->hdr)
+#define core_datasec(bfd) (((struct suncordata *) ((bfd)->tdata))->data_section)
+#define core_stacksec(bfd) (((struct suncordata*)((bfd)->tdata))->stack_section)
+#define core_regsec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg_section)
+#define core_reg2sec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg2_section)
+
+/* These are stored in the bfd's tdata */
+struct suncordata {
+  struct core *hdr;             /* core file header */
+  asection *data_section;
+  asection *stack_section;
+  asection *reg_section;
+  asection *reg2_section;
+};
+
+bfd_target *
+sunos4_core_file_p (abfd)
+     bfd *abfd;
+{
+  unsigned char longbuf[4];    /* Raw bytes of various header fields */
+  int core_size;
+  int core_mag;
+  struct core *core;
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)longbuf, 1, sizeof (longbuf), abfd) !=
+        sizeof (longbuf))
+    return 0;
+  core_mag = bfd_h_getlong (abfd, longbuf);
+
+  if (core_mag != CORE_MAGIC) return 0;
+
+  /* SunOS core headers can vary in length; second word is size; */
+  if (bfd_read ((void *)longbuf, 1, sizeof (longbuf), abfd) !=
+        sizeof (longbuf))
+    return 0;
+  core_size = bfd_h_getlong (abfd, longbuf);
+  /* Sanity check */
+  if (core_size > 20000)
+    return 0;
+
+  if (bfd_seek (abfd, 0L, false) < 0) return 0;
+
+  rawptr = zalloc (core_size + sizeof (struct suncordata));
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  core = (struct core *) (rawptr + sizeof (struct suncordata));
+
+  if ((bfd_read ((void *) core, 1, core_size, abfd)) != core_size) {
+    bfd_error = system_call_error;
+    free ((void *)rawptr);
+    return 0;
+  }
+
+  swapcore (abfd, core);
+  set_tdata (abfd, ((struct suncordata *) rawptr));
+  core_hdr (abfd) = core;
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  core_stacksec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_stacksec (abfd) == NULL) {
+loser:
+    bfd_error = no_memory;
+    free ((void *)rawptr);
+    return 0;
+  }
+  core_datasec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_datasec (abfd) == NULL) {
+loser1:
+    free ((void *)core_stacksec (abfd));
+    goto loser;
+  }
+  core_regsec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_regsec (abfd) == NULL) {
+loser2:
+    free ((void *)core_datasec (abfd));
+    goto loser1;
+  }
+  core_reg2sec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_reg2sec (abfd) == NULL) {
+    free ((void *)core_regsec (abfd));
+    goto loser2;
+  }
+
+  core_stacksec (abfd)->name = ".stack";
+  core_datasec (abfd)->name = ".data";
+  core_regsec (abfd)->name = ".reg";
+  core_reg2sec (abfd)->name = ".reg2";
+
+  core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_regsec (abfd)->flags = SEC_ALLOC;
+  core_reg2sec (abfd)->flags = SEC_ALLOC;
+
+  core_stacksec (abfd)->size = core->c_ssize;
+  core_datasec (abfd)->size = core->c_dsize;
+  core_regsec (abfd)->size = (sizeof core->c_regs);
+  /* Float regs take up end of struct, except c_ucode.  */
+  core_reg2sec (abfd)->size = core_size - (sizeof core->c_ucode) -
+                             (file_ptr)(((struct core *)0)->fp_stuff);
+
+  core_stacksec (abfd)->vma = (USRSTACK - core->c_ssize);
+  core_datasec (abfd)->vma = N_DATADDR(core->c_aouthdr);
+  core_regsec (abfd)->vma = -1;
+  core_reg2sec (abfd)->vma = -1;
+
+  core_stacksec (abfd)->filepos = core->c_len + core->c_dsize;
+  core_datasec (abfd)->filepos = core->c_len;
+                        /* In file header: */
+  core_regsec (abfd)->filepos = (file_ptr)(&((struct core *)0)->c_regs);
+  core_reg2sec (abfd)->filepos = (file_ptr)(((struct core *)0)->fp_stuff);
+
+  /* Align to word at least */
+  core_stacksec (abfd)->alignment_power = 2;
+  core_datasec (abfd)->alignment_power = 2;
+  core_regsec (abfd)->alignment_power = 2;
+  core_reg2sec (abfd)->alignment_power = 2;
+
+  abfd->sections = core_stacksec (abfd);
+  core_stacksec (abfd)->next = core_datasec (abfd);
+  core_datasec (abfd)->next = core_regsec (abfd);
+  core_regsec (abfd)->next = core_reg2sec (abfd);
+
+  abfd->section_count = 4;
+
+  return abfd->xvec;
+}
+
+char *
+sunos4_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_cmdname;
+}
+
+int
+sunos4_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_signo;
+}
+
+boolean
+sunos4_core_file_matches_executable_p  (core_bfd, exec_bfd)
+     bfd *core_bfd, *exec_bfd;
+{
+  if (core_bfd->xvec != exec_bfd->xvec) {
+    bfd_error = system_call_error;
+    return false;
+  }
+
+  return (bcmp ((char *)&core_hdr (core_bfd), (char*) &exec_hdr (exec_bfd),
+                sizeof (struct exec)) == 0) ? true : false;
+}
+
+/* byte-swap core structure */
+/* FIXME, this needs more work to swap IN a core struct from raw bytes */
+static void
+swapcore (abfd, core)
+     bfd *abfd;
+     struct core *core;
+{
+  unsigned char exec_bytes[EXEC_BYTES_SIZE];
+
+  core->c_magic = bfd_h_getlong (abfd, (unsigned char *)&core->c_magic);
+  core->c_len   = bfd_h_getlong (abfd, (unsigned char *)&core->c_len  );
+  /* Leave integer registers in target byte order.  */
+  bcopy ((char *)&(core->c_aouthdr), (char *)exec_bytes, EXEC_BYTES_SIZE);
+  bfd_aout_swap_exec_header_in (abfd, exec_bytes, &core->c_aouthdr);
+  core->c_signo = bfd_h_getlong (abfd, (unsigned char *)&core->c_signo);
+  core->c_tsize = bfd_h_getlong (abfd, (unsigned char *)&core->c_tsize);
+  core->c_dsize = bfd_h_getlong (abfd, (unsigned char *)&core->c_dsize);
+  core->c_ssize = bfd_h_getlong (abfd, (unsigned char *)&core->c_ssize);
+  /* Leave FP registers in target byte order.  */
+  /* Leave "c_ucode" unswapped for now, since we can't find it easily.  */
+}
+\f
+/** exec and core file sections */
+
+boolean
+sunos4_new_section_hook (abfd, newsect)
+     bfd *abfd;
+     asection *newsect;
+{
+  /* align to double at least */
+  newsect->alignment_power = 3;
+
+  if (bfd_get_format (abfd) == bfd_object) {
+    if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
+      obj_textsec(abfd)= newsect;
+      return true;
+    }
+
+    if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
+      obj_datasec(abfd) = newsect;
+      return true;
+    }
+
+    if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
+      obj_bsssec(abfd) = newsect;
+      return true;
+    }
+  }
+
+  /* We allow more than three sections internally */
+  return true;
+}
+
+boolean
+sunos4_set_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     unsigned char *location;
+     file_ptr offset;
+      int count;
+{
+  if (abfd->output_has_begun == false)
+    {                          /* set by bfd.c handler */
+      if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)
+         
+         /*||
+           (obj_textsec (abfd)->size == 0) || (obj_datasec (abfd)->size=
+           0)*/
+         ) 
+       {
+         bfd_error = invalid_operation;
+         return false;
+       }
+
+
+#if 0
+      if (abfd->flags & D_PAGED)
+       {
+         obj_textsec (abfd)->filepos = sizeof(struct exec);
+         obj_datasec(abfd)->filepos =  obj_textsec (abfd)->size;
+       }
+      else 
+#endif
+       {
+         obj_textsec (abfd)->filepos = sizeof(struct exec);
+         obj_datasec(abfd)->filepos = obj_textsec(abfd)->filepos  + obj_textsec (abfd)->size;
+
+       }
+    }
+  /* regardless, once we know what we're doing, we might as well get going */
+
+  bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+  if (count) {
+    return (bfd_write ((void *)location, 1, count, abfd) == count) ?
+      true : false;
+  }
+  return false;
+}
+boolean
+sunos4_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     void  *location;
+     file_ptr offset;
+     int count;
+{
+  if (count) {
+    if (offset >= section->size) return false;
+
+    bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+    return (bfd_read (location, 1, count, abfd) == count) ? true:false;
+  }
+  else return true;
+}
+
+\f
+/* Classify stabs symbols */
+
+
+#define sym_in_text_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
+
+#define sym_in_data_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
+
+#define sym_in_bss_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
+
+/* Symbol is undefined if type is N_UNDF|N_EXT and if it has
+   zero in the "value" field.  Nonzeroes there are fortrancommon
+   symbols.  */
+#define sym_is_undefined(sym) \
+        ((sym)->n_type == (N_UNDF | N_EXT) && (sym)->n_value == 0)
+
+/* Symbol is a global definition if N_EXT is on and if it has
+   a nonzero type field.  */
+#define sym_is_global_defn(sym) \
+        (((sym)->n_type & N_EXT) && (sym)->n_type & N_TYPE)
+
+/* Symbol is debugger info if any bits outside N_TYPE or N_EXT
+   are on.  */
+#define sym_is_debugger_info(sym) \
+        ((sym)->n_type & ~(N_EXT | N_TYPE))
+
+#define sym_is_fortrancommon(sym)       \
+        (((sym)->n_type == (N_EXT)) && (sym)->n_value != 0)
+
+/* Symbol is absolute if it has N_ABS set */
+#define sym_is_absolute(sym) \
+              (((sym)->n_type  & N_TYPE)== N_ABS)
+
+
+#define sym_is_indirect(sym) \
+              (((sym)->n_type  & N_ABS)== N_ABS)
+
+/* Only in their own functions for ease of debugging; when sym flags have
+   stabilised these should be inlined into their (single) caller */
+
+static void
+translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
+     struct nlist *sym_pointer;
+     aout_symbol_type *cache_ptr;
+     bfd *abfd;
+{
+  switch (cache_ptr->type & N_TYPE) {
+  case N_SETA:
+  case N_SETT:
+  case N_SETD:
+  case N_SETB:
+    {
+      asection *section = bfd_make_section(abfd,
+                                          cache_ptr->symbol.name);
+      arelent_chain *reloc = (arelent_chain *)malloc(sizeof(arelent_chain));
+
+      switch ( (cache_ptr->type  & N_TYPE) ) {
+      case N_SETA:
+       reloc->relent.section =  (asection *)NULL;
+       cache_ptr->symbol.section = (asection *)NULL;
+       break;
+      case N_SETT:
+       reloc->relent.section = (asection *)obj_textsec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETD:
+       reloc->relent.section = (asection *)obj_datasec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETB:
+       reloc->relent.section = (asection *)obj_bsssec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      }
+      cache_ptr->symbol.section = reloc->relent.section;
+      reloc->relent.addend = cache_ptr->symbol.value ;
+      /* 
+        We modify the symbol to belong to a section depending upon the
+        name of the symbol - probably __CTOR__ or __DTOR__ but we don't
+        really care, and add to the size of the section to contain a
+        pointer to the symbol. Build a reloc entry to relocate to this
+        symbol attached to this section.
+        */
+
+
+      section->flags = SEC_CONSTRUCTOR;
+      section->reloc_count++;
+      section->alignment_power = 2;
+      reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
+      reloc->next = section->constructor_chain;
+      section->constructor_chain = reloc;
+      reloc->relent.address = section->size;
+      section->size += sizeof(int *);
+
+      reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
+      cache_ptr->symbol.flags |=  BSF_DEBUGGING ;
+      }
+    break;
+  default:
+
+    if (sym_is_debugger_info (sym_pointer)) {
+      cache_ptr->symbol.flags = BSF_DEBUGGING ;
+      /* Work out the section correct for this symbol */
+      switch (sym_pointer->n_type & N_TYPE) 
+       {
+       case N_TEXT:
+       case N_FN:
+         cache_ptr->symbol.section = obj_textsec (abfd);
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         break;
+       case N_DATA:
+         cache_ptr->symbol.value  -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+         break;
+       case N_BSS :
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+         break;
+       case N_ABS:
+       default:
+         cache_ptr->symbol.section = 0;
+         break;
+       }
+    }
+    else {
+      if (sym_is_fortrancommon (sym_pointer))
+       {
+         cache_ptr->symbol.flags = BSF_FORT_COMM;
+         cache_ptr->symbol.section = (asection *)NULL;
+       }
+      else {
+       if (sym_is_undefined (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_UNDEFINED;
+       }
+       else if (sym_is_global_defn (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+       }
+
+       else if (sym_is_absolute (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_ABSOLUTE;
+       }
+       else {
+         cache_ptr->symbol.flags = BSF_LOCAL;
+       }
+
+       /* In a.out, the value of a symbol is always relative to the 
+        * start of the file, if this is a data symbol we'll subtract
+        * the size of the text section to get the section relative
+        * value. If this is a bss symbol (which would be strange)
+        * we'll subtract the size of the previous two sections
+        * to find the section relative address.
+        */
+
+       if (sym_in_text_section (sym_pointer))   {
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         cache_ptr->symbol.section = obj_textsec (abfd);
+       }
+       else if (sym_in_data_section (sym_pointer)){
+         cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+       }
+       else if (sym_in_bss_section(sym_pointer)) {
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+       }
+       else {
+         cache_ptr->symbol.section = (asection *)NULL;
+         cache_ptr->symbol.flags |= BSF_ABSOLUTE;
+       }
+      }
+    }
+  }
+}
+
+void
+translate_to_native_sym_flags (sym_pointer, cache_ptr_g, abfd)
+     struct nlist *sym_pointer;
+     generic_symbol_type *cache_ptr_g;
+     bfd *abfd;
+{
+  asymbol *cache_ptr = (asymbol *)cache_ptr_g;
+
+  /* FIXME check for wrigin bss */
+  if (bfd_get_section(cache_ptr)) {
+    if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
+      sym_pointer->n_type |= N_BSS;
+    }
+    else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
+      sym_pointer->n_type |= N_DATA;
+    }
+    else  if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
+      sym_pointer->n_type |= N_TEXT;
+    }
+    else {
+      bfd_error_trap(bfd_error_nonrepresentable_section,
+                bfd_get_output_section(cache_ptr)->name);
+
+    }
+    /* Turn the symbol from section relative to absolute again */
+    sym_pointer->n_value +=
+      cache_ptr->section->output_section->vma 
+       + cache_ptr->section->output_offset ;
+  }
+  else {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
+    sym_pointer->n_type = (N_UNDF | N_EXT);
+    return;
+  }
+
+  if (cache_ptr->flags & BSF_ABSOLUTE) {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
+    sym_pointer->n_type |= N_EXT;
+  }
+  if (cache_ptr->flags & BSF_DEBUGGING) {
+    sym_pointer->n_type = ((aout_symbol_type *)cache_ptr)->type;
+  }
+  
+}
+\f
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+   function exits.  We read the strings into a buffer large enough to
+   hold them all plus all the cached symbol entries. */
+
+asymbol *
+sunos4_make_empty_symbol (abfd)
+bfd *abfd;
+{
+  aout_symbol_type  *new =
+    (aout_symbol_type *)zalloc (sizeof (aout_symbol_type));
+  new->symbol.the_bfd = abfd;
+
+  return &new->symbol;
+}
+
+boolean
+sunos4_slurp_symbol_table (abfd)
+     bfd *abfd;
+{
+  unsigned int symbol_count;
+  size_t symbol_size;
+  size_t string_size;
+  struct nlist *syms;
+  char *strings;
+  aout_symbol_type *cached;
+
+  /* If there's no work to be done, don't do any */
+  if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
+  symbol_size = exec_hdr(abfd)->a_syms;
+  if (symbol_size == 0) {
+    bfd_error = no_symbols;
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)&string_size, 4, 1, abfd) != 4)
+    return false;
+  string_size = bfd_h_getlong (abfd, (unsigned char *)&string_size);
+
+  symbol_count = symbol_size / sizeof (struct nlist);
+
+  /* Malloc (should alloca) space for native symbols, and
+     malloc space for string table and symbol cache. */
+
+  syms = (struct nlist *) zalloc (symbol_size);
+  if (syms == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  cached = (aout_symbol_type *) zalloc ((size_t)(string_size + 1 +
+                               (symbol_count * sizeof (aout_symbol_type))));
+  if (cached == NULL) {
+    bfd_error = no_memory;
+    free ((void *)syms);
+    return false;
+  }
+
+  strings = ((char *) cached) + (symbol_count * sizeof (aout_symbol_type));
+
+  bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)syms, 1, symbol_size, abfd) != symbol_size) {
+  bailout:
+    free ((void *)cached);
+    free ((void*)syms);
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)strings, 1, string_size, abfd) != string_size) {
+    goto bailout;
+  }
+
+  /* OK, now walk the new symtable, cacheing symbol properties */
+  {
+    register struct nlist *sym_pointer;
+    register struct nlist *sym_end = syms + symbol_count;
+    register aout_symbol_type *cache_ptr = cached;
+
+    if (bfd_header_twiddle_required (abfd) == true) {
+      /* run through the table and byte swap if needed */
+      for (sym_pointer = syms; sym_pointer < sym_end;  sym_pointer++) {
+        sym_pointer->n_un.n_strx =
+         bfd_h_get_x (abfd, &sym_pointer->n_un.n_strx);
+        sym_pointer->n_desc =
+         bfd_h_get_x (abfd, &sym_pointer->n_desc);
+        sym_pointer->n_value =
+         bfd_h_get_x (abfd, &sym_pointer->n_value);
+       sym_pointer->n_other = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_other);
+       sym_pointer->n_type = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_type);
+
+      }
+    }
+    /* Run through table and copy values */
+    for (sym_pointer = syms, cache_ptr = cached;
+        sym_pointer < sym_end; sym_pointer++, cache_ptr++) 
+      {
+       cache_ptr->symbol.the_bfd = abfd;
+       if (sym_pointer->n_un.n_strx)
+         cache_ptr->symbol.name = sym_pointer->n_un.n_strx + strings;
+       else
+         cache_ptr->symbol.name = (char *)NULL;
+       cache_ptr->symbol.value = sym_pointer->n_value;
+       cache_ptr->desc = sym_pointer->n_desc;
+       cache_ptr->other = sym_pointer->n_other;
+       cache_ptr->type = sym_pointer->n_type;
+       cache_ptr->symbol.udata = 0;
+       translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
+
+      }
+  }
+
+  obj_aout_symbols (abfd) =  cached;
+  bfd_get_symcount (abfd) = symbol_count;
+  free ((void *)syms);
+
+  return true;
+}
+
+\f
+void
+sunos4_write_syms (abfd)
+     bfd *abfd;
+{
+  unsigned int count ;
+  asymbol **generic = bfd_get_outsymbols (abfd);
+
+  unsigned int stindex = sizeof(stindex); /* initial string length */
+
+  for (count = 0; count < bfd_get_symcount (abfd); count++) {
+    asymbol *g = generic[count];
+    struct nlist nsp;
+
+    if (g->name) {
+      unsigned int length = strlen(g->name) +1;
+      bfd_h_putlong  (abfd, stindex, (unsigned char *)&nsp.n_un.n_strx);
+      stindex += length;
+    }
+    else {
+      bfd_h_putlong  (abfd, 0, (unsigned char *)&nsp.n_un.n_strx);
+    }
+
+    if (g->the_bfd->xvec->flavour == abfd->xvec->flavour) 
+      {
+       nsp.n_desc = aout_symbol( g)->desc;
+       nsp.n_other = aout_symbol(g)->other;
+       nsp.n_type = aout_symbol(g)->type;
+      }
+    else
+      {
+       nsp.n_desc = 0;
+       nsp.n_other = 0;
+       nsp.n_type = 0;
+      }
+
+
+    nsp.n_value = g->value;
+    translate_to_native_sym_flags (&nsp, (generic_symbol_type *)g, abfd);
+
+
+    bfd_h_putshort (abfd, nsp.n_desc, (unsigned char *)&nsp.n_desc);
+    bfd_h_putlong  (abfd, nsp.n_value, (unsigned char *)&nsp.n_value);
+    bfd_write((void *)&nsp,1, sizeof(nsp), abfd);
+  }
+
+
+  /* Now output the strings.  Be sure to put string length into correct
+   * byte ordering before writing it.
+   */
+  bfd_h_putlong  (abfd, stindex, (unsigned char *)&stindex);
+
+  bfd_write((void *)&stindex, 1, sizeof(stindex), abfd);
+  
+  generic = bfd_get_outsymbols(abfd);
+  for (count = 0; count < bfd_get_symcount(abfd); count++) 
+    {
+      asymbol *g = *(generic++);
+
+      if (g->name != (char *)NULL) 
+       {
+         size_t length = strlen(g->name)+1;
+         bfd_write((void *)g->name, 1, length, abfd);
+       }
+      if ((g->flags & BSF_FAKE)==0) {
+       g->name = itos(count);  /* smash the generic symbol */
+      }
+    }
+}
+
+\f
+void
+sunos4_reclaim_symbol_table (abfd)
+     bfd *abfd;
+{
+  asection *section;
+
+  if (!bfd_get_symcount (abfd)) return;
+
+  for (section = abfd->sections;
+       section != (asection *) NULL;
+       section = section->next)
+    if (section->relocation) {
+      free ((void *)section->relocation);
+      section->relocation = NULL;
+      section->reloc_count = 0;
+    }
+
+  bfd_get_symcount (abfd) = 0;
+  free ((void *)obj_aout_symbols (abfd));
+  obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+}
+\f
+unsigned int
+sunos4_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
+}
+
+unsigned int
+sunos4_get_symtab (abfd, location)
+     bfd *abfd;
+     asymbol **location;
+{
+  unsigned int counter = 0;
+  aout_symbol_type *symbase;
+
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
+    *(location++) = (asymbol *)( symbase++);
+  *location++ =0;
+  return bfd_get_symcount(abfd);
+}
+
+\f
+/* Obsolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+   BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+sunos4_get_symcount_upper_bound (abfd)
+     bfd *abfd;
+{
+  /* In case we're doing an output file or something...?  */
+  if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+  return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+}
+
+symindex
+sunos4_get_first_symbol (ignore_abfd)
+     bfd * ignore_abfd;
+{
+  return 0;
+}
+
+symindex
+sunos4_get_next_symbol (abfd, oidx)
+     bfd *abfd;
+     symindex oidx;
+{
+  if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+  return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
+}
+
+char *
+sunos4_symbol_name (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.name;
+}
+
+long
+sunos4_symbol_value (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.value;
+}
+
+symclass
+sunos4_classify_symbol (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+  if ((sym->symbol.flags & BSF_FORT_COMM) != 0)   return bfd_symclass_fcommon;
+  if ((sym->symbol.flags & BSF_GLOBAL) != 0)    return bfd_symclass_global;
+  if ((sym->symbol.flags & BSF_DEBUGGING) != 0)  return bfd_symclass_debugger;
+  if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+
+  return bfd_symclass_unknown;
+}
+
+boolean
+sunos4_symbol_hasclass (abfd, idx, class)
+     bfd *abfd;
+     symindex idx;
+     symclass class;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+  switch (class) {
+  case bfd_symclass_fcommon:
+    return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+  case bfd_symclass_global:
+    return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+  case bfd_symclass_debugger:
+    return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+  case bfd_symclass_undefined:
+    return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+  default: return false;
+  }
+}
+\f
+/* Standard reloc stuff */
+/* Output standard relocation information to a file in target byte order. */
+
+void
+swap_std_reloc_out (abfd, p, natptr, count)
+     bfd *abfd;
+     arelent **p;              /* Generic relocation struct */
+     struct reloc_std_bytes *natptr;
+     unsigned int count;
+{
+  int r_index;
+  int r_extern;
+  unsigned int r_length;
+  int r_pcrel;
+  int r_baserel, r_jmptable, r_relative;
+  unsigned int r_addend;
+  unsigned int idx;
+  for (idx = 0; idx < count; idx++, p++, natptr++) 
+    {
+      arelent *g = *p;
+      bfd_h_putlong (abfd, g->address, natptr->r_address);
+
+      r_length = g->howto->size; /* Size as a power of two */
+      r_pcrel  = g->howto->pc_relative;        /* Relative to PC? */
+      /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
+      r_baserel = 0;
+      r_jmptable = 0;
+      r_relative = 0;
+
+      r_addend = g->addend;    /* Start here, see how it goes */
+
+      /* name was clobbered by sunos4_write_syms to be symbol index */
+
+      if (g->sym_ptr_ptr != NULL) 
+       {
+         if ((*(g->sym_ptr_ptr))->section) {
+           /* put the section offset into the addend for output */
+           r_addend += (*(g->sym_ptr_ptr))->section->vma;
+         }
+
+         r_index = stoi((*(g->sym_ptr_ptr))->name);
+         r_extern = 1;
+       }
+      else {
+       r_extern = 0;
+       if (g->section == NULL) {
+         BFD_ASSERT(0);
+         r_index = N_ABS | N_EXT;
+       }
+       else  if(g->section->output_section == obj_textsec(abfd)) {
+         r_index = N_TEXT | N_EXT;
+         r_addend += g->section->output_section->vma;
+       }
+       else if (g->section->output_section == obj_datasec(abfd)) {
+         r_index = N_DATA | N_EXT;
+         r_addend += g->section->output_section->vma;
+       }
+       else if (g->section->output_section == obj_bsssec(abfd)) {
+         r_index = N_BSS | N_EXT ;
+         r_addend += g->section->output_section->vma;
+       }
+       else {
+         BFD_ASSERT(0);
+       }
+      }
+
+      /* now the fun stuff */
+      if (abfd->xvec->header_byteorder_big_p != false) {
+       natptr->r_index[0] = r_index >> 16;
+       natptr->r_index[1] = r_index >> 8;
+       natptr->r_index[2] = r_index;
+       natptr->r_bits[0] =
+         (r_extern?    RELOC_STD_BITS_EXTERN_BIG: 0)
+           | (r_pcrel?     RELOC_STD_BITS_PCREL_BIG: 0)
+             | (r_baserel?   RELOC_STD_BITS_BASEREL_BIG: 0)
+               | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_BIG: 0)
+                 | (r_relative?  RELOC_STD_BITS_RELATIVE_BIG: 0)
+                   | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG);
+      } else {
+       natptr->r_index[2] = r_index >> 16;
+       natptr->r_index[1] = r_index >> 8;
+       natptr->r_index[0] = r_index;
+       natptr->r_bits[0] =
+         (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
+           | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
+             | (r_baserel?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
+               | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
+                 | (r_relative?  RELOC_STD_BITS_RELATIVE_LITTLE: 0)
+                   | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE);
+      }
+
+
+    }
+}
+
+
+/* Extended stuff */
+/* Output extended relocation information to a file in target byte order. */
+
+void
+swap_ext_reloc_out (abfd, p, natptr, count)
+     bfd *abfd;
+     arelent **p;              /* Generic relocation struct */
+     register struct reloc_ext_bytes *natptr;
+     unsigned int count;
+{
+
+  int r_index;
+  int r_extern;
+  unsigned int r_type;
+  unsigned int r_addend;
+  unsigned int idx;
+  for (idx = 0; idx < count; idx++, p++, natptr++) {
+    arelent *g = *p;
+
+    bfd_h_putlong (abfd, g->address, natptr->r_address);
+
+    /* Find a type in the output format which matches the input howto - 
+       at the moment we assume input format == output format FIXME!! */
+    r_type = (enum reloc_type) g->howto->type;
+
+    r_addend = g->addend;      /* Start here, see how it goes */
+
+    /* name was clobbered by sunos4_write_syms to be symbol index*/
+
+    if (g->sym_ptr_ptr != NULL) 
+      {
+       if ((*(g->sym_ptr_ptr))->section) {
+         /* put the section offset into the addend for output */
+         r_addend += (*(g->sym_ptr_ptr))->section->vma;
+       }
+
+       r_index = stoi((*(g->sym_ptr_ptr))->name);
+       r_extern = 1;
+      }
+    else {
+      r_extern = 0;
+      if (g->section == NULL) {
+       BFD_ASSERT(0);
+       r_index = N_ABS | N_EXT;
+      }
+      else  if(g->section->output_section == obj_textsec(abfd)) {
+       r_index = N_TEXT | N_EXT;
+       r_addend += g->section->output_section->vma;
+      }
+      else if (g->section->output_section == obj_datasec(abfd)) {
+       r_index = N_DATA | N_EXT;
+       r_addend += g->section->output_section->vma;
+      }
+      else if (g->section->output_section == obj_bsssec(abfd)) {
+       r_index = N_BSS | N_EXT ;
+       r_addend += g->section->output_section->vma;
+      }
+      else {
+       BFD_ASSERT(0);
+      }
+    }
+
+    /* now the fun stuff */
+    if (abfd->xvec->header_byteorder_big_p != false) {
+      natptr->r_index[0] = r_index >> 16;
+      natptr->r_index[1] = r_index >> 8;
+      natptr->r_index[2] = r_index;
+      natptr->r_bits[0] =
+       (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
+         || (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
+    } else {
+      natptr->r_index[2] = r_index >> 16;
+      natptr->r_index[1] = r_index >> 8;
+      natptr->r_index[0] = r_index;
+      natptr->r_bits[0] =
+       (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
+         || (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
+    }
+
+    bfd_h_putlong (abfd, r_addend, natptr->r_addend);
+  }
+}
+#define MOVE_ADDRESS(ad)                                                       \
+  if (r_extern) {                                                      \
+    cache_ptr->sym_ptr_ptr = symbols + r_index;                                \
+    cache_ptr->section = (asection *)NULL;                             \
+      cache_ptr->addend = ad;                                          \
+  } else {                                                             \
+    cache_ptr->sym_ptr_ptr = (asymbol **)NULL;                         \
+    switch (r_index) {                                                 \
+    case N_TEXT:                                                       \
+    case N_TEXT | N_EXT:                                               \
+      cache_ptr->section = obj_textsec(abfd);                          \
+      cache_ptr->addend = ad  - su->textsec->vma;                      \
+      break;                                                           \
+    case N_DATA:                                                       \
+    case N_DATA | N_EXT:                                               \
+      cache_ptr->section = obj_datasec(abfd);                          \
+      cache_ptr->addend = ad - su->datasec->vma;                       \
+      break;                                                           \
+    case N_BSS:                                                                \
+    case N_BSS | N_EXT:                                                        \
+      cache_ptr->section = obj_bsssec(abfd);                           \
+      cache_ptr->addend = ad - su->bsssec->vma;                                \
+      break;                                                           \
+    case N_ABS:                                                                \
+    case N_ABS | N_EXT:                                                        \
+      BFD_ASSERT(1);                                                   \
+      break;                                                           \
+    default:                                                           \
+      BFD_ASSERT(1);                                                   \
+      break;                                                           \
+    }                                                                  \
+  }                                                                    \
+
+void
+swap_ext_reloc_in (abfd, bytes, cache_ptr, symbols)
+     bfd *abfd;
+     struct reloc_ext_bytes *bytes;
+     arelent *cache_ptr;
+     asymbol **symbols;
+{
+  int r_index;
+  int r_extern;
+  unsigned int r_type;
+  struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
+
+  cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
+
+  /* now the fun stuff */
+  if (abfd->xvec->header_byteorder_big_p != false) {
+    r_index =  (bytes->r_index[0] << 16)
+            | (bytes->r_index[1] << 8)
+            |  bytes->r_index[2];
+    r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_BIG));
+    r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_BIG)
+                                     >> RELOC_EXT_BITS_TYPE_SH_BIG;
+  } else {
+    r_index =  (bytes->r_index[2] << 16)
+            | (bytes->r_index[1] << 8)
+            |  bytes->r_index[0];
+    r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
+    r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_LITTLE)
+                                     >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
+  }
+
+  cache_ptr->howto =  howto_table_ext + r_type;
+  MOVE_ADDRESS(bfd_h_getlong(abfd,bytes->r_addend));
+                                                                        
+}
+
+void
+swap_std_reloc_in (abfd, bytes, cache_ptr, symbols)
+     bfd *abfd;
+ struct reloc_std_bytes *bytes;
+     arelent *cache_ptr;
+     asymbol **symbols;
+{
+  int r_index;
+  int r_extern;
+  unsigned int r_length;
+  int r_pcrel;
+  int r_baserel, r_jmptable, r_relative;
+  struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
+  cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
+
+  /* now the fun stuff */
+  if (abfd->xvec->header_byteorder_big_p != false) {
+    r_index =  (bytes->r_index[0] << 16)
+      | (bytes->r_index[1] << 8)
+       |  bytes->r_index[2];
+    r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_BIG));
+    r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_BIG));
+    r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_BIG));
+    r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+    r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_BIG));
+    r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_BIG) 
+      >> RELOC_STD_BITS_LENGTH_SH_BIG;
+  } else {
+    r_index =  (bytes->r_index[2] << 16)
+      | (bytes->r_index[1] << 8)
+       |  bytes->r_index[0];
+    r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_LITTLE));
+    r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_LITTLE));
+    r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_LITTLE));
+    r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
+    r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
+    r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_LITTLE) 
+      >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
+  }
+
+  cache_ptr->howto =  howto_table_std + r_length + 4 * r_pcrel;
+  /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
+
+  MOVE_ADDRESS(0);
+}
+
+/* Reloc hackery */
+
+boolean
+sunos4_slurp_reloc_table (abfd, asect, symbols)
+     bfd *abfd;
+     sec_ptr asect;
+     asymbol **symbols;
+{
+  unsigned int count;
+  size_t reloc_size;
+  void *relocs;
+  arelent *reloc_cache;
+  size_t each_size;
+
+  if (asect->relocation) return true;
+
+  if (asect->flags & SEC_CONSTRUCTOR) return true;
+
+  if (asect == obj_datasec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_drsize;
+    goto doit;
+  }
+
+  if (asect == obj_textsec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_trsize;
+    goto doit;
+  }
+
+  bfd_error = invalid_operation;
+  return false;
+
+ doit:
+  bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
+  each_size = reloc_size_func(abfd);
+
+  count = reloc_size / each_size;
+
+  relocs =  malloc (reloc_size);
+  if (!relocs) {
+    bfd_error = no_memory;
+    return false;
+  }
+  reloc_cache = (arelent *) zalloc ((size_t)(count * sizeof (arelent)));
+  if (reloc_cache == (arelent *)NULL) {
+    free (relocs);
+    bfd_error = no_memory;
+    return false;
+  }
+
+  if (bfd_read ( relocs, 1, reloc_size, abfd) != reloc_size) {
+    bfd_error = system_call_error;
+    free (reloc_cache);
+    free (relocs);
+    return false;
+  }
+
+  if (each_size == RELOC_EXT_SIZE)
+    {
+      register struct reloc_ext_bytes *rptr = relocs;
+      unsigned int counter = 0;
+      arelent *cache_ptr = reloc_cache;
+
+      for (; counter < count; counter++, rptr++, cache_ptr++) {
+       swap_ext_reloc_in(abfd, rptr, cache_ptr, symbols);
+      }
+    }
+  else {
+    register struct reloc_std_bytes *rptr = relocs;
+    unsigned int counter = 0;
+    arelent *cache_ptr = reloc_cache;
+
+    for (; counter < count; counter++, rptr++, cache_ptr++) {
+       swap_std_reloc_in(abfd, rptr, cache_ptr, symbols);
+    }
+
+  }
+  free (relocs);
+  asect->relocation = reloc_cache;
+  asect->reloc_count = count;
+  return true;
+}
+
+
+
+/* Write out a relocation section into an object file.  */
+
+static boolean
+sunos4_squirt_out_relocs (abfd, section)
+     bfd *abfd;
+     asection *section;
+{
+  arelent **generic;
+  unsigned char *native;
+  size_t each_size;
+
+  unsigned int count = section->reloc_count;
+  size_t natsize;
+
+  if (count == 0) return true;
+
+  each_size = reloc_size_func(abfd);
+  natsize = each_size * count;
+  native = (unsigned char *) zalloc (natsize);
+  if (!native) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  generic = section->orelocation;
+
+  if (each_size == RELOC_EXT_SIZE) 
+    {
+      swap_ext_reloc_out (abfd,
+                         generic,
+                         (struct reloc_ext_bytes *)native,
+                         count);
+    }
+  else 
+    {
+      swap_std_reloc_out(abfd, generic, native, count);
+    }
+
+  if ( bfd_write ((void *) native, 1, natsize, abfd) != natsize) {
+    free(native);
+    return false;
+  }
+  free (native);
+
+  return true;
+}
+
+/* This is stupid.  This function should be a boolean predicate */
+unsigned int
+sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  arelent *tblptr = section->relocation;
+  unsigned int count;
+
+  if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
+    return 0;
+
+  if (section->flags & SEC_CONSTRUCTOR) {
+    arelent_chain *chain = section->constructor_chain;
+    for (count = 0; count < section->reloc_count; count ++) {
+      *relptr ++ = &chain->relent;
+      chain = chain->next;
+    }
+  }
+  else {
+    tblptr = section->relocation;
+    if (!tblptr) return 0;
+
+    for (count = 0; count++ < section->reloc_count;) 
+      {
+       *relptr++ = tblptr++;
+      }
+  }
+  *relptr = 0;
+
+  return section->reloc_count;
+}
+
+unsigned int
+sunos4_get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  if (bfd_get_format (abfd) != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+  if (asect->flags & SEC_CONSTRUCTOR) {
+    return (sizeof (arelent *) * (asect->reloc_count+1));
+  }
+
+
+  if (asect == obj_datasec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_drsize / reloc_size_func(abfd))
+             +1));
+
+  if (asect == obj_textsec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_trsize / reloc_size_func(abfd))
+             +1));
+
+  bfd_error = invalid_operation;
+  return 0;
+}
+
+void
+sunos4_reclaim_reloc (ignore_abfd, section)
+     bfd *ignore_abfd;
+     sec_ptr section;
+{
+  if (section->relocation) {
+    free (section->relocation);
+    section->relocation = NULL;
+    section->reloc_count = 0;
+    }
+}
+\f
+
+alent *
+sunos4_get_lineno(ignore_abfd, ignore_symbol)
+bfd *ignore_abfd;
+generic_symbol_type *ignore_symbol;
+{
+return (alent *)NULL;
+}
+
+void 
+sunos4_print_symbol(ignore_abfd, file,  symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+  switch (how) {
+  case bfd_print_symbol_name_enum:
+    fprintf(file,"%s", symbol->name);
+    break;
+  case bfd_print_symbol_type_enum:
+    fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
+           (unsigned)(   aout_symbol(symbol)->other  & 0xff),
+           (unsigned)(aout_symbol(symbol)->type));
+    break;
+  case bfd_print_symbol_all_enum:
+    {
+      char *section_name = symbol->section == (asection *)NULL ?
+       "*abs" : symbol->section->name;
+
+      bfd_print_symbol_vandf((void *)file,symbol);
+
+      fprintf(file," %-5s %04x %02x %02x %s",
+             section_name,
+             (unsigned)(aout_symbol(symbol)->desc & 0xffff),
+             (unsigned)(aout_symbol(symbol)->other  & 0xff),
+             (unsigned)(aout_symbol(symbol)->type  & 0xff),
+             symbol->name);
+    }
+    break;
+  }
+}
+/* Once we know all the stuff that could be consed, we know how to clean
+   it up.  So why don't we? */
+
+boolean
+sunos4_close_and_cleanup (abfd)
+     bfd *abfd;
+{
+  if (!bfd_read_p (abfd))
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) return false; break;
+    case bfd_object:
+      if (!sunos4_write_object_contents (abfd))  return false; break;
+    default: bfd_error = invalid_operation; return false;
+    }
+
+#define cleaner(ptr) if (abfd->ptr) free (abfd->ptr)
+  cleaner (tdata);
+
+  if (abfd->my_archive)
+    cleaner (filename);
+
+#undef cleaner
+  return true;
+}
+
+/* 
+ provided a bfd, a section and an offset into the section, calculate
+ and return the name of the source file and the line nearest to the
+ wanted location.
+*/
+boolean
+sunos4_find_nearest_line(abfd,
+                        section,
+                        symbols,
+                        offset,
+                        filename_ptr,
+                        functionname_ptr,
+                        line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+  /* Run down the file looking for the filename, function and linenumber */
+  asymbol **p;
+  static  char buffer[100];
+  bfd_vma high_line_vma = ~0;
+  bfd_vma low_func_vma = 0;
+  asymbol *func = 0;
+  *filename_ptr = abfd->filename;
+  *functionname_ptr = 0;
+  *line_ptr = 0;
+  if (symbols != (asymbol **)NULL) {
+    for (p = symbols; *p; p++) {
+      aout_symbol_type  *q = (aout_symbol_type *)(*p);
+      switch (q->type){
+      case N_SO:
+       *filename_ptr = q->symbol.name;
+       if (obj_textsec(abfd) != section) {
+         return true;
+       }
+       break;
+      case N_SLINE:
+
+      case N_DSLINE:
+      case N_BSLINE:
+       /* We'll keep this if it resolves nearer than the one we have already */
+       if (q->symbol.value >= offset &&
+           q->symbol.value < high_line_vma) {
+         *line_ptr = q->desc;
+         high_line_vma = q->symbol.value;
+       }
+       break;
+      case N_FUN:
+       {
+         /* We'll keep this if it is nearer than the one we have already */
+         if (q->symbol.value >= low_func_vma &&
+             q->symbol.value <= offset) {
+           low_func_vma = q->symbol.value;
+           func = (asymbol *)q;
+         }
+         if (*line_ptr && func) {
+           char *function = func->name;
+           char *p;
+           strncpy(buffer, function, sizeof(buffer)-1);
+           buffer[sizeof(buffer)-1] = 0;
+           /* Have to remove : stuff */
+           p = strchr(buffer,':');
+           if (p != NULL) {*p = NULL; }
+           *functionname_ptr = buffer;
+           return true;
+
+         }
+       }
+       break;
+      }
+    }
+  }
+  
+  return true;
+
+}
+
+bfd_target aoutvec =
+{
+  "a.out-generic-big",         /* name */
+  bfd_target_aout_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  sunos4_close_and_cleanup,    /* _close_and_cleanup */
+  sunos4_set_section_contents, /* bfd_set_section_contents */
+  sunos4_get_section_contents, /* bfd_get_section_contents */
+  sunos4_new_section_hook,     /* new_section_hook */
+  sunos4_core_file_failing_command, /* _core_file_failing_command */
+  sunos4_core_file_failing_signal, /* _core_file_failing_signal */
+  sunos4_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_bsd_armap,         /* bfd_slurp_armap */
+  bfd_true,                    /* bfd_slurp_extended_name_table */
+  bfd_bsd_truncate_arname,     /* bfd_truncate_arname */
+
+  sunos4_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  sunos4_get_symtab,           /* canonicalize_symtab */
+  sunos4_reclaim_symbol_table, /* bfd_reclaim_symbol_table */
+  sunos4_get_reloc_upper_bound,        /* get_reloc_upper_bound */
+  sunos4_canonicalize_reloc,   /* bfd_canonicalize_reloc */
+  sunos4_reclaim_reloc,                /* bfd_reclaim_reloc */
+  sunos4_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  sunos4_get_first_symbol,     /* bfd_get_first_symbol */
+  sunos4_get_next_symbol,      /* bfd_get_next_symbol */
+  sunos4_classify_symbol,      /* bfd_classify_symbol */
+  sunos4_symbol_hasclass,      /* bfd_symbol_hasclass */
+  sunos4_symbol_name,          /* bfd_symbol_name */
+  sunos4_symbol_value,         /* bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target, sunos4_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, sunos4_core_file_p},
+  {bfd_false, sunos4_mkobject, /* bfd_zxset_format */
+     _bfd_generic_mkarchive, bfd_false},
+  sunos4_make_empty_symbol,
+  sunos4_print_symbol,
+  sunos4_get_lineno,
+  sunos4_set_arch_mach,
+  bsd_write_armap,
+  bfd_generic_openr_next_archived_file,
+  sunos4_find_nearest_line,    /* bfd_find_nearest_line */
+  bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+  };
+
diff --git a/bfd/archive.c b/bfd/archive.c
new file mode 100644 (file)
index 0000000..477b6b1
--- /dev/null
@@ -0,0 +1,1240 @@
+/*** archive.c -- an attempt at combining the machine-independent parts of
+  archives */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Assumes:
+   o - all archive elements start on an even boundary, newline padded;
+   o - all arch headers are char *;
+   o - all arch headers are the same size (across architectures).
+*/
+
+/* $Id$ 
+ * $Log$
+ * Revision 1.4  1991/04/04 17:55:47  steve
+ * *** empty log message ***
+ *
+ * Revision 1.3  1991/04/04  14:56:42  gumby
+ * Minor format fixes.
+ *
+ * Revision 1.2  1991/04/03  22:09:43  steve
+ * Various noise
+ *
+ * Revision 1.1.1.1  1991/03/21  21:10:42  gumby
+ * Back from Intel with Steve
+ *
+ * Revision 1.1  1991/03/21  21:10:42  gumby
+ * Initial revision
+ *
+ * Revision 1.3  1991/03/16  05:55:25  rich
+ * pop
+ *
+ * Revision 1.2  1991/03/15  18:15:50  rich
+ * *** empty log message ***
+ *
+ * Revision 1.7  1991/03/08  04:18:02  rich
+ * *** empty log message ***
+ *
+ * Revision 1.6  1991/03/07  21:55:31  sac
+ * Added primitive file caching, a file open only for input and
+ * less than BFD_INCORE_FILE_SIZE will be malloced and read in
+ * only once.
+ *
+ * Revision 1.5  1991/03/05  16:31:12  sac
+ * lint
+ *
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "ar.h"
+#include "ranlib.h"
+
+/* We keep a cache of archive filepointers to archive elements to
+   speed up searching the archive by filepos.  We only add an entry to
+   the cache when we actually read one.  We also don't sort the cache;
+   it's short enough to search linearly.
+   Note that the pointers here point to the front of the ar_hdr, not
+   to the front of the contents!
+*/
+struct ar_cache {
+  file_ptr ptr;
+  bfd* arelt;
+  struct ar_cache *next;
+};
+
+#define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
+#define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
+
+#define arch_hdr(bfd) ((struct ar_hdr *)   \
+                      (((struct areltdata *)((bfd)->arelt_data))->arch_header))
+
+\f
+
+boolean
+_bfd_generic_mkarchive (abfd)
+     bfd *abfd;
+{
+  abfd->tdata =(void *) zalloc (sizeof (struct artdata));
+
+  if (abfd->tdata == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+bfd_ardata(abfd)->cache = 0;
+  return true;
+}
+
+symindex
+bfd_get_next_mapent (abfd, prev, entry)
+     bfd *abfd;
+   symindex prev;
+     carsym **entry;
+{
+  if (!bfd_has_map (abfd)) {
+    bfd_error = invalid_operation;
+    return BFD_NO_MORE_SYMBOLS;
+  }
+  
+  if (prev == BFD_NO_MORE_SYMBOLS) prev = 0;
+  else if (++prev >= (symindex)(bfd_ardata (abfd)->symdef_count))
+    return BFD_NO_MORE_SYMBOLS;
+
+  *entry = (bfd_ardata (abfd)->symdefs + prev);
+  return prev;
+}
+
+
+/* To be called by backends only */
+bfd *
+_bfd_create_empty_archive_element_shell (obfd)
+     bfd *obfd;
+{
+  bfd *nbfd;
+
+  nbfd = new_bfd_contained_in(obfd);
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+  return nbfd;
+}
+
+boolean
+bfd_set_archive_head (output_archive, new_head)
+     bfd *output_archive, *new_head;
+{
+  output_archive->archive_head = new_head;
+  return true;
+}
+
+bfd *
+look_for_bfd_in_cache (arch_bfd, filepos)
+     bfd *arch_bfd;
+     file_ptr filepos;
+{
+  struct ar_cache *current;
+
+  for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
+       current = current->next)
+    if (current->ptr == filepos) return current->arelt;
+
+  return NULL;
+}
+
+/* Kind of stupid to call cons for each one, but we don't do too many */
+boolean
+add_bfd_to_cache (arch_bfd, filepos, new_elt)
+     bfd *arch_bfd, *new_elt;
+     file_ptr filepos;
+{
+  struct ar_cache *new_cache = ((struct ar_cache *)
+                               zalloc (sizeof (struct ar_cache)));
+
+  if (new_cache == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  new_cache->ptr = filepos;
+  new_cache->arelt = new_elt;
+  new_cache->next = (struct ar_cache *)NULL;
+  if (bfd_ardata (arch_bfd)->cache == NULL)
+    bfd_ardata (arch_bfd)->cache = new_cache;
+  else {
+    struct ar_cache *current = bfd_ardata (arch_bfd)->cache;
+
+    for (; current->next != NULL; current = current->next);
+    current->next = new_cache;
+  }
+    
+  return true;
+}
+
+\f
+
+/* The name begins with space.  Hence the rest of the name is an index into
+   the string table. */
+
+char *
+get_extended_arelt_filename (arch, name)
+     bfd *arch;
+     char *name;
+{
+    extern int errno;
+    unsigned long index = 0;
+
+    /* Should extract string so that I can guarantee not to overflow into
+       the next region, but I"m too lazy. */
+    errno = 0;
+    index = strtol (name, NULL, 10);
+    if (errno != 0) {
+       bfd_error = malformed_archive;
+       return NULL;
+    }
+
+    return bfd_ardata (arch)->extended_names + index;
+}  
+
+/* This functions reads an arch header and returns an areltdata pointer, or
+   NULL on error.
+
+   Presumes the file pointer is already in the right place (ie pointing
+   to the ar_hdr in the file).   Moves the file pointer; on success it
+   should be pointing to the front of the file contents; on failure it
+   could have been moved arbitrarily.
+*/
+
+struct areltdata *
+snarf_ar_hdr (abfd)
+     bfd *abfd;
+{
+    extern int errno;
+    struct ar_hdr hdr;
+    char *hdrp = (char *) &hdr;
+    unsigned int parsed_size;
+    struct areltdata *ared;
+    char *filename = NULL;
+    unsigned int namelen = 0;
+    unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
+    char *allocptr;
+
+    if (bfd_read ((void *)hdrp, 1, sizeof (struct ar_hdr), abfd)
+       != sizeof (struct ar_hdr)) {
+       bfd_error = no_more_archived_files;
+       return NULL;
+    }
+    if (strncmp ((hdr.ar_fmag), ARFMAG, 2)) {
+       bfd_error = malformed_archive;
+       return NULL;
+    }
+
+    errno = 0;
+    parsed_size = strtol (hdr.ar_size, NULL, 10);
+    if (errno != 0) {
+       bfd_error = malformed_archive;
+       return NULL;
+    }
+
+    /* extract the filename from the archive */
+    if (hdr.ar_name[0] == ' ' && bfd_ardata (abfd)->extended_names != NULL) {
+       filename = get_extended_arelt_filename (abfd, hdr.ar_name);
+       if (filename == NULL) {
+           bfd_error = malformed_archive;
+           return NULL;
+       }
+    } 
+    else 
+       {
+           /* We judge the end of the name by looking for a space or a
+              padchar */
+
+           namelen = 0;
+
+           while (namelen < (unsigned)ar_maxnamelen(abfd) &&
+                  ( hdr.ar_name[namelen] != 0 &&
+                   hdr.ar_name[namelen] != ' ' &&
+                   hdr.ar_name[namelen] != ar_padchar(abfd))) {
+               namelen++;
+           }
+
+           allocsize += namelen + 1;
+       }
+
+    allocptr = zalloc (allocsize);
+    if (allocptr == NULL) {
+       bfd_error = no_memory;
+       return NULL;
+    }
+
+    ared = (struct areltdata *) allocptr;
+
+    ared->arch_header = allocptr + sizeof (struct areltdata);
+    memcpy ((char *) ared->arch_header, &hdr, sizeof (struct ar_hdr));
+    ared->parsed_size = parsed_size;
+
+    if (filename != NULL) ared->filename = filename;
+    else {
+       ared->filename = allocptr + (sizeof (struct areltdata) +
+                                    sizeof (struct ar_hdr));
+       if (namelen)
+           memcpy (ared->filename, hdr.ar_name, namelen);
+       ared->filename[namelen] = '\0';
+    }
+  
+    return ared;
+}
+\f
+bfd *
+get_elt_at_filepos (archive, filepos)
+     bfd *archive;
+     file_ptr filepos;
+{
+  struct areltdata *new_areldata;
+  bfd *n_nfd;
+
+  n_nfd = look_for_bfd_in_cache (archive, filepos);
+  if (n_nfd) return n_nfd;
+
+  if (0 > bfd_seek (archive, filepos, SEEK_SET)) {
+    bfd_error = system_call_error;
+    return NULL;
+  }
+
+  if ((new_areldata = snarf_ar_hdr (archive)) == NULL) return NULL;
+  
+  n_nfd = _bfd_create_empty_archive_element_shell (archive);
+  if (n_nfd == NULL) {
+    free (new_areldata);
+    return NULL;
+  }
+  n_nfd->origin = bfd_tell (archive);
+  n_nfd->arelt_data = (void *) new_areldata;
+  n_nfd->filename = new_areldata->filename;
+
+  if (add_bfd_to_cache (archive, filepos, n_nfd))
+    return n_nfd;
+
+  /* huh? */
+  free (new_areldata);
+  free (n_nfd);
+  return NULL;
+}
+
+bfd *
+bfd_get_elt_at_index (abfd, index)
+     bfd *abfd;
+     int index;
+{
+  bfd *result =
+    get_elt_at_filepos
+      (abfd, (bfd_ardata (abfd)->symdefs + index)->file_offset);
+  return result;
+}
+
+/* If you've got an archive, call this to read each subfile. */
+bfd *
+bfd_openr_next_archived_file (archive, last_file)
+     bfd *archive, *last_file;
+{
+
+  if ((bfd_get_format (archive) != bfd_archive) ||
+      (archive->direction == write_direction)) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+
+
+  return BFD_SEND (archive,
+                  openr_next_archived_file,
+                  (archive,
+                   last_file));
+
+}
+
+bfd *bfd_generic_openr_next_archived_file(archive, last_file)
+     bfd *archive;
+     bfd *last_file;
+{
+  file_ptr filestart;
+
+  if (!last_file)
+    filestart = bfd_ardata (archive)->first_file_filepos;
+  else {
+  unsigned int size = arelt_size(last_file);
+    filestart = last_file->origin +size + size %2;
+}
+
+
+
+  return get_elt_at_filepos (archive, filestart);
+}
+\f
+
+bfd_target *
+bfd_generic_archive_p (abfd)
+     bfd *abfd;
+{
+  char armag[SARMAG+1];
+
+  if (bfd_read ((void *)armag, 1, SARMAG, abfd) != SARMAG) {
+    bfd_error = wrong_format;
+    return 0;
+  }
+
+  if (strncmp (armag, ARMAG, SARMAG)) return 0;
+
+  bfd_set_ardata(abfd, (struct artdata *) zalloc (sizeof (struct artdata)));
+
+  if (bfd_ardata (abfd)  == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  bfd_ardata (abfd)->first_file_filepos = SARMAG;
+  
+  if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) {
+    free (bfd_ardata (abfd));
+    abfd->tdata = NULL;
+    return 0;
+  }
+
+  /* armap could be left ungc'd! FIXME -- potential storage leak */
+  if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) {
+    free (bfd_ardata (abfd));
+    abfd->tdata = NULL;
+    return 0;
+  }
+  
+  return abfd->xvec;
+}
+
+/* Returns false on error, true otherwise */
+boolean
+bfd_slurp_bsd_armap (abfd)
+     bfd *abfd;
+{
+  struct areltdata *mapdata;
+  char nextname[17];
+  unsigned int counter = 0;
+  int *raw_armap, *rbase;
+  struct artdata *ardata = bfd_ardata (abfd);
+  char *stringbase;
+
+  if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
+      /* The archive has at least 16 bytes in it */
+      bfd_seek (abfd, -16L, SEEK_CUR);
+
+      if (strncmp (nextname, "__.SYMDEF       ", 16)) {
+         bfd_has_map (abfd) = false;
+         return true;
+      }
+
+      mapdata = snarf_ar_hdr (abfd);
+      if (mapdata == NULL) return false;
+
+      raw_armap = (int *) zalloc (mapdata->parsed_size);
+      if (raw_armap == NULL) {
+         bfd_error = no_memory;
+  byebye:
+         free (mapdata);
+         return false;
+      }
+
+      if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
+         mapdata->parsed_size) {
+         bfd_error = malformed_archive;
+         free (raw_armap);
+         goto byebye;
+      }
+
+      ardata->symdef_count = *(raw_armap) / sizeof (struct symdef);
+      ardata->cache = 0;
+      rbase = raw_armap+1;
+      ardata->symdefs = (carsym *) rbase;
+      stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4;
+
+      for (;counter < (unsigned)( ardata->symdef_count); counter++) {
+         struct symdef *sym = ((struct symdef *) rbase) + counter;
+         sym->s.name = sym->s.string_offset + stringbase;
+      }
+  
+      ardata->first_file_filepos = bfd_tell (abfd);
+      /* Pad to an even boundary if you have to */
+      ardata->first_file_filepos += (ardata-> first_file_filepos) %2;
+      free (mapdata);
+      bfd_has_map (abfd) = true;
+  }
+  return true;
+}
+
+/* Returns false on error, true otherwise */
+boolean
+bfd_slurp_coff_armap (abfd)
+     bfd *abfd;
+{
+  struct areltdata *mapdata;
+  char nextname;
+  int *raw_armap, *rawptr;
+  struct artdata *ardata = bfd_ardata (abfd);
+  char *stringbase;
+  unsigned int stringsize;
+  carsym *carsyms;
+
+  if (bfd_read ((void *)&nextname, 1, 1, abfd) != 1) {
+  bfd_seek (abfd, -1L, SEEK_CUR);
+    bfd_has_map(abfd) = false;
+    return true;
+  }
+  bfd_seek (abfd, -1L, SEEK_CUR);
+
+  if (nextname != '/') {
+    /* Actually I think this is an error for a COFF archive */
+    bfd_has_map (abfd) = false;
+    return true;
+  }
+
+  mapdata = snarf_ar_hdr (abfd);
+  if (mapdata == NULL) return false;
+
+  raw_armap = (int *) zalloc (mapdata->parsed_size);
+  if (raw_armap == NULL) {
+    bfd_error = no_memory;
+  byebye:
+    free (mapdata);
+    return false;
+  }
+
+  if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
+      mapdata->parsed_size) {
+    bfd_error = malformed_archive;
+  oops:
+    free (raw_armap);
+    goto byebye;
+  }
+
+  /* The coff armap must be read sequentially.  So we construct a bsd-style
+     one in core all at once, for simplicity. */
+
+  stringsize = mapdata->parsed_size - (4 * (*raw_armap)) - 4;
+
+  {
+    unsigned int nsymz = *raw_armap;
+    unsigned int carsym_size = (nsymz * sizeof (carsym));
+    unsigned int ptrsize = (4 * nsymz);
+    unsigned int i;
+    ardata->symdefs = (carsym *) zalloc (carsym_size + stringsize + 1);
+    if (ardata->symdefs == NULL) {
+      bfd_error = no_memory;
+      goto oops;
+    }
+    carsyms = ardata->symdefs;
+
+    stringbase = ((char *) ardata->symdefs) + carsym_size;
+    memcpy (stringbase, (char*)raw_armap + ptrsize + 4,  stringsize);
+
+
+    /* OK, build the carsyms */
+    for (i = 0; i < nsymz; i++) 
+      {
+       rawptr = raw_armap + i + 1;
+       carsyms->file_offset = *rawptr;
+       carsyms->name = stringbase;
+       for (; *(stringbase++););
+       carsyms++;
+      }
+    *stringbase = 0;
+  }
+  ardata->symdef_count = *raw_armap;
+  ardata->first_file_filepos = bfd_tell (abfd);
+  /* Pad to an even boundary if you have to */
+  ardata->first_file_filepos += (ardata->first_file_filepos) %2;
+  free (raw_armap);
+  free (mapdata);
+  bfd_has_map (abfd) = true;
+  return true;
+}
+
+\f
+/** Extended name table.
+
+  Normally archives support only 14-character filenames.  Intel has extended
+  the format: longer names are stored in a special element (the first in the
+  archive, or second if there is an armap); the name in the ar_hdr is replaced
+  by <space><index into filename element>.  Index is the P.R. of an int (radix:
+  8). */
+
+/* Returns false on error, true otherwise */
+boolean
+_bfd_slurp_extended_name_table (abfd)
+     bfd *abfd;
+{
+  char nextname[17];
+  struct areltdata *namedata;
+
+  if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
+
+  bfd_seek (abfd, -16L, SEEK_CUR);
+
+  if (strncmp (nextname, "ARFILENAMES/    ", 16)) {
+    bfd_ardata (abfd)->extended_names = NULL;
+    return true;
+  }
+
+  namedata = snarf_ar_hdr (abfd);
+  if (namedata == NULL) return false;
+  
+  
+  bfd_ardata (abfd)->extended_names = zalloc (namedata->parsed_size);
+  if (bfd_ardata (abfd)->extended_names == NULL) {
+    bfd_error = no_memory;
+  byebye:
+    free (namedata);
+    return false;
+  }
+
+  if (bfd_read ((void*)bfd_ardata (abfd)->extended_names, 1,
+               namedata->parsed_size, abfd) != namedata->parsed_size) {
+    bfd_error = malformed_archive;
+    free (bfd_ardata (abfd)->extended_names);
+    bfd_ardata (abfd)->extended_names = NULL;
+    goto byebye;
+  }
+
+  /* Pad to an even boundary if you have to */
+  bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
+  bfd_ardata (abfd)->first_file_filepos +=
+    (bfd_ardata (abfd)->first_file_filepos) %2;
+
+  free (namedata);
+}
+  return true;
+}
+
+static
+char *normalize(file)
+char *file;
+{
+    char *    filename = strrchr(file, '/');
+    if (filename != (char *)NULL) {
+       filename ++;
+    }
+    else {
+       filename = file;
+    }
+return filename;
+}
+
+/* Follows archive_head and produces an extended name table if necessary.
+   Returns (in tabloc) a pointer to an extended name table, and in tablen
+   the length of the table.  If it makes an entry it clobbers the filename
+   so that the element may be written without further massage.
+   Returns true if it ran successfully, false if something went wrong.
+   A successful return may still involve a zero-length tablen!
+   */
+boolean
+bfd_construct_extended_name_table (abfd, tabloc, tablen)
+     bfd *abfd;
+     char **tabloc;
+     unsigned int *tablen;
+{
+    unsigned int maxname = abfd->xvec->ar_max_namelen;
+    unsigned int total_namelen = 0;
+    bfd *current;
+    char *strptr;
+
+    *tablen = 0;
+  
+    /* Figure out how long the table should be */
+    for (current = abfd->archive_head; current != NULL; current = current->next){
+       unsigned int thislen = strlen (normalize(current->filename));
+       if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \0 */
+    }
+
+    if (total_namelen == 0) return true;
+
+    *tabloc = zalloc (total_namelen);
+    if (*tabloc == NULL) {
+       bfd_error = no_memory;
+       return false;
+    }
+
+    *tablen = total_namelen;
+    strptr = *tabloc;
+
+    for (current = abfd->archive_head; current != NULL; current =
+        current->next) {
+       char *normal =normalize( current->filename);
+       unsigned int thislen = strlen (normal);
+       if (thislen > maxname) {
+         /* Works for now; may need to be re-engineered if we encounter an oddball
+            archive format and want to generalise this hack. */
+         struct ar_hdr *hdr = arch_hdr(current);
+           strcpy (strptr, normal);
+           hdr->ar_name[0] = ' ';
+           /* We know there will always be enough room (one of the few cases
+              where you may safely use sprintf). */
+           sprintf ((hdr->ar_name) + 1, "%-o", (unsigned) (strptr - *tabloc));
+
+           strptr += thislen + 1;
+       }
+    }
+
+    return true;
+}
+\f
+/** A couple of functions for creating ar_hdrs */
+
+/* Takes a filename, returns an arelt_data for it, or NULL if it can't make one.
+   The filename must refer to a filename in the filesystem.
+   The filename field of the ar_hdr will NOT be initialized
+*/
+
+struct areltdata *
+bfd_ar_hdr_from_filesystem (filename)
+     char *filename;
+{
+  struct stat status;
+  struct areltdata *ared;
+  struct ar_hdr *hdr;
+  char *temp, *temp1;
+
+
+  if (stat (filename, &status) != 0) {
+    bfd_error = system_call_error;
+    return NULL;
+  }
+
+  ared = (struct areltdata *) zalloc (sizeof (struct ar_hdr) +
+                                     sizeof (struct areltdata));
+  if (ared == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+  hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
+
+  /* ar headers are space padded, not null padded! */
+  temp = (char *) hdr;
+  temp1 = temp + sizeof (struct ar_hdr) - 2;
+  for (; temp < temp1; *(temp++) = ' ');
+  strncpy (hdr->ar_fmag, ARFMAG, 2);
+  
+  /* Goddamned sprintf doesn't permit MAXIMUM field lengths */
+  sprintf ((hdr->ar_date), "%-12ld", status.st_mtime);
+  sprintf ((hdr->ar_uid), "%d", status.st_uid);
+  sprintf ((hdr->ar_gid), "%d", status.st_gid);
+  sprintf ((hdr->ar_mode), "%-8o", (unsigned) status.st_mode);
+  sprintf ((hdr->ar_size), "%-10ld", status.st_size);
+  /* Correct for a lossage in sprintf whereby it null-terminates.  I cannot
+     understand how these C losers could design such a ramshackle bunch of
+     IO operations */
+  temp = (char *) hdr;
+  temp1 = temp + sizeof (struct ar_hdr) - 2;
+  for (; temp < temp1; temp++) {
+    if (*temp == '\0') *temp = ' ';
+  }
+  strncpy (hdr->ar_fmag, ARFMAG, 2);
+  ared->parsed_size = status.st_size;
+  ared->arch_header = (char *) hdr;
+
+  return ared;
+}
+
+struct ar_hdr *
+bfd_special_undocumented_glue (filename)
+     char *filename;
+{
+
+  return (struct ar_hdr *) bfd_ar_hdr_from_filesystem (filename) -> arch_header;
+}
+
+
+/* Analogous to stat call */
+int
+bfd_generic_stat_arch_elt (abfd, buf)
+     bfd *abfd;
+     struct stat *buf;
+{
+  struct ar_hdr *hdr;
+  char *aloser;
+  
+  if (abfd->arelt_data == NULL) {
+    bfd_error = invalid_operation;
+    return -1;
+  }
+    
+  hdr = arch_hdr (abfd);
+
+#define foo(arelt, stelt, size)  \
+  buf->stelt = strtol (hdr->arelt, &aloser, size); \
+  if (aloser == hdr->arelt) return -1;
+  
+  foo (ar_date, st_mtime, 10);
+  foo (ar_uid, st_uid, 10);
+  foo (ar_gid, st_gid, 10);
+  foo (ar_mode, st_mode, 8);
+  foo (ar_size, st_size, 10);
+
+  return 0;
+}
+
+/* Don't do anything -- it'll be taken care of later */
+void
+bfd_dont_truncate_arname (ignore_abfd, ignore_filename, ignore_arhdr)
+     bfd *ignore_abfd;
+     char *ignore_filename;
+     char *ignore_arhdr;
+{
+  /* FIXME -- Actually this is incorrect.  If the name is short we
+    should insert into the header; only if it is long should we do
+    nothing.
+
+    Anyway, this interacts unpleasantly with ar's quick-append option,
+    for now just be compatible with the old system */
+
+  return;
+}
+
+void
+bfd_bsd_truncate_arname (abfd, pathname, arhdr)
+     bfd *abfd;
+     char *pathname;
+     char *arhdr;
+{
+  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+  int length;
+  char *filename = strrchr (pathname, '/');
+  int maxlen = ar_maxnamelen (abfd);
+
+
+  if (filename == NULL)
+    filename = pathname;
+  else
+    ++filename;
+
+  length = strlen (filename);
+
+  if (length <= maxlen)
+    memcpy (hdr->ar_name, filename, length);
+  else {
+    /* pathname: meet procrustes */
+    memcpy (hdr->ar_name, filename, maxlen);
+    length = maxlen;
+  }
+
+  if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
+}
+
+/* Store name into ar header.  Truncates the name to fit.
+   1> strip pathname to be just the basename.
+   2> if it's short enuf to fit, stuff it in.
+   3> If it doesn't end with .o, truncate it to fit
+   4> truncate it before the .o, append .o, stuff THAT in.
+*/
+
+/* This is what gnu ar does.  It's better but incompatible with the bsd ar. */
+void
+bfd_gnu_truncate_arname (abfd, pathname, arhdr)
+     bfd *abfd;
+     char *pathname;
+     char *arhdr;
+{
+  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+  int length;
+  char *filename = strrchr (pathname, '/');
+  int maxlen = ar_maxnamelen (abfd);
+       
+  if (filename == NULL)
+    filename = pathname;
+  else
+    ++filename;
+
+  length = strlen (filename);
+
+  if (length <= maxlen)
+    memcpy (hdr->ar_name, filename, length);
+  else {                       /* pathname: meet procrustes */
+    memcpy (hdr->ar_name, filename, maxlen);
+    if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) {
+      hdr->ar_name[maxlen - 2] = '.';
+      hdr->ar_name[maxlen - 1] = 'o';
+    }
+    length = maxlen;
+  }
+
+  if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
+}
+\f
+
+PROTO (boolean, compute_and_write_armap, (bfd *arch, unsigned int elength));
+
+/* The bfd is open for write and has its format set to bfd_archive */
+boolean
+_bfd_write_archive_contents (arch)
+     bfd *arch;
+{
+  bfd *current;
+  char *etable = NULL;
+  unsigned int elength = 0;
+  boolean makemap = bfd_has_map (arch);
+  boolean hasobjects = false;  /* if no .o's, don't bother to make a map */
+  unsigned int i;
+
+
+  /* Verify the viability of all entries; if any of them live in the
+     filesystem (as opposed to living in an archive open for input)
+     then construct a fresh ar_hdr for them.
+     */
+  for (current = arch->archive_head; current; current = current->next) {
+    if (bfd_write_p (current)) {
+      bfd_error = invalid_operation;
+      return false;
+    }
+    if (!current->arelt_data) {
+      current->arelt_data =
+         (void *) bfd_ar_hdr_from_filesystem (current->filename);
+      if (!current->arelt_data) return false;
+
+      /* Put in the file name */
+    
+    BFD_SEND (arch, _bfd_truncate_arname,(arch, 
+                                         current->filename,
+                                        (char *) arch_hdr(current)));
+
+      
+    }
+
+    if (makemap) {             /* don't bother if we won't make a map! */
+      if ((bfd_check_format (current, bfd_object))
+#if 0                          /* FIXME -- these are not set correctly */
+         && ((bfd_get_file_flags (current) & HAS_SYMS))
+#endif
+         )
+       hasobjects = true;
+    }
+  }
+
+  if (!bfd_construct_extended_name_table (arch, &etable, &elength))
+    return false;
+
+  bfd_seek (arch, 0, SEEK_SET);
+  bfd_write (ARMAG, 1, SARMAG, arch);
+
+  if (makemap && hasobjects) {
+
+    if (compute_and_write_armap (arch, elength) != true) {
+      if (etable) free (etable);
+      return false;
+    }
+  }
+
+  if (elength != 0) {
+    struct ar_hdr hdr;
+
+    memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
+    sprintf (&(hdr.ar_name[0]), "ARFILENAMES/");
+    sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);
+    hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
+    for (i = 0; i < sizeof (struct ar_hdr); i++)
+      if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
+    bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+    bfd_write (etable, 1, elength, arch);
+    if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
+    if (etable) free (etable);
+  }
+
+  for (current = arch->archive_head; current; current = current->next) {
+    char buffer[DEFAULT_BUFFERSIZE];
+    unsigned int remaining = arelt_size (current);
+    struct ar_hdr *hdr = arch_hdr(current);
+    /* write ar header */
+
+    if (bfd_write (hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
+    syserr:
+       bfd_error = system_call_error;
+       return false;
+      }
+    if (bfd_seek (current, 0L, SEEK_SET) != 0L) goto syserr;
+    while (remaining) 
+       {
+         unsigned int amt = DEFAULT_BUFFERSIZE;
+         if (amt > remaining) {
+           amt = remaining;
+         }
+         if (bfd_read (buffer, amt, 1, current) != amt) goto syserr;
+         if (bfd_write (buffer, amt, 1, arch)   != amt) goto syserr;
+         remaining -= amt;
+       }
+    if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch);
+  }
+return true;
+}
+\f
+/* Note that the namidx for the first symbol is 0 */
+
+  
+
+boolean
+compute_and_write_armap (arch, elength)
+     bfd *arch;
+     unsigned int elength;
+{
+  bfd *current;
+  file_ptr elt_no = 0;
+  struct orl *map;
+  int orl_max = 15000;         /* fine initial default */
+  int orl_count = 0;
+  int stridx = 0;              /* string index */
+
+  /* Dunno if this is the best place for this info... */
+  if (elength != 0) elength += sizeof (struct ar_hdr);
+  elength += elength %2 ;
+
+  map = (struct orl *) zalloc (orl_max * sizeof (struct orl));
+  if (map == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  /* Map over each element */
+  for (current = arch->archive_head;
+       current != (bfd *)NULL;
+       current = current->next, elt_no++) 
+      {
+       if ((bfd_check_format (current, bfd_object) == true)
+           && ((bfd_get_file_flags (current) & HAS_SYMS))) {
+         asymbol **syms;
+         unsigned int storage;
+         unsigned int symcount;
+         unsigned int src_count;
+
+         storage = get_symtab_upper_bound (current);
+         if (storage != 0) {
+
+           syms = (asymbol **) zalloc (storage);
+           if (syms == NULL) {
+             bfd_error = no_memory; /* FIXME -- memory leak */
+             return false;
+           }
+           symcount = bfd_canonicalize_symtab (current, syms);
+
+
+           /* Now map over all the symbols, picking out the ones we want */
+           for (src_count = 0; src_count <symcount; src_count++) {
+             flagword flags = (syms[src_count])->flags;
+             if ((flags & BSF_GLOBAL) ||
+                 (flags & BSF_FORT_COMM)) {
+
+               /* This symbol will go into the archive header */
+               if (orl_count == orl_max) 
+                   {
+                     orl_max *= 2;
+                     map = (struct orl *) realloc ((char *) map,
+                                                   orl_max * sizeof (struct orl));
+                   }
+
+               (map[orl_count]).name = &((syms[src_count])->name);
+               (map[orl_count]).pos = elt_no;
+               (map[orl_count]).namidx = stridx;
+
+               stridx += strlen ((syms[src_count])->name) + 1;
+               ++orl_count;
+             }
+           }
+         }
+       }
+      }
+  /* OK, now we have collected all the data, let's write them out */
+  if (!BFD_SEND (arch, write_armap,
+                (arch, elength, map, orl_count, stridx))) {
+    free (map);
+    return false;
+  }
+
+  free (map);
+  return true;
+}
+
+\f
+ /* FIXME -- have to byte-swap this */
+
+boolean
+bsd_write_armap (arch, elength, map, orl_count, stridx)
+     bfd *arch;
+     unsigned int elength;
+     struct orl *map;
+     int orl_count;
+     int stridx;
+{
+  unsigned int ranlibsize = (orl_count * sizeof (struct ranlib)) + 4;
+  unsigned int stringsize = stridx + 4;
+  unsigned int mapsize = stringsize + ranlibsize;
+  file_ptr firstreal;
+  bfd *current = arch->archive_head;
+  int last_eltno = 0;          /* last element arch seen */
+  int temp;
+  int count;
+  struct ar_hdr hdr;
+  struct stat statbuf;
+  unsigned int i;
+  int padit = mapsize & 1;
+  
+  if (padit) mapsize ++;
+
+  firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
+
+  fstat (arch->iostream, &statbuf); /* FIXME -- descriptor must be open! */
+  memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
+  sprintf (hdr.ar_name, "__.SYMDEF");
+  sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+  sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);  
+  hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
+  for (i = 0; i < sizeof (struct ar_hdr); i++)
+    if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
+  bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+
+  temp = orl_count /* + 4 */;
+  bfd_write (&temp, 1, sizeof (temp), arch);
+  
+  for (count = 0; count < orl_count; count++) {
+    struct symdef outs;
+    struct symdef *outp = &outs;
+    
+    if ((map[count]).pos != last_eltno) {
+      firstreal += arelt_size (current) + sizeof (struct ar_hdr);
+      firstreal += firstreal % 2;
+    last_eltno = (map[count]).pos;
+      current = current->next;
+    }
+
+    outs.s.string_offset = ((map[count]).namidx) +4;
+    outs.file_offset = firstreal;
+    bfd_write ((char *)outp, 1, sizeof (outs), arch);
+  }
+
+  /* now write the strings themselves */
+  temp = stridx + 4;
+  bfd_write (&temp, 1, sizeof (temp), arch);
+  for (count = 0; count < orl_count; count++)
+    bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);
+
+  /* The spec sez this should be a newline.  But in order to be
+     bug-compatible for sun's ar we use a null. */
+  if (padit)
+    bfd_write("\0",1,1,arch);
+
+  return true;
+}
+\f
+
+/* A coff armap looks like :
+ ARMAG
+ struct ar_hdr with name = '/' 
+ number of symbols
+ offset of file for symbol 0
+ offset of file for symbol 1
+    ..
+ offset of file for symbol n-1
+ symbol name 0
+ symbol name 1 
+    ..
+ symbol name n-1
+
+*/
+  
+boolean
+coff_write_armap (arch, elength, map, orl_count, stridx)
+     bfd *arch;
+     unsigned int elength;
+     struct orl *map;
+     int orl_count;
+     int stridx;
+{
+    unsigned int ranlibsize = (orl_count * 4) + 4;
+    unsigned int stringsize = stridx;
+    unsigned int mapsize = stringsize + ranlibsize;
+    file_ptr archive_member_file_ptr;
+    bfd *current = arch->archive_head;
+    int last_eltno = 0;                /* last element arch seen */
+    int count;
+    struct ar_hdr hdr;
+    unsigned int i;
+    int padit = mapsize & 1;
+  
+    if (padit) mapsize ++;
+
+    archive_member_file_ptr =
+       mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
+
+    memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
+    hdr.ar_name[0] = '/';
+    sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+    sprintf (hdr.ar_date, "%ld", time (NULL));
+    /* This, at least, is what Intel coff sets the values to.: */
+    sprintf ((hdr.ar_uid), "%d", 0);
+    sprintf ((hdr.ar_gid), "%d", 0);
+    sprintf ((hdr.ar_mode), "%-7o", 0);
+    hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
+
+    for (i = 0; i < sizeof (struct ar_hdr); i++)
+       if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
+
+    /* Write the ar header for this item and the number of symbols */
+
+    bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+    bfd_write (&orl_count, 1, sizeof (orl_count), arch);
+
+    /* Two passes, first write the file offsets for each symbol -
+       remembering that each offset is on a two byte boundary
+       */
+
+    for (count = 0; count < orl_count; count++) {
+       while ((map[count]).pos != last_eltno) {
+           /* If this is the first time we've seen a ref to this archive
+              then remember it's size */
+           archive_member_file_ptr +=
+               arelt_size (current) + sizeof (struct ar_hdr);
+           archive_member_file_ptr += archive_member_file_ptr % 2;
+           current = current->next;
+           last_eltno++;
+       }
+       bfd_write (&archive_member_file_ptr,
+                  1,
+                  sizeof (archive_member_file_ptr),
+                  arch);
+    }
+
+    /* now write the strings themselves */
+    for (count = 0; count < orl_count; count++) {
+       bfd_write (*((map[count]).name),
+                  1,
+                  strlen (*((map[count]).name))+1, arch);
+
+    }
+    /* The spec sez this should be a newline.  But in order to be
+       bug-compatible for arc960 we use a null. */
+    if (padit)
+       bfd_write("\0",1,1,arch);
+
+    return true;
+}
diff --git a/bfd/archures.c b/bfd/archures.c
new file mode 100644 (file)
index 0000000..b7fdaf9
--- /dev/null
@@ -0,0 +1,368 @@
+/* BFD library support routines for architectures. */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "archures.h"
+
+static char *prt_num_mach ();
+static boolean scan_num_mach ();
+static char *prt_960_mach ();
+static boolean scan_960_mach ();
+
+struct arch_print {
+       enum bfd_architecture arch;
+       char *astr;
+       char *(*mach_print)();
+       boolean (*mach_scan)();
+} arch_print[] = {
+
+       {bfd_arch_unknown,      "unknown",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_obscure,      "obscure",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_m68k,         "m68k",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_vax,          "vax",          prt_num_mach,   scan_num_mach},
+       {bfd_arch_i960,         "i960",         prt_960_mach,   scan_960_mach},
+       {bfd_arch_a29k,         "a29k",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_sparc,        "sparc",        prt_num_mach,   scan_num_mach},
+       {bfd_arch_mips,         "mips",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_i386,         "i386",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_ns32k,        "ns32k",        prt_num_mach,   scan_num_mach},
+       {bfd_arch_tahoe,        "tahoe",        prt_num_mach,   scan_num_mach},
+       {bfd_arch_i860,         "i860",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_romp,         "romp",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_alliant,      "alliant",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_convex,       "convex",       prt_num_mach,   scan_num_mach},
+       {bfd_arch_m88k,         "m88k",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_pyramid,      "pyramid",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_unknown,      (char *)0,      prt_num_mach,   scan_num_mach},
+};
+
+/* Return a printable string representing the architecture and machine
+   type.  The result is only good until the next call to
+   bfd_printable_arch_mach.  */
+
+char *
+bfd_printable_arch_mach (arch, machine)
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  struct arch_print *ap;
+
+  for (ap = arch_print; ap->astr; ap++) {
+    if (ap->arch == arch) {
+      if (machine == 0)
+       return ap->astr;
+      return (*ap->mach_print)(ap, machine);
+    }
+  }
+  return "UNKNOWN!";
+}
+
+static char *
+prt_num_mach (ap, machine)
+     struct arch_print *ap;
+     unsigned long machine;
+{
+  static char result[20];
+
+  sprintf(result, "%s:%ld", ap->astr, (long) machine);
+  return result;
+}
+
+/* Scan a string and attempt to turn it into an archive and machine type
+   combination.  */
+
+boolean
+bfd_scan_arch_mach (string, archp, machinep)
+     char *string;
+     enum bfd_architecture *archp;
+     unsigned long *machinep;
+{
+  struct arch_print *ap;
+  int len;
+
+  /* First look for an architecture, possibly followed by machtype. */
+  for (ap = arch_print; ap->astr; ap++) {
+    if (ap->astr[0] != string[0])
+      continue;
+    len = strlen (ap->astr);
+    if (!strncmp (ap->astr, string, len)) {
+      /* We found the architecture, now see about the machine type */
+      if (archp)
+       *archp = ap->arch;
+      if (string[len] != '\0') {
+       if (ap->mach_scan (string+len, ap, archp, machinep, 1))
+         return true;
+      }
+      if (machinep)
+       *machinep = 0;
+      return true;
+    }
+  }
+
+  /* Couldn't find an architecture -- try for just a machine type */
+  for (ap = arch_print; ap->astr; ap++) {
+    if (ap->mach_scan (string, ap, archp, machinep, 0))
+      return true;
+  }
+
+  return false;
+}
+
+static boolean
+scan_num_mach (string, ap, archp, machinep, archspec)
+     char *string;
+     struct arch_print *ap;
+     enum bfd_architecture *archp;
+     unsigned long *machinep;
+     int archspec;
+{
+  enum bfd_architecture arch;
+  unsigned long machine;
+  char achar;
+
+  if (archspec) {
+
+    /* Architecture already specified, now go for machine type.  */
+    if (string[0] != ':')
+      return false;
+    /* We'll take any valid number that occupies the entire string */
+    if (1 != sscanf (string+1, "%lu%c", &machine, &achar))
+      return false;
+    arch = ap->arch;
+
+  } else {
+
+    /* We couldn't identify an architecture prefix.  Perhaps the entire
+       thing is a machine type.  Be a lot picker.  */
+    if (1 != sscanf (string, "%lu%c", &machine, &achar))
+      return false;
+    switch (machine) {
+    case 68010:
+    case 68020:
+    case 68030:
+    case 68040:
+    case 68332:
+    case 68050:                arch = bfd_arch_m68k; break;
+    case 68000:                arch = bfd_arch_m68k; machine = 0; break;
+
+    case 80960:
+    case 960:          arch = bfd_arch_i960; machine = 0; break;
+
+    case 386:
+    case 80386:                arch = bfd_arch_i386; machine = 0; break;
+    case 486:          arch = bfd_arch_i386; break;
+
+    case 29000:                arch = bfd_arch_a29k; machine = 0; break;
+
+    case 32016:
+    case 32032:
+    case 32132:
+    case 32232:
+    case 32332:
+    case 32432:
+    case 32532:                arch = bfd_arch_ns32k; break;
+    case 32000:                arch = bfd_arch_ns32k; machine = 0; break;
+
+    case 860:
+    case 80860:                arch = bfd_arch_i860; machine = 0; break;
+
+    default:           return false;
+    }
+  }
+
+  if (archp)
+    *archp = arch;
+  if (machinep)
+    *machinep = machine;
+  return true;
+}
+\f
+/* Intel 960 machine variants.  */
+
+static char *
+prt_960_mach (ap, machine)
+     struct arch_print *ap;
+     unsigned long machine;
+{
+  static char result[20];
+  char *str;
+
+  switch (machine) {
+  case bfd_mach_i960_core:     str = "core"; break;
+  case bfd_mach_i960_kb_sb:    str = "kb"; break;
+  case bfd_mach_i960_mc:       str = "mc"; break;
+  case bfd_mach_i960_xa:       str = "xa"; break;
+  case bfd_mach_i960_ca:       str = "ca"; break;
+  case bfd_mach_i960_ka_sa:    str = "ka"; break;
+  default:
+       return prt_num_mach (ap, machine);
+  }
+  sprintf (result, "%s:%s", ap->astr, str);
+  return result;
+}
+
+static boolean
+scan_960_mach (string, ap, archp, machinep, archspec)
+     char *string;
+     struct arch_print *ap;
+     enum bfd_architecture *archp;
+     unsigned long *machinep;
+     int archspec;
+{
+  unsigned long machine;
+
+  if (!archspec)
+    return false;
+  if (string[0] != ':')
+    return false;
+  string++;
+  if (string[0] == '\0')
+    return false;
+  if (string[0] == 'c' && string[1] == 'o' && string[2] == 'r' &&
+      string[3] == 'e' && string[4] == '\0')
+    machine = bfd_mach_i960_core;
+  else if (string[1] == '\0' || string[2] != '\0')     /* rest are 2-char */
+    return false;
+  else if (string[0] == 'k' && string[1] == 'b')
+    machine = bfd_mach_i960_kb_sb;
+  else if (string[0] == 's' && string[1] == 'b')
+    machine = bfd_mach_i960_kb_sb;
+  else if (string[0] == 'm' && string[1] == 'c')
+    machine = bfd_mach_i960_mc;
+  else if (string[0] == 'x' && string[1] == 'a')
+    machine = bfd_mach_i960_xa;
+  else if (string[0] == 'c' && string[1] == 'a')
+    machine = bfd_mach_i960_ca;
+  else if (string[0] == 'k' && string[1] == 'a')
+    machine = bfd_mach_i960_ka_sa;
+  else if (string[0] == 's' && string[1] == 'a')
+    machine = bfd_mach_i960_ka_sa;
+  else
+    return false;
+
+  if (archp)
+    *archp = ap->arch;
+  if (machinep)
+    *machinep = machine;
+  return true;
+}
+
+
+\f
+/* Determine whether two BFDs' architectures and machine types are
+   compatible.  Return merged architecture and machine type if nonnull
+   pointers.  */
+
+boolean
+bfd_arch_compatible (abfd, bbfd, archp, machinep)
+    bfd *abfd;
+    bfd *bbfd;
+    enum bfd_architecture *archp;
+    unsigned long *machinep;
+{
+  enum bfd_architecture archa, archb;
+  unsigned long macha, machb;
+  int pick_a;
+
+  archa = bfd_get_architecture (abfd);
+  archb = bfd_get_architecture (bbfd);
+  macha = bfd_get_machine (abfd);
+  machb = bfd_get_machine (bbfd);
+
+  if (archb == bfd_arch_unknown)
+       pick_a = 1;
+  else if (archa == bfd_arch_unknown)
+       pick_a = 0;
+  else if (archa != archb)
+       return false;                   /* Not compatible */
+  else {
+    /* Architectures are the same.  Check machine types.  */
+    if (macha == machb)                /* Same machine type */
+      pick_a = 1;
+    else if (machb == 0)       /* B is default */
+      pick_a = 1;
+    else if (macha == 0)       /* A is default */
+      pick_a = 0;
+    else switch (archa) {
+      /* If particular machine types of one architecture are not
+        compatible with each other, this is the place to put those tests
+        (returning false if incompatible).  */
+    case bfd_arch_i960:
+      /* The i960 has to distinct subspecies which may not interbreed:
+        CORE CA          
+        CORE KA KB MC
+        Any architecture on the same line is compatible, the one on
+        the right is the least restrictive.
+        */
+      /* So, if either is a ca then the other must be a be core or ca */
+      if (macha == bfd_mach_i960_ca) {
+       if (machb != bfd_mach_i960_ca &&
+           machb != bfd_mach_i960_core) {
+         return false;
+       }
+       pick_a = 1;
+      }
+      else      if (machb == bfd_mach_i960_ca) {
+       if (macha != bfd_mach_i960_ca &&
+           macha != bfd_mach_i960_core) {
+         return false;
+       }
+       pick_a = 0;
+      }
+      else {
+       /* This must be from the bottom row, so take the higest */
+       pick_a = (macha > machb);
+      }
+        
+        
+
+      break;
+
+      /* For these chips, as far as we care, "lower" numbers are included
+        by "higher" numbers, e.g. merge 68010 and 68020 into 68020,
+        386 and 486 into 486, etc.  This will need to change
+        if&when we care about things like 68332.  */
+    case bfd_arch_m68k:
+    case bfd_arch_ns32k:
+    case bfd_arch_i386:
+      pick_a = (macha > machb);
+      break;
+    
+      /* By default, pick first file's type, for lack of something better.  */
+    default:
+      pick_a = 1;
+    }
+  }
+
+  /* Set result based on our pick */
+  if (!pick_a) {
+    archa = archb;
+    macha = machb;
+  }
+  if (archp)
+    *archp = archa;
+  if (machinep)
+    *machinep = macha;
+
+  return true;
+}
diff --git a/bfd/archures.h b/bfd/archures.h
new file mode 100755 (executable)
index 0000000..db14d1d
--- /dev/null
@@ -0,0 +1,35 @@
+/* Intel 960 machine types */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+   Machine architecture and type definitions for BFD.
+
+   These definitions are only used inside the BFD package.  External programs
+   access them by calling bfd_scan_arch_mach() and bfd_arch_mach_string().
+
+   The architectures themselves are defined in bfd.h since they are an
+   enum needed for BFD structs.  Numeric machine types are simply used
+   as-is, e.g. 68020.  Non-numeric machine types like "i960CA" have
+   names in this file.  */
+
+/* $Id$ */
+
+
diff --git a/bfd/bfd.c b/bfd/bfd.c
new file mode 100644 (file)
index 0000000..d93bc72
--- /dev/null
+++ b/bfd/bfd.c
@@ -0,0 +1,882 @@
+                          /* -*- C -*- */
+
+/*** bfd -- binary file diddling routines by Gumby Wallace of Cygnus Support.
+           Every definition in this file should be exported and declared
+           in bfd.c.  If you don't want it to be user-visible, put it in
+           libbfd.c!
+*/
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+short _bfd_host_big_endian = 0x0100;
+       /* Accessing the above as (*(char*)&_bfd_host_big_endian), will
+        * return 1 if the host is big-endian, 0 otherwise.
+        * (See HOST_IS_BIG_ENDIAN_P in bfd.h.)
+        */
+
+
+
+\f
+/** Error handling
+    o - Most functions return nonzero on success (check doc for
+       precise semantics); 0 or NULL on error.
+    o - Internal errors are documented by the value of bfd_error.
+       If that is system_call_error then check errno.
+    o - The easiest way to report this to the user is to use bfd_perror.
+*/
+
+bfd_ec bfd_error = no_error;
+
+char *bfd_errmsgs[] = {"No error",
+                      "System call error",
+                      "Invalid target",
+                      "File in wrong format",
+                      "Invalid operation",
+                      "Memory exhausted",
+                      "No symbols",
+                      "No relocation info",
+                      "No more archived files",
+                      "Malformed archive",
+                      "Symbol not found",
+                      "File format not recognized",
+                      "File format is ambiguous",
+                          "Section has no contents",
+                      "#<Invalid error code>"
+                      };
+
+#if !defined(ANSI_LIBRARIES)
+char *
+strerror (code)
+     int code;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+
+  return (((code < 0) || (code >= sys_nerr)) ? "(unknown error)" :
+         sys_errlist [code]);
+}
+#endif /* not ANSI_LIBRARIES */
+
+char *
+bfd_errmsg (error_tag)
+     bfd_ec error_tag;
+{
+       extern int errno;
+
+  if (error_tag == system_call_error)
+    return strerror (errno);
+
+  if ((((int)error_tag <(int) no_error) ||
+       ((int)error_tag > (int)invalid_error_code)))
+    error_tag = invalid_error_code;/* sanity check */
+
+  return bfd_errmsgs [(int)error_tag];
+}
+
+void
+bfd_perror (message)
+     char *message;
+{
+  if (bfd_error == system_call_error)
+    perror(message);           /* must be system error then... */
+  else {
+    if (message == NULL || *message == '\0')
+      fprintf (stderr, "%s\n", bfd_errmsg (bfd_error));
+    else
+      fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error));
+  }
+}
+
+/* for error messages */
+char *
+bfd_format_string (format)
+     bfd_format format;
+{
+  if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) return "invalid";
+  
+  switch (format) {
+  case bfd_object: return "object"; /* linker/assember/compiler output */
+  case bfd_archive: return "archive"; /* object archive file */
+  case bfd_core: return "core";        /* core dump */
+  default: return "unknown";
+  }
+}
+\f
+/** Target configurations */
+
+extern bfd_target *target_vector[];
+
+/* Returns a pointer to the transfer vector for the object target
+   named target_name.  If target_name is NULL, chooses the one in the
+   environment variable GNUTARGET; if that is null or not defined then
+   the first entry in the target list is chosen.  Passing in the
+   string "default" or setting the environment variable to "default"
+   will cause the first entry in the target list to be returned. */
+
+bfd_target *
+bfd_find_target (target_name)
+     char *target_name;
+{
+  bfd_target **target;
+  extern char *getenv ();
+  char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
+
+  /* This is safe; the vector cannot be null */
+  if (targname == NULL || !strcmp (targname, "default"))
+    return target_vector[0];
+
+  for (target = &target_vector[0]; *target != NULL; target++) {
+    if (!strcmp (targname, (*target)->name))
+      return *target;
+  }
+
+  bfd_error = invalid_target;
+  return NULL;
+}
+
+/* Returns a freshly-consed, NULL-terminated vector of the names of all the
+   valid bfd targets.  Do not modify the names */
+
+char **
+bfd_target_list ()
+{
+  int vec_length= 0;
+  bfd_target **target;
+  char **name_list, **name_ptr;
+
+  for (target = &target_vector[0]; *target != NULL; target++)
+    vec_length++;
+
+  name_ptr = name_list = (char **) zalloc ((vec_length + 1) * sizeof (char **));
+
+  if (name_list == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  for (target = &target_vector[0]; *target != NULL; target++)
+    *(name_ptr++) = (*target)->name;
+
+  return name_list;
+}
+\f
+/** Init a bfd for read of the proper format.
+ */
+
+/* We should be able to find out if the target was defaulted or user-specified.
+   If the user specified the target explicitly then we should do no search.
+   I guess the best way to do this is to pass an extra argument which specifies
+   the DWIM. */
+
+/* I have chanegd this always to set the filepos to the origin before
+   guessing.  -- Gumby, 14 Februar 1991*/
+
+boolean
+bfd_check_format (abfd, format)
+     bfd *abfd;
+     bfd_format format;
+{
+#if obsolete
+  file_ptr filepos;
+#endif
+  bfd_target **target, *save_targ, *right_targ;
+  int match_count;
+
+  if (!bfd_read_p (abfd) ||
+      ((int)(abfd->format) < (int)bfd_unknown) ||
+      ((int)(abfd->format) >= (int)bfd_type_end)) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
+
+  /* presume the answer is yes */
+  abfd->format = format;
+
+#if obsolete
+  filepos = bfd_tell (abfd);
+#endif
+  bfd_seek (abfd, (file_ptr)0, SEEK_SET);      /* instead, rewind! */
+
+
+  right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+  if (right_targ) {
+    abfd->xvec = right_targ;           /* Set the target as returned */
+    return true;                       /* File position has moved, BTW */
+  }
+
+  /* This isn't a <format> file in the specified or defaulted target type.
+     See if we recognize it for any other target type.  (We check them
+     all to make sure it's uniquely recognized.)  */
+
+  save_targ = abfd->xvec;
+  match_count = 0;
+  right_targ = 0;
+
+  for (target = target_vector; *target != NULL; target++) {
+    bfd_target *temp;
+
+    abfd->xvec = *target;      /* Change BFD's target temporarily */
+#if obsolete
+    bfd_seek (abfd, filepos, SEEK_SET);        /* Restore original file position */
+#endif
+    bfd_seek (abfd, (file_ptr)0, SEEK_SET);
+    temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+    if (temp) {                                /* This format checks out as ok! */
+      right_targ = temp;
+      match_count++;
+    }
+  }
+
+  if (match_count == 1) {
+    abfd->xvec = right_targ;           /* Change BFD's target permanently */
+    return true;                       /* File position has moved, BTW */
+  }
+
+  abfd->xvec = save_targ;              /* Restore original target type */
+  abfd->format = bfd_unknown;          /* Restore original format */
+  bfd_error = ((match_count == 0) ? file_not_recognized :
+              file_ambiguously_recognized);
+#if  obsolete
+  bfd_seek (abfd, filepos, SEEK_SET);  /* Restore original file position */
+#endif
+  return false;
+}
+
+boolean
+bfd_set_format (abfd, format)
+     bfd *abfd;
+     bfd_format format;
+{
+  file_ptr filepos;
+
+  if (bfd_read_p (abfd) ||
+      ((int)abfd->format < (int)bfd_unknown) ||
+      ((int)abfd->format >= (int)bfd_type_end)) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
+
+  /* presume the answer is yes */
+  abfd->format = format;
+
+  filepos = bfd_tell (abfd);
+
+  if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
+    abfd->format = bfd_unknown;
+    bfd_seek (abfd, filepos, SEEK_SET);
+    return false;
+  }
+
+  return true;
+}
+\f
+/* Hack object and core file sections */
+
+sec_ptr
+bfd_get_section_by_name (abfd, name)
+     bfd *abfd;
+     char *name;
+{
+  asection *sect;
+  
+  for (sect = abfd->sections; sect != NULL; sect = sect->next)
+    if (!strcmp (sect->name, name)) return sect;
+  return NULL;
+}
+
+/* If you try to create a section with a name which is already in use,
+   returns the old section by that name instead. */
+sec_ptr
+bfd_make_section (abfd, name)
+     bfd *abfd;
+     char *name;
+{
+  asection *newsect;  
+  asection **  prev = &abfd->sections;
+  asection * sect = abfd->sections;
+  
+  if (abfd->output_has_begun) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+
+  while (sect) {
+    if (!strcmp(sect->name, name)) return sect;
+    prev = &sect->next;
+    sect = sect->next;
+  }
+
+  newsect = (asection *) zalloc (sizeof (asection));
+  if (newsect == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  newsect->name = name;
+  newsect->index = abfd->section_count++;
+  newsect->flags = SEC_NO_FLAGS;
+
+#if ignore     /* the compiler doesn't know that zalloc clears the storage */
+  newsect->userdata = 0;
+  newsect->next = (asection *)NULL;
+  newsect->relocation = (arelent *)NULL;
+  newsect->reloc_count = 0;
+  newsect->line_filepos =0;
+#endif
+  if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) {
+    free (newsect);
+    return NULL;
+  }
+
+  *prev = newsect;
+  return newsect;
+}
+
+/* Call operation on each section.  Operation gets three args: the bfd,
+   the section, and a void * pointer (whatever the user supplied). */
+
+/* This is attractive except that without lexical closures its use is hard
+   to make reentrant. */
+/*VARARGS2*/
+void
+bfd_map_over_sections (abfd, operation, user_storage)
+     bfd *abfd;
+     void (*operation)();
+     void *user_storage;
+{
+  asection *sect;
+  int i = 0;
+  
+  for (sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    (*operation) (abfd, sect, user_storage);
+
+  if (i != abfd->section_count)                /* Debugging */
+    abort();
+}
+
+boolean
+bfd_set_section_flags (abfd, section, flags)
+     bfd *abfd;
+     sec_ptr section;
+     flagword flags;
+{
+  if ((flags & bfd_applicable_section_flags (abfd)) != flags) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+   section->flags = flags;
+return true;
+}
+
+
+boolean
+bfd_set_section_size (abfd, ptr, val)
+     bfd *abfd;
+     sec_ptr ptr;
+     unsigned long val;
+{
+  /* Once you've started writing to any section you cannot create or change
+     the size of any others. */
+
+  if (abfd->output_has_begun) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  ptr->size = val;
+  
+  return true;
+}
+
+boolean
+bfd_set_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+void *location;
+     file_ptr offset;
+     int count;
+{
+       if (!(bfd_get_section_flags(abfd, section) &
+             SEC_HAS_CONTENTS)) {
+               bfd_error = no_contents;
+               return(false);
+       } /* if section has no contents */
+
+  if (BFD_SEND (abfd, _bfd_set_section_contents,
+           (abfd, section, location, offset, count))) {
+    abfd->output_has_begun = true;
+    return true;
+  }
+
+  return false;
+}
+
+boolean
+bfd_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     void *location;
+     file_ptr offset;
+     int count;
+{
+  if (section->flags & SEC_CONSTRUCTOR) {
+    memset(location, 0, count);
+    return true;
+  }
+  else {
+    return  (BFD_SEND (abfd, _bfd_get_section_contents,
+                      (abfd, section, location, offset, count)));
+  }
+}
+
+\f
+/** Some core file info commands */
+
+/* Returns a read-only string explaining what program was running when
+   it failed. */
+
+char *
+bfd_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  if (abfd->format != bfd_core) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+  return BFD_SEND (abfd, _core_file_failing_command, (abfd));
+}
+
+int
+bfd_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  if (abfd->format != bfd_core) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+  return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
+}
+
+boolean
+core_file_matches_executable_p (core_bfd, exec_bfd)
+     bfd *core_bfd, *exec_bfd;
+{
+  if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) {
+    bfd_error = wrong_format;
+    return false;
+  }
+
+  return BFD_SEND (core_bfd, _core_file_matches_executable_p, (core_bfd, exec_bfd));
+}
+\f
+/** Symbols */
+
+boolean
+bfd_set_symtab (abfd, location, symcount)
+     bfd *abfd;
+     asymbol **location;
+     unsigned int symcount;
+{
+  if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  bfd_get_outsymbols (abfd) = location;
+  bfd_get_symcount (abfd) = symcount;
+  return true;
+}
+
+/* returns the number of octets of storage required */
+unsigned int
+get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  if (abfd->format != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+
+  return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect));
+}
+
+unsigned int
+bfd_canonicalize_reloc (abfd, asect, location, symbols)
+     bfd *abfd;
+     sec_ptr asect;
+     arelent **location;
+     asymbol **symbols;
+{
+  if (abfd->format != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+
+  return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols));
+}
+
+void
+bfd_print_symbol_vandf(file, symbol)
+void *file;
+asymbol *symbol;
+{
+  flagword type = symbol->flags;
+  if (symbol->section != (asection *)NULL)
+    {
+      fprintf(file,"%08lx ", symbol->value+symbol->section->vma);
+    }
+  else 
+    {
+      fprintf(file,"%08lx ", symbol->value);
+    }
+  fprintf(file,"%c%c%c%c%c%c%c",
+         (type & BSF_LOCAL)  ? 'l':' ',
+         (type & BSF_GLOBAL) ? 'g' : ' ',
+         (type & BSF_IMPORT) ? 'i' : ' ',
+         (type & BSF_EXPORT) ? 'e' : ' ',
+         (type & BSF_UNDEFINED) ? 'u' : ' ',
+         (type & BSF_FORT_COMM) ? 'c' : ' ',
+         (type & BSF_DEBUGGING) ? 'd' :' ');
+
+}
+
+
+boolean
+bfd_set_file_flags (abfd, flags)
+     bfd *abfd;
+     flagword flags;
+{
+  if (abfd->format != bfd_object) {
+    bfd_error = wrong_format;
+    return false;
+  }
+
+  if (bfd_read_p (abfd)) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  if ((flags & bfd_applicable_file_flags (abfd)) != flags) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  bfd_get_file_flags (abfd) = flags;
+return true;
+}
+
+
+void
+bfd_set_reloc (ignore_abfd, asect, location, count)
+     bfd *ignore_abfd;
+     sec_ptr asect;
+     arelent **location;
+     unsigned int count;
+{
+  asect->orelocation  = location;
+  asect->reloc_count = count;
+}
+/*
+If an output_bfd is supplied to this function the generated image
+will be relocatable, the relocations are copied to the output file
+after they have been changed to reflect the new state of the world.
+There are two ways of reflecting the results of partial linkage in an
+output file; by modifying the output data in place, and by modifying
+the relocation record. Some native formats (eg basic a.out and basic
+coff) have no way of specifying an addend in the relocation type, so
+the addend has to go in the output data.  This is no big deal since in
+these formats the output data slot will always be big enough for the
+addend. Complex reloc types with addends were invented to solve just
+this problem.
+*/
+
+bfd_reloc_status_enum_type
+bfd_perform_relocation(abfd,
+                      reloc_entry,
+                      data,
+                      input_section,
+                      output_bfd)
+bfd *abfd;
+arelent *reloc_entry;
+void  *data;
+asection *input_section;
+bfd *output_bfd;
+{
+  bfd_vma relocation;
+  bfd_reloc_status_enum_type flag = bfd_reloc_ok;
+  bfd_vma relocation_before;
+  bfd_vma mask;
+  bfd_vma target_mask;
+  bfd_vma addr = reloc_entry->address ;
+  bfd_vma output_base = 0;
+  struct rint_struct *howto = reloc_entry->howto;
+  asection *reloc_target_output_section;
+  asection *reloc_target_input_section;
+  asymbol *symbol;
+
+  if (reloc_entry->sym_ptr_ptr) {
+    symbol = *( reloc_entry->sym_ptr_ptr);
+    if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) {
+      flag = bfd_reloc_undefined;
+    }
+  }
+  else {
+    symbol = (asymbol*)NULL;
+  }
+
+  if (howto->special_function) {
+    bfd_reloc_status_enum_type cont;
+    cont = howto->special_function(abfd,
+                                  reloc_entry,
+                                  symbol,
+                                  data,
+                                  input_section);
+    if (cont != bfd_reloc_continue) return cont;
+  }
+
+  /* 
+     Work out which section the relocation is targetted at and the
+     initial relocation command value.
+     */
+
+
+  if (symbol != (asymbol *)NULL){
+    if (symbol->flags & BSF_FORT_COMM) {
+      relocation = 0;
+    }
+    else {
+      relocation = symbol->value;
+    }
+    if (symbol->section != (asection *)NULL)
+      {
+       reloc_target_input_section = symbol->section;
+      }
+    else {
+      reloc_target_input_section = (asection *)NULL;
+    }
+  }
+  else if (reloc_entry->section != (asection *)NULL)
+    {
+      relocation = 0;
+      reloc_target_input_section = reloc_entry->section;
+    }
+  else {
+    relocation = 0;
+    reloc_target_input_section = (asection *)NULL;
+  }
+
+
+  if (reloc_target_input_section != (asection *)NULL) {
+
+    reloc_target_output_section =
+      reloc_target_input_section->output_section;
+
+    if (output_bfd && howto->partial_inplace==false) {
+      output_base = 0;
+    }
+    else {
+      output_base = reloc_target_output_section->vma;
+
+    }
+
+    relocation += output_base +   reloc_target_input_section->output_offset;
+  }
+
+  relocation += reloc_entry->addend ;
+
+
+  if(reloc_entry->address > (bfd_vma)(input_section->size)) 
+    {
+      return bfd_reloc_outofrange;
+    }
+         
+
+  if (howto->pc_relative == true)
+    {
+      /*
+        Anything which started out as pc relative should end up that
+        way too 
+        */
+
+      relocation -= 
+       output_base +   input_section->output_offset;
+
+    }
+
+  if (output_bfd!= (bfd *)NULL &&   howto->partial_inplace == false)  {
+    /*
+       This is a partial relocation, and we want to apply the relocation
+       to the reloc entry rather than the raw data. Modify the reloc
+       inplace to reflect what we now know.
+       */
+    reloc_entry->addend = relocation  ;
+    reloc_entry->section = reloc_target_input_section;
+    if (reloc_target_input_section != (asection *)NULL) {
+      /* If we know the output section we can forget the symbol */
+      reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
+    }
+    reloc_entry->address += 
+      input_section->output_offset;
+  }
+  else {
+    reloc_entry->addend = 0;
+
+
+    /* 
+       Either we are relocating all the way, or we don't want to apply
+       the relocation to the reloc entry (probably because there isn't
+       any room in the output format to describe addends to relocs)
+       */
+    relocation >>= howto->rightshift;
+    if (howto->bitsize == 32) {
+      mask = ~0;
+    }
+    else {
+      mask = (1L << howto->bitsize) - 1 ;
+      mask |= mask - 1;                /* FIXME, what is this?  */
+    }
+
+    relocation &= mask;
+
+    /* Shift everything up to where it's going to be used */
+   
+    relocation <<= howto->bitpos;
+    mask <<= howto->bitpos;
+    target_mask = ~mask;
+
+    /* Wait for the day when all have the mask in them */
+
+    BFD_ASSERT(howto->mask == mask);
+
+
+
+    relocation_before = relocation;
+
+
+    switch (howto->size)
+      {
+      case 0:
+       {
+         char x = bfd_getchar(abfd, (char *)data + addr);
+         relocation +=  x & mask;
+         bfd_putchar(abfd,
+                     ( x & target_mask) | ( relocation & mask),
+                     (unsigned char *) data + addr);
+       }
+       break;
+
+      case 1:
+       { 
+         short x = bfd_getshort(abfd, (bfd_byte *)data + addr);
+         relocation += x & mask;
+         bfd_putshort(abfd, ( x & target_mask) | (relocation & mask),
+                      (unsigned char *)data + addr);
+       }
+       break;
+      case 2:
+       {
+         long  x = bfd_getlong(abfd, (bfd_byte *) data + addr);
+         relocation +=  x & mask;
+         bfd_putlong(abfd, ( x & target_mask) | (relocation & mask),
+                     (bfd_byte *)data + addr);
+       }          
+       break;
+      case 3:
+       /* Do nothing */
+       break;
+      default:
+       return bfd_reloc_other;
+      }
+
+    /* See if important parts of the relocation were chopped to make
+       it fit into the relocation field. (ie are there any significant
+       bits left over after the masking ? */
+    if ((relocation_before & target_mask) != 0 &&
+       howto->complain_on_overflow == true) 
+      {
+       /* Its ok if the bit which fell off is */
+       return bfd_reloc_overflow;
+      }
+  }
+
+  return flag;
+}
+
+void
+bfd_assert(file, line)
+char *file;
+int line;
+{
+  printf("bfd assertion fail %s:%d\n",file,line);
+}
+
+
+boolean
+bfd_set_start_address(abfd, vma)
+bfd *abfd;
+bfd_vma vma;
+{
+  abfd->start_address = vma;
+  return true;
+}
+
+
+bfd_vma bfd_log2(x)
+bfd_vma x;
+{
+  bfd_vma  result = 0;
+  while ( (bfd_vma)(1<< result) < x)
+    result++;
+  return result;
+}
+
+/* bfd_get_mtime:  Return cached file modification time (e.g. as read
+   from archive header for archive members, or from file system if we have
+   been called before); else determine modify time, cache it, and
+   return it.  */
+
+long
+bfd_get_mtime (abfd)
+     bfd *abfd;
+{
+  FILE *fp;
+  struct stat buf;
+
+  if (abfd->mtime_set)
+    return abfd->mtime;
+
+  fp = bfd_cache_lookup (abfd);
+  if (0 != fstat (fileno (fp), &buf))
+    return 0;
+
+  abfd->mtime_set = true;
+  abfd->mtime = buf.st_mtime;
+  return abfd->mtime;
+}
diff --git a/bfd/bfd.doc b/bfd/bfd.doc
new file mode 100755 (executable)
index 0000000..3e3183e
--- /dev/null
@@ -0,0 +1,705 @@
+This file contains -*- Text -*-.
+
+BFD is a set of routines for reading and writing binary files.
+
+The user should call only the interface routines at the end of bfd.h.
+The one I'm working out of is /4/gumby/bfd/bfd.h
+
+       Sample "strip" program using BFD:
+
+       #include "bfd.h"
+
+       doit ()
+       {
+               ibfd = bfd_openr(...)
+               obfd = bfd_openw(...)
+               bfd_check_format (ibfd, object);
+               bfd_set_format (obfd, object);
+
+               bfd_set_arch_mach (obfd, ...)
+               bfd_set_start_address (obfd, ...)
+               etc...
+       
+               [optionally:
+                 asymbol * foo = malloc (get_symtab_upper_bound (ibfd));
+                 bfd_canonicalize_symtab (ibfd, foo);
+                 <sort foo, frob foo, etc, using asymbol def from bfd.h>
+                 bfd_set_symtab (obfd, foo, updated_symbol_count);
+               ]
+
+               bfd_map_over_sections (abfd, setup, NULL);
+               bfd_map_over_sections (abfd, cleaner, NULL);
+
+               bfd_close (obfd);
+               bfd_close (ibfd);
+       }
+
+       setup (ibfd, sect)
+       {
+           osect = make_section (obfd, bfd_section_name (ibfd, sect));
+           bfd_set_section_size (obfd, osect, bfd_section_size (ibfd, sect));
+           ...     
+       }
+
+       cleaner (ibfd, sect)
+       {
+           osect = bfd_get_section_by_name (obfd,
+                                          bfd_section_name (ibfd, sect));
+           bfd_copy_section (ibfd, sect, obfd, osect);
+           [perhaps: bfd_set_reloc (osect, NULL, 0); ]
+       }
+           
+
+\f
+BFD is a package for manipulating binary files required for developing
+programs.  It implements a group of structured operations designed to
+shield the programmer from the underlying representation of these
+binary files.  It understands object (compiled) files, archive
+libraries, and core files.  It is designed to work in a variety of
+target environments.
+
+To use the library, include bfd.h and link with libbfd.a.      
+
+A bfd iteself is a representation for a particular file.  It is opened
+in a manner similar to a file; code then manipulates it rather than
+the raw files.
+\f
+BFD makes a distinction between TARGETS (families of file formats) and
+FORMATS (individual file formats).  For instance, the "sun4os4" target
+can handle core, object and archive formats of files.  The exact
+layout of the different formats depends on the target environment.
+
+The target "default" means the first one known (usually used for
+environments that only support one format, or where the common format
+is known at compile or link time).  The target NULL means the one
+specified at runtime in the environment variable GNUTARGET; if that is
+null or not defined then the first entry in the target list is chosen
+(on output), or all targets are searched (on input) to find a matching
+one..
+
+Most programs should use the target NULL.
+
+There is a way to get a list of the names of all the targets:
+char**   bfd_target_list ()
+         This function returns a freshly-malloced list of all the
+         defined targets (or NULL if it could not malloc).  The names
+         are read-only.  You could use this to prompt the user, or
+         perhaps to error-check.
+
+char * bfd_format_string (bfd_format format)
+     This function will give you a printable, single-word description
+     (like "core" or "archive") for a bfd format.
+\f
+Error handling
+
+General rules:
+funtions which are boolean return true on success and false on failure
+(unless they're a predicate).  Functions which return pointers to
+objects return NULL on error.  The specifics are documented with each
+function.
+
+If a function fails, you should check the variable bfd_error.  If the
+value is no_error, then check the C variable errno just as you would
+with any other program.  The other values bfd_error may take on are
+documented in bfd.h.
+
+If you would prefer a comprehensible string for the error message, use
+the function bfd_errmsg:
+       char * bfd_errmsg (error_tag)
+This function returns a read-only string which documents the error
+code.  If the error code is no_error then it will return a string
+depending on the value of errno.
+
+bfd_perror() is like the perror() function except it understands
+bfd_error.
+\f
+Operations on bfds themselves
+
+bfd *  bfd_openr  (char *filename, char *target);
+bfd *  bfd_fdopenr  (int fd, char *target, char *filename);
+
+       Open a binary file for reading.  TARGET is the type of the file,
+       a char string like "sun4os4" or "elf".  (Note this is not the
+       "function" of the file, e.g. an object versus a core file
+       versus an archive, but instead describes how all these files
+       are encoded.)  Returns a new bfd or NULL upon failure.
+       
+bfd *  bfd_openw  (char *filename, char *target);
+
+       Open a file named `filename'  for writing.  If an existing
+       file has the same name, then it will be overwritten by a
+       successful bfd_close on the returned bfd.  Will return either
+       a new bfd or NULL upon failure.
+
+boolean  bfd_close  (bfd *abfd);
+       
+       Close a BFD opened for either reading or writing.  May involve
+       several filesystem operations, depending on the data format;
+       some things may not be known to the system until file-closing
+       time.  Returns true if it successfully wrote the file, false
+       if not.  A false return will not leave a partially-written
+       file behind with the name supplied to bfd_openw.
+
+       On a bfd open for reading will generally successfully
+       complete.
+
+       It is an error to call this on a file opened from inside an
+       archive.
+
+       FIXME -- show which error codes may be recoverable and
+       followed by another call to bfd_close!
+
+
+The defined formats are specified by the enumeration bfd_format.
+       
+boolean  bfd_check_format  (bfd *abfd, bfd_format format);
+
+       This routine must be called after a bfd_openr.  It sets up
+       internal data structures based on the contents of the file.
+       It returns FALSE if the file is not really in the specified
+       format.
+
+boolean  bfd_set_format  (bfd *abfd, bfd_format format);
+
+       This routine must be called after a bfd_openw.  It sets up
+       internal data structures for the proper format of file.
+       It returns FALSE if that format is not supported for output
+       (e.g. core files).
+
+The following macros may be used to obtain information about a bfd:
+
+bfd_get_filename -- returns a pointer to a null-terminated string
+       which names the bfd's file, or NULL if that is not known.
+       Don't side-effect this string!
+bfd_get_format -- returns the format code for the bfd.
+bfd_get_target -- returns the string which names the bfd's target.
+bfd_get_mtime -- returns an time_t indicating the modification time of an
+             input bfd, if that could be determined, or 0 of not.
+\f
+Object files have certain properties.  For input bfds, these
+properties may be read at any time.  For output bfds you should set
+them before you begin building any sections.
+       
+bfd_vma        bfd_get_start_address  (bfd *abfd);
+
+       Returns the address in an object file where execution will begin.
+
+boolean        bfd_set_start_address   (bfd *abfd, int vma);  
+
+       Set the address where execution will start in an object file.
+
+       If the address you select is incorrect for your architecture
+       (for instance, if it's required to be on a page_boundary and
+       your supplied starting address is not, then you may get the
+       invalid_operation error.  It is not always possible to
+       generate an error in this case.
+
+An object file has an architecture, which is the general instruction
+set of the instructions that it contains.  Architectures are defined in
+enum bfd_architecture in bfd.h.  New architectures can be added by
+putting them in the enum, updating architectures.c, and adding code to
+handle them for the object files that know that architecture.  The
+bfd_architecture values are not stored in files, but are only used
+within the BFD library and its callers.
+
+An object file also has a machine type, which is the specific machine
+within the architecture.  For example, if the architecture is bfd_arch_m68k,
+the Motorola 68000 series, then the machine type might be 68010, the mc68010
+chip.  For architectures such as the SPARC where specific versions of
+the architecture exist, the version number should probably be used.
+
+Particular object file formats may or may not store the machine architecture
+and type.  When copying an object file, you should copy these fields.
+Most callers of BFD will not need to know the particular values that
+these fields contain, but will instead propagate them from file to file,
+or compare the architectures from two files.
+
+enum bfd_architecture bfd_get_architecture (bfd *abfd);
+unsigned long bfd_get_machine     (bfd *abfd);
+
+       Get the machine type and architecture.
+
+boolean bfd_set_arch_mach         (bfd *abfd, enum bfd_architecture arch,
+                                   unsigned long machine);
+
+       Set the architecture and machine type.  The result is true
+       if the object file can exactly represent the specified type.
+       The result is false otherwise.
+
+boolean bfd_arch_compatible       (bfd *abfd, bfd *bbfd,
+                                   enum bfd_architecture *res_arch,
+                                   unsigned long *res_machine);
+
+       Decides whether two BFD's contain compatible architectures and
+       machine types.  If the result is TRUE and the res_arch and
+       res_machine pointers are non-NULL, the resulting "merged" 
+       architecture and machine type are returned through the pointers.
+       A linker could call this to decide whether two object files
+       can be linked, and to deterine the arch and machine type of
+       the resulting file.
+
+char * bfd_printable_arch_mach     (enum bfd_architecture arch,
+                                   unsigned long machine);
+
+       Returns a printable string that represents the particular
+       combination of architecture and machine type.
+
+boolean bfd_scan_arch_mach        (char *string, enum bfd_architecture *archp,
+                                   unsigned long *machinep);
+
+       Examines a printable string and tries to extract an
+       architecture and machine type from it.  The intended use is for
+       parsing specifications from the user, e.g. command line
+       arguments.  The result is true if a known architecture was
+       found, and the resulting architecture and machine type are
+       stored through the argument pointers.  Note that an
+       architecture scannable by this function might not be
+       representable by the particular object file format in use.
+       (i.e. bfd_set_arch_mach might return false).
+
+
+There are also a number of boolean flags which apply to object bfds.
+
+flagword bfd_get_file_flags       (bfd *abfd); 
+
+        returns a flagword containing the bfd's flags.
+
+boolean bfd_set_file_flags        (bfd *abfd, flagword flags,
+                                       boolean on_or_off); 
+
+       sets (on_or_off == true) or clears (on_or_off == false) the flags
+       specified by flagword.  All other flags are unaffected.
+       Some flag combinations don't make sense; It is not always
+       possible to detect them (since they may depend on other information).
+       Returns true if the flags could be modified as requested,
+       false if not.  Upon a false return, no flags will have been
+       altered.
+
+
+flagword bfd_applicable_file_flags     (bfd *abfd); 
+
+        returns a flagword with bits set for all the flags which are
+        meaningful for the bfd.
+
+The flags are:
+    HAS_RELOC -- file contains unresolved relocation information.
+    EXEC_P -- file can be executed.  These two may both be on in the
+             case of some dynamically-linked binaries.
+    HAS_LINENO -- has line number information.
+    HAS_DEBUG -- has debugging information.
+    HAS_SYMS -- has any symbols.
+    HAS_LOCALS -- has local symbols.
+    DYNAMIC -- binary is dynamically linked.
+    WP_TEXT -- text is write-protected
+    D_PAGED -- binary should be demand-paged
+
+These flags are one bit wide and may be OR-ed together with |.
+
+If you are building a large application with bfd there may be data
+specific to your program that you may wish to associate with a bfd.
+Rather than require you to build a parallel table structure, bfd
+provides a void* pointer in each bfd for arbitrary user data.  The
+macro bfd_usrdata (bfd *abfd) extracts these data; you may set them
+with = (ie bfd_usrdata (my_bfd) = frob_it (my_bfd, moon_phase);).
+\f
+Object and core files have sections.
+
+File sections are represented by opaque pointers.  You may map over
+the sections of a file or you may ask for one by name.  Note that not
+all files may have all the possible sections.
+
+Section pointers are valid from the time you get them until the bfd
+to which they refer is closed.
+
+When doing output, you must set up all the file's sections before
+outputting to any.   All that means is that all the file's sections
+must have already been created and their size set before output
+commences.
+
+Each section contains some small information, plus three chunks of
+data in the object file:  contents, relocation, and line numbers.
+In some file formats (e.g. a.out), the line number part is always
+empty, and line number information (if any) is instead recorded in
+the symbol table.
+
+sec_ptr        bfd_get_section_by_name (bfd *abfd, char *name); 
+       Returns a section named NAME, or NULL if none by that name
+       exists.  Works on input and output bfds.
+
+sec_ptr        bfd_make_section        (bfd *abfd, char *name); 
+       Creates a section named name in the output bfd abfd.
+       returns NULL if it cannot create the section (if, for instance,
+       the output format does not permit such a section).  If a
+       section with that name already exists, it is returned; a new
+       one with the same name is NOT created.
+
+unsigned int bfd_count_sections (bfd *abfd)
+
+       This function returns the number of sections in the bfd abfd.
+
+void   bfd_map_over_sections   (bfd *abfd, void (*operation)(),
+                                void *user_storage); 
+
+       This is how you operate on all sections of an input file.
+       Pass in a function pointer.  The function will be called for each
+       section of the file, in random order.  It will be passed
+       three arguments: the bfd, the sec_ptr for the section, and
+       whatever was passed in as user_storage.
+
+char * bfd_section_name        (bfd *abfd, sec_ptr ptr); 
+
+       Produces the name of a section, e.g. ".text" or ".data".
+       This will produce arbitrary names for files with extensible
+       section names (e.g. COFF, ELF) so don't assume that you will
+       only see a few values here.
+
+long   bfd_section_size        (bfd *abfd, sec_ptr ptr); 
+
+       The size of a section in bytes.  Result == -1 for error.
+
+boolean        bfd_set_section_size    (bfd *abfd, sec_ptr section unsigned long size);
+
+       Set the size of a section.  This must be done before any data
+       transfer is done for the section.
+
+bfd_vma        bfd_section_vma (bfd *abfd, sec_ptr ptr); 
+
+       Virtual memory address where a section "belongs".
+
+boolean        bfd_set_section_vma     (bfd *abfd, bfd_vma vma);
+
+       Set the virtual memory address of a section.
+
+int bfd_get_section_alignment  (bfd *abfd, sec_ptr ptr); 
+
+        returns the alignment of a section.  If alignment is not
+       possible, return value is undefined.
+       
+boolean bfd_set_section_alignment  (bfd *abfd, sec_ptr ptr, int alignment) 
+
+       returns true if it can set the section to the requested value.
+       Alignment is an integer; it refers to the power of two
+       specifying the byte boundary we want (ie 0 is byte-aligned; 4
+       is word aligned).  If the requested alignment is not available
+       any existing value is unchanged.
+
+Sections have properties just as object files may:
+
+flagword bfd_get_section_flags    (bfd *abfd, sec_ptr section); 
+
+        returns a flagword containing the section's flags.
+
+boolean bfd_set_section_flags     (bfd *abfd, sec_ptr section,
+                                       flagword flags, boolean on_or_off); 
+
+       sets (on_or_off == true) or clears (on_or_off == false) the flags
+       specified by flagword.  All other flags are unaffected.
+       Some flag combinations don't make sense; It is not always
+       possible to detect them (since they may depend on other information).
+       Returns true if the flags could me modified as requested,
+       false if not.  Unpon a false return, no flags will have been
+       altered.
+
+flagword bfd_applicable_section_flags  (bfd *abfd); 
+
+        returns a flagword with bits set for all the flags which are
+        meaningful for a section.
+
+The flags are:
+
+    SEC_BALIGN -- segment can be byte-aligned.
+    SEC_RELOC -- segment should be relocated.
+    SEC_ALLOC -- when converted into a memory image with the intent of
+           constructing a runable process, memory space will be
+           allocated for this section.
+    SEC_LOAD -- when converted into a memory image with the intent of
+           constructing a runable process, section contents will be
+           copied from the object file into memory.  When this flag
+           is set, SEC_ALLOC is guaranteed to also be set.
+    SEC_HAS_CONTENTS -- The contents of this section exist in the
+           object file.  Sections whose contents do not exist in the
+           object file may still have their contents read.  On read,
+           a segment filled with zeroes will be invented to satisfy
+           the read request.  It is an error to attempt to set the
+           contents of a section that has no contents.
+
+These last three probably need some explanation.  In a traditional,
+native unix object format, there are three real sections, text, data,
+and bss.  The text section will be allocated memory on exec, and will
+be loaded from file into memory on exec.  So the flags for a
+traditional unix text section would typically be at least (SEC_ALLOC |
+SEC_LOAD | SEC_HAS_CONTENTS).  The data section has basically these
+same traits.  The bss section, however is a little different.  It is
+not relocated, and it is not loaded from file on exec, but it is
+allocated memory on exec.  Thus, its flags would be more like
+(SEC_ALLOC).  It is possible to have a section which is the converse
+of the bss section.  That is, (SEC_HAS_CONTENTS & ~SEC_ALLOC).  This
+could be anything from profiling information or notes from one pass of
+a toolchain to another to time and version stamp information.
+
+Note that the section flags currently lack information on position
+dependance.
+
+boolean        bfd_get_section_contents  (bfd *abfd, sec_ptr section,
+                                  unsigned char *location,
+                                  int offset, int count); 
+
+       Stores count bytes from the section's contents starting at
+       offset from within those contents.  The values are stored into
+       location.  Returns true if it could do so.  Supplying invalid
+       values for offset and count will produce unpredictable results.
+
+boolean        bfd_set_section_contents (bfd *abfd, sec_ptr section,
+                                unsigned char *location,
+                                int offset, int count); 
+       Stores count bytes from location into offset within the
+       section contents.  You need not write all the contents contiguously
+       (that is, you may write words 5-7 followed by 0-4 if you
+       wish).  However once you start writing into a section, any
+       other sections into which you have previously written are
+       considered finished, and you may not write in them any more.
+
+*** Line numbers ***
+
+bfd_get_section_lineno_size (bfd *abfd, sec_ptr section);
+       Returns how many bytes of line numbers are associated with this
+       section.
+
+bfd_set_section_lineno_size (bfd *abfd, sec_ptr section, unsigned long val);
+       Sets the number of bytes of line numbers that this section should
+       contain.
+
+boolean bfd_get_section_linenos (bfd *abfd, sec_ptr section,
+                                unsigned char *location,
+                                int offset, int count); 
+       Same as get_section_contents, except that it works on the linenos
+       for this section.
+
+boolean bfd_set_section_linenos (bfd *abfd, sec_ptr section,
+                                unsigned char *location,
+                                int offset, int count); 
+       Same as set_section_contents, except that it works on the linenos
+       for this section.
+
+As with files, you may associate arbitrary program-specific data with
+a section of a bfd.  The following two functions are provided for
+manipulating these data:
+
+void * bfd_get_section_userdata (bfd *abfd, sec_ptr section)
+       Returns whatever was stored in section's user data, or NULL if nothing.
+
+boolean bfd_set_section_userdata (bfd *abfd, sec_ptr section, void *contents)
+       Set the section contents.  Returns true if it can, false if not.
+\f
+Core files
+
+Core files are currently only supported for reading.
+
+Apart from opening them, looking at the various sections (generally
+the .data, .stack, and .regs sections; maybe a .user_struct section
+eventually), you can make some queries about the status of the core
+file, detailed below.  The ".regs" section contains the general and
+floating point registers of the process that died, in some machine-
+specific order and format "intended to be unsurprising to someone who
+knows the machine".
+
+char *  bfd_core_file_failing_command  (bfd *abfd);
+
+       The command name of the program that failed, creating the core file.
+       The result is NULL if BFD can't figure out what the failing command was.
+
+int  bfd_core_file_failing_signal  (bfd *abfd);
+
+       The signal number which caused the program to die, causing the
+       core file to be created.  It will be positive if valid.
+
+boolean        core_file_matches_executable_p  (bfd *core_bfd, bfd *exec_bfd);
+
+       For debuggers, checks whether a core file "matches" (is likely to
+       have come from) an executable file.  This will not be perfect on
+       most systems, but will just provide a way to reject gross mismatches.
+\f
+Archives.
+
+An archive is a special file which can contain other files.
+Originally it was intended to be a general way to group files, the way
+tar is today.  But now it is used almost exclusively to hold object
+files.
+
+An archive may be opened for reading or writing just like any other
+bfd.  Once it is open for reading you may obtain bfds for each of the
+files contained within it with the following function:
+
+bfd *  bfd_openr_next_archived_file    (bfd *arch_bfd, bfd *last_file);
+
+       If called with NULL as the second argument, returns the first
+       file contained in the archive arch_bfd.  If called with a file
+       contained within arch_bfd, returns the one which follows that
+       one, or NULL if it was the last.  Returns NULL also if the
+       bfd supplied as last_file did not come from the archive arch_bfd.
+                                                      
+Any bfd open for read may be placed in an output archive.  When the
+output archive is closed, the contents will be placed into the
+archive.
+
+You control the order of files in an archive.  You set the first one
+with the following function:
+
+boolean bfd_set_archive_head (bfd *output_archive, bfd *new_head)
+
+       This function sets the first file in the archive
+       output_archive to be the bfd new_head.
+
+bfd's contain a pointer called next, which is bfd *.  It is used by
+bfd_close when an archive is closed to decide which file should next
+go into the archive.  So to place a group of files into an archive,
+open bfds for each of them, chain them together using the next pointer
+in the order you desire (be sure to store NULL into the final one's
+next pointer), then do bfd_set_archive_head with the head of the
+chain.  The next pointer may be freely smashed at any time; it is only
+looked at when closing an output archive.
+
+bfds for files contained within archives are normal bfds; you can do
+any input operations on them that you can do with a normal bfd.
+
+bfd_my_archive is a macro which takes an input bfd and returns NULL if
+it lives in the filesystem and a bfd if it is contained in an archive.
+In the latter case, the returned bfd is the archive itself.
+
+Archives containing only object files may have a "map" -- a table in
+the front which maps external symbols to the files which contain them.
+
+Archive maps will refer only to object files; if an archive contains a
+file which is not an archive that file will of course not appear in
+the map.        
+        
+boolean  bfd_has_map (bfd *archive_bfd)
+
+        This macro takes a bfd of an archive and returns true or
+        false depending on whether the bfd has a map.  For output
+        bfds this may be set to true or false, depending on whether
+        you want the map to be maintained or not.  For some targets,
+        setting this to false will cause no map to be generated; for
+        others it will merely cause an empty map to be created, since
+        a map is required by that target.
+
+For archives with maps you may use the following function:
+
+int bfd_get_next_mapent (bfd *abfd, int prev, char **name)
+
+    You may use this to step through all the entries in the archive
+    map.  Supply BFD_NO_MORE_SYMBOLS as the 'prev' entry to get the
+    first entry; then use successive returned values from this
+    function to get the succeeding ones.  The name of the next entry
+    will be stored through the pointer name.
+
+    This function returns BFD_NO_MORE_SYMBOLS when there are no more
+    entries or on error.
+bfd * bfd_get_elt_at_index (abfd, int index)
+
+    This function takes an index as returned by bfd_get_next_mapent
+    and returns the bfd which corresponds to that entry.  Returns NULL
+    on error.
+\f
+Symbol and relocation information.
+
+Symbol-table information is the area of greatest incompatibility.
+bfd has a canonical symbol representation; all formats are parsed into
+and out of it.
+
+Note that canonicalize_symtab takes a pointer to an array of pointers
+to canonical symbols.  This is necessary so that the end of the array
+can be marked with NULL.  You may shuffle the pointers and you may
+clobber the symbol contents.  But don't move the symbols themselves.
+
+unsigned int bfd_get_symtab_upper_bound        (bfd *abfd);
+
+       Returns the maximum number of bytes that would be taken by
+       the output of canonicalize_symtab.  Returns 0 on error.
+                                                             
+unsigned int bfd_canonicalize_symtab (bfd *abfd, asymbol **location);
+
+       Produces a symbol table in canonical format at LOCATION, which 
+       must be of size specified by get_symtab_upper_bound bytes.
+       Not all those bytes may be used.   Returns the number of
+       symbol pointers written.  Returns 0 upon error.
+
+boolean        bfd_set_symtab  (bfd *outbfd, asymbol **location,
+                       unsigned int symcount);
+
+       Takes a generic symbol table and an output bfd.  Used to set
+       the symbol table for an output bfd.  Do not change the table
+       after using this function (although the storage may be
+       reclaimed once the bfd has been closed).
+       
+If you're done with the symol table you can tell bfd about it by
+calling bfd_reclaim_symbol_table, which takes a bfd.  Calling this
+function will also reclaim any relocation entries you may have
+requested.  If you don't use this function bfd will keep around all
+symbol information until the bfd is closed.
+
+Similarly, relocations have a canonical format.  See the file bfd.h for
+the exact definition.  It is similar to the sun-4 relocation format.
+Please note that:
+o - Each relocation has a pointer to a generic symbol.
+o - Not all values of reloc_type are supported for all targets.  There
+    is a bitvector which explains which are; you can index into it by
+    relocation type.  The macro which extracts it is bfd_valid_reloc_types.
+
+Since relocation information is saved on a per-section basis, the
+interface is slightly different from that of the symbol table:
+
+unsigned int get_reloc_upper_bound     (bfd *abfd, sec_ptr asect);
+
+       Returns the maximum number of bytes that would be taken by
+       the output of canonicalize_reloc.  Returns 0 on error.
+
+unsigned int canonicalize_reloc (bfd *abfd, sec_ptr asect, arelent *location);
+
+       Produces a relocation table in canonical format at LOCATION,
+       which must be of size specified by get_reloc_upper_bound
+       bytes.  Not all those bytes may be used.  Returns the number
+       of entries written.  Returns 0 upon error.
+
+boolean        bfd_set_reloc   (bfd *outbfd, sec_ptr asect, arelent *location,
+                        unsigned int count);
+
+       Takes a generic reloc table and an output bfd.  Used to set
+       the reloc table for an output bfd.  Do not change the table
+       after using this function (although the storage may be
+       reclaimed once the bfd has been closed).
+\f
+Byte-swapping
+
+Unfortunately, not all machines have the same byte order.  Worse,
+storage layout is in general highly machine-dependent.  Although bfd
+can hide that from you in most cases, it cannot do so with the section
+contents, since they are totally uninterpreted.  Hence you must
+byte-swap those data yourself.  This is not usually much of an issue
+since you should just generate your data in the correct byte order.
+
+[THIS IS WRONG AND ALSO DOES NOT REFLECT THE CODE WHICH IS CORRECT]
+
+Fortunately, bfd can tell if byte-swapping or realignment is required
+at all!  The macro bfd_bit_twiddle_required takes a pointer to a bfd
+and returns true if byte-swapping is required, false if not.
+
+However if you don't wish to check this you may just use the following
+functions which will do the conversions required:
+
+
+long   bfd_getlong     (bfd *abfd, unsigned char *ptr);
+       bfd_putlong     (bfd *abfd, unsigned char *ptr, long time);
+
+short  bfd_getshort    (bfd *abfd, unsigned char *ptr);
+       bfd_putshort    (bfd *abfd, unsigned char *ptr, short stop);
+
+       These functions take a pointer that points to data which is,
+       or will be, part of a section contents.  They extract numbers
+       from the data, or insert numbers into the data.  The argument
+       or result is in the host's number format; the data stored at
+       the pointer or retrieved from it is in the target's number format.
+       Typically this transfer is either a no-op or is a byte-swap;
+       sometimes it involves an access to a "misaligned" location from
+       the host's point of view..
diff --git a/bfd/cache.c b/bfd/cache.c
new file mode 100644 (file)
index 0000000..39ffc7a
--- /dev/null
@@ -0,0 +1,200 @@
+/*** cache.c -- Allows you to have more bfds open than your system has fds. */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+/* These declarations should not be needed; libbfd.h's inclusion should
+   have handled it.
+   int fclose();
+   int fseek();
+*/
+
+
+/* The maximum number of FDs opened by bfd */
+#define BFD_CACHE_MAX_OPEN 10
+
+/* when this exceeds BFD_CACHE_MAX_OPEN, we get to work */
+static int open_files;
+
+static bfd *cache_sentinel;    /* Chain of bfds with active fds we've
+                                  opened */
+static void
+bfd_cache_delete();
+
+bfd *bfd_last_cache;
+\f
+
+static void
+close_one()
+{
+    bfd *kill = cache_sentinel;
+    if (kill == 0)             /* Nothing in the cache */
+       return ;
+
+    /* We can only close files that want to play this game.  */
+    while (!kill->cacheable) {
+       kill = kill->lru_prev;
+       if (kill == cache_sentinel) /* Nobody wants to play */
+          return ;
+    }
+
+    kill->where = ftell((FILE *)(kill->iostream));
+    bfd_cache_delete(kill);
+
+}
+/* Cuts the bfd abfd out of the chain in the cache */
+static void 
+snip (abfd)
+     bfd *abfd;
+{
+  abfd->lru_prev->lru_next = abfd->lru_next;
+  abfd->lru_next->lru_prev = abfd->lru_prev; 
+  if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
+}
+
+static void
+bfd_cache_delete (abfd)
+     bfd *abfd;
+{
+  fclose ((FILE *)(abfd->iostream));
+  snip (abfd);
+  abfd->iostream = NULL;
+  open_files--;
+}
+  
+static bfd *
+insert(x,y)
+bfd *x;
+bfd *y;
+{
+  if (y) {
+    x->lru_next = y;
+    x->lru_prev = y->lru_prev;
+    y->lru_prev->lru_next = x;
+    y->lru_prev = x;
+
+  }
+  else {
+    x->lru_prev = x;
+    x->lru_next = x;
+  }
+  return x;
+}
+\f
+
+/* Initialize a BFD by putting it on the cache LRU.  */
+void
+bfd_cache_init(abfd)
+bfd *abfd;
+{
+  cache_sentinel = insert(abfd, cache_sentinel);
+}
+
+void
+bfd_cache_close(abfd)
+bfd *abfd;
+{
+  /* If this file is open then remove from the chain */
+  if (abfd->iostream) 
+    {
+      bfd_cache_delete(abfd);
+    }
+}
+\f
+/* Call the OS to open a file for this BFD.  Returns the FILE *
+   (possibly null) that results from this operation.  Sets up the
+   BFD so that future accesses know the file is open.  */
+
+FILE *
+bfd_open_file (abfd)
+     bfd *abfd;
+{
+    abfd->cacheable = true;    /* Allow it to be closed later. */
+    if(open_files >= BFD_CACHE_MAX_OPEN) {
+       close_one();
+    }
+    switch (abfd->direction) {
+ case read_direction:
+ case no_direction:
+       abfd->iostream = (char *) fopen(abfd->filename, "r");
+       break;
+ case both_direction:
+ case write_direction:
+       if (abfd->opened_once == true) {
+           abfd->iostream = (char *) fopen(abfd->filename, "r+");
+           if (!abfd->iostream) {
+               abfd->iostream = (char *) fopen(abfd->filename, "w+");
+           }
+       } else {
+           /*open for creat */
+           abfd->iostream = (char *) fopen(abfd->filename, "w");
+           abfd->opened_once = true;
+       }
+       break;
+    }
+    if (abfd->iostream) {
+       open_files++;
+       bfd_cache_init (abfd);
+    }
+
+    return (FILE *)(abfd->iostream);
+}
+
+/* Find a file descriptor for this BFD.  If necessary, open it.
+   If there are already more than BFD_CACHE_MAX_OPEN files open, try to close
+   one first, to avoid running out of file descriptors.  */
+
+FILE *
+bfd_cache_lookup_worker (abfd)
+     bfd *abfd;
+{
+  if (abfd->my_archive) 
+    {
+      abfd = abfd->my_archive;
+    }
+  /* Is this file already open .. if so then quick exit */
+  if (abfd->iostream) 
+    {
+      if (abfd != cache_sentinel) {
+       /* Place onto head of lru chain */
+       snip (abfd);
+       cache_sentinel = insert(abfd, cache_sentinel);
+      }
+    }
+  /* This is a bfd without a stream -
+     so it must have been closed or never opened.
+     find an empty cache entry and use it.  */
+  else 
+    {
+
+      if (open_files >= BFD_CACHE_MAX_OPEN) 
+       {
+       close_one();
+    }
+
+      BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
+      fseek((FILE *)(abfd->iostream), abfd->where, false);
+    }
+bfd_last_cache = abfd;
+  return (FILE *)(abfd->iostream);
+}
diff --git a/bfd/coff-code.h b/bfd/coff-code.h
new file mode 100755 (executable)
index 0000000..2c1e289
--- /dev/null
@@ -0,0 +1,2514 @@
+/*
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option) any later version.
+
+BFD 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
+   BFD; see the file COPYING.  If not, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* $Id$ */
+/*
+Most of this hacked by Steve Chamberlain, steve@cygnus.com
+*/
+
+#include "archures.h"          /* Machine architectures and types */
+
+/* SUPPRESS 558 */
+/* SUPPRESS 590 */
+/* SUPPRESS 529 */
+/* SUPPRESS 530 */
+
+#define ALIGN(this, boundary) \
+  ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
+
+#define sp(x) bfd_h_put_x(abfd, x, &x)
+
+
+
+/*
+   Align an address by rounding it up to a power of two.  It leaves the
+   address unchanged if align == 0 (2^0 = alignment of 1 byte)
+*/
+#define        i960_align(addr, align) \
+       ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+
+/* All the swapping routines */
+
+static void
+swap_reloc(abfd, reloc)
+    bfd            *abfd;
+    RELOC          *reloc;
+{
+    sp(reloc->r_vaddr);
+    sp(reloc->r_symndx);
+    sp(reloc->r_type);
+}
+
+
+static void
+swap_filehdr(abfd, filehdr)
+    bfd            *abfd;
+    FILHDR         *filehdr;
+{
+    sp(filehdr->f_magic);
+    sp(filehdr->f_nscns);
+    sp(filehdr->f_timdat);
+    sp(filehdr->f_symptr);
+    sp(filehdr->f_nsyms);
+    sp(filehdr->f_opthdr);
+    sp(filehdr->f_flags);
+
+
+}
+
+static void
+swap_aouthdr(abfd, aouthdr)
+    bfd            *abfd;
+    AOUTHDR        *aouthdr;
+{
+
+    sp(aouthdr->magic);
+    sp(aouthdr->vstamp);
+    sp(aouthdr->tsize);
+    sp(aouthdr->dsize);
+    sp(aouthdr->bsize);
+    sp(aouthdr->entry);
+    sp(aouthdr->text_start);
+    sp(aouthdr->data_start);
+#ifdef I960
+    sp(aouthdr->tagentries);
+#endif
+}
+
+static void
+swap_scnhdr(abfd, scnhdr)
+    bfd            *abfd;
+    SCNHDR         *scnhdr;
+{
+    sp(scnhdr->s_vaddr);
+    sp(scnhdr->s_paddr);
+    sp(scnhdr->s_size);
+    sp(scnhdr->s_scnptr);
+    sp(scnhdr->s_relptr);
+    sp(scnhdr->s_lnnoptr);
+    sp(scnhdr->s_nreloc);
+    sp(scnhdr->s_nlnno);
+    sp(scnhdr->s_flags);
+#ifdef I960
+    sp(scnhdr->s_align);
+#endif
+}
+
+static void
+swap_name(abfd, ptr)
+    bfd            *abfd;
+    long           *ptr;
+{
+    if (ptr[0] == 0) {
+       /* There is an index which needs to be swapped */
+       bfd_h_put_x(abfd, ptr[1], (ptr + 1));
+    }
+    else {
+       /* This is a string .. leave it alone */
+    }
+}
+
+static void
+bfd_coff_swap_sym(abfd, se)
+    bfd            *abfd;
+    SYMENT         *se;
+{
+    swap_name(abfd, se->n_name);
+    bfd_h_put_x(abfd, se->n_value, &se->n_value);
+    bfd_h_put_x(abfd, se->n_scnum, &se->n_scnum);
+    bfd_h_put_x(abfd, se->n_type, &se->n_type);
+    bfd_h_put_x(abfd, se->n_sclass, &se->n_sclass);
+    bfd_h_put_x(abfd, se->n_numaux, &se->n_numaux);
+}
+
+static void
+bfd_coff_swap_aux(abfd, au, type, class)
+    bfd            *abfd;
+    AUXENT         *au;
+    int             type;
+    int             class;
+{
+    switch (class) {
+    case C_FILE:
+       swap_name(abfd, &au->x_file.x_n);
+       break;
+    case C_STAT:
+#ifdef C_LEAFSTAT
+    case C_LEAFSTAT:
+#endif
+    case C_HIDDEN:
+       if (type == T_NULL) {
+           sp(au->x_scn.x_scnlen);
+           sp(au->x_scn.x_nreloc);
+           sp(au->x_scn.x_nlinno);
+           break;
+       }
+    default:
+       sp(au->x_sym.x_tagndx);
+       sp(au->x_sym.x_tvndx);
+
+       if (ISARY(type)) {
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[0]);
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[1]);
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[2]);
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[3]);
+       }
+       else {
+           sp(au->x_sym.x_fcnary.x_fcn.x_lnnoptr);
+           sp(au->x_sym.x_fcnary.x_fcn.x_endndx);
+       }
+       if (ISFCN(type)) {
+           sp(au->x_sym.x_misc.x_fsize);
+       }
+       else {
+           sp(au->x_sym.x_misc.x_lnsz.x_lnno);
+           sp(au->x_sym.x_misc.x_lnsz.x_size);
+       }
+    }
+}
+
+static void
+bfd_coff_swap_lineno(abfd, lineno)
+    bfd            *abfd;
+    LINENO         *lineno;
+{
+    sp(lineno->l_addr.l_symndx);
+    sp(lineno->l_lnno);
+}
+
+
+/* void warning(); */
+extern asection abs_section;
+
+
+
+static int
+get_index(symbol)
+    asymbol        *symbol;
+{
+    return (int) symbol->value;
+}
+
+static void
+set_index(symbol, idx)
+    asymbol        *symbol;
+    unsigned int    idx;
+{
+    symbol->value = idx;
+}
+
+/*
+   initialize a section structure with information peculiar to this
+   particular implementation of coff
+*/
+
+static          boolean
+coff_new_section_hook(abfd_ignore, section_ignore)
+    bfd            *abfd_ignore;
+    asection       *section_ignore;
+{
+  return true;
+}
+/* actually it makes itself and its children from the file headers */
+static          boolean
+make_a_section_from_file(abfd, hdr)
+    bfd            *abfd;
+    struct scnhdr  *hdr;
+
+{
+    asection       *return_section;
+    {
+       char           *name = malloc(9);
+       if (name == NULL) {
+           bfd_error = no_memory;
+           return (BFD_FAILURE);
+       }                       /* on error */
+       strncpy(name, (char *) &hdr->s_name[0], 8);
+
+       return_section = bfd_make_section(abfd, name);
+       (return_section->name)[8] = 0;
+    }
+
+    /* s_paddr is presumed to be = to s_vaddr */
+#define assign(to, from) return_section->to = hdr->from
+    assign(vma, s_vaddr);
+    /* assign (vma, s_vaddr); */
+    assign(size, s_size);
+    assign(filepos, s_scnptr);
+    assign(rel_filepos, s_relptr);
+    assign(reloc_count, s_nreloc);
+#ifdef I960
+    {
+
+       assign(alignment_power, s_align);
+       {
+           unsigned int    i;
+           for (i = 0; i < 32; i++) {
+               if ((1 << i) >= (int) (return_section->alignment_power)) {
+                   return_section->alignment_power = i;
+                   break;
+               }
+           }
+       }
+    }
+#endif
+    assign(line_filepos, s_lnnoptr);
+    /*
+       return_section->linesize =   hdr->s_nlnno * sizeof (struct lineno);
+    */
+
+#undef assign
+    return_section->lineno_count = hdr->s_nlnno;
+    return_section->userdata = NULL;
+    return_section->next = (asection *) NULL;
+    if ((hdr->s_flags & STYP_TEXT) || (hdr->s_flags & STYP_DATA))
+       return_section->flags = (SEC_LOAD | SEC_ALLOC);
+    else if (hdr->s_flags & STYP_BSS)
+       return_section->flags = SEC_ALLOC;
+
+    if (hdr->s_nreloc != 0)
+       return_section->flags |= SEC_RELOC;
+    if (hdr->s_scnptr != 0)
+       return_section->flags |= SEC_HAS_CONTENTS;
+    return true;
+}
+
+
+static
+bfd_target     *
+coff_real_object_p(abfd, nscns, opthdr)
+    bfd            *abfd;
+    unsigned        nscns,
+                    opthdr;
+{
+  struct icofdata *tdata;
+  char           *file_info;   /* buffer for all the headers */
+  size_t          readsize;    /* length of file_info */
+  struct filehdr *filehdr;     /* points into file_info */
+  struct scnhdr  *sections;    /* points into file_info */
+  /*
+     OK, now we know the format, read in the filehdr, soi-disant "optional
+     header", and all the sections.
+     */
+  readsize = sizeof(struct filehdr)
+    + opthdr
+      + (nscns * sizeof(struct scnhdr));
+
+  file_info = malloc(readsize);
+  if (file_info == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+  if (bfd_seek(abfd, 0L, SEEK_SET) < 0)
+    return 0;
+  if (bfd_read((void *) file_info, 1, readsize, abfd) != readsize)
+    return 0;
+  filehdr = (struct filehdr *) file_info;
+  sections = (struct scnhdr *) (file_info + sizeof(struct filehdr) + opthdr);
+
+
+  swap_filehdr(abfd, filehdr);
+
+  /* Now copy data as required; construct all asections etc */
+  tdata = (struct icofdata *) malloc(sizeof(struct icofdata) +
+                                    sizeof(AOUTHDR));
+  if (tdata == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+  tdata->symbol_index_slew = 0;
+  tdata->relocbase =0;
+  tdata->raw_syment_count = 0;
+  tdata->raw_linenos = 0;
+  tdata->raw_syments = 0;
+  tdata->sym_filepos =0;
+  tdata->flags = filehdr->f_flags;
+  if (nscns != 0) {
+    unsigned int    i;
+    for (i = 0; i < nscns; i++) {
+      swap_scnhdr(abfd, sections + i);
+      make_a_section_from_file(abfd, sections + i);
+    }
+  }
+  /* Determine the machine architecture and type.  */
+  abfd->obj_machine = 0;
+  switch (filehdr->f_magic) {
+#ifdef MC68MAGIC
+  case MC68MAGIC:
+  case MC68DMAGIC:
+    abfd->obj_arch = bfd_arch_m68k;
+    abfd->obj_machine = 68020;
+    break;
+#endif
+#ifdef I960ROMAGIC
+  case I960ROMAGIC:
+  case I960RWMAGIC:
+    abfd->obj_arch = bfd_arch_i960;
+    switch (F_I960TYPE & filehdr->f_flags) 
+      {
+      default:
+      case F_I960CORE:
+       abfd->obj_machine = bfd_mach_i960_core;
+       break;
+      case F_I960KB:
+       abfd->obj_machine = bfd_mach_i960_kb_sb;
+       break;
+      case F_I960MC:
+       abfd->obj_machine = bfd_mach_i960_mc;
+       break;
+      case F_I960XA:
+       abfd->obj_machine = bfd_mach_i960_xa;
+       break;
+      case F_I960CA:
+       abfd->obj_machine = bfd_mach_i960_ca;
+       break;
+      case F_I960KA:
+       abfd->obj_machine = bfd_mach_i960_ka_sa;
+       break;
+
+      }
+    break;
+#endif
+
+  default:                     /* Unreadable input file type */
+    abfd->obj_arch = bfd_arch_obscure;
+    break;
+  }
+
+  if (!(filehdr->f_flags & F_RELFLG))
+    abfd->flags |= HAS_RELOC;
+  if ((filehdr->f_flags & F_EXEC))
+    abfd->flags |= EXEC_P;
+  if (!(filehdr->f_flags & F_LNNO))
+    abfd->flags |= HAS_LINENO;
+  if (!(filehdr->f_flags & F_LSYMS))
+    abfd->flags |= HAS_LOCALS;
+
+  abfd->tdata = (void *) tdata;
+  bfd_get_symcount(abfd) = filehdr->f_nsyms;
+  if (filehdr->f_nsyms)
+    abfd->flags |= HAS_SYMS;
+
+  tdata->sym_filepos = filehdr->f_symptr;
+  tdata->hdr = (struct aouthdr *) (file_info + sizeof(struct filehdr));
+
+  swap_aouthdr(abfd, tdata->hdr);
+
+  tdata->symbols = (coff_symbol_type *) NULL;
+  bfd_get_start_address(abfd) = opthdr ? exec_hdr(abfd)->entry : 0;
+
+  return abfd->xvec;
+}
+
+
+/* 
+Takes a bfd and a symbol, returns a pointer to the coff specific area
+of the symbol if there is one.
+*/
+static coff_symbol_type *
+coff_symbol_from(abfd, symbol)
+    bfd            *abfd;
+    asymbol        *symbol;
+{
+  if (symbol->the_bfd->xvec->flavour != bfd_target_coff_flavour_enum) 
+    return (coff_symbol_type *)NULL;
+
+  if (symbol->the_bfd->tdata == (void *)NULL)
+    return (coff_symbol_type *)NULL;
+
+  return  (coff_symbol_type *) symbol;
+}
+
+
+
+static bfd_target *
+coff_object_p(abfd)
+    bfd            *abfd;
+{
+    unsigned short  magic,
+                    nscns,
+                    opthdr;
+    bfd_error = system_call_error;
+
+    /* figure out how much to read */
+    if (bfd_read((void *) &magic, 1, sizeof(magic), abfd) != sizeof(magic))
+       return 0;
+
+    magic = bfd_h_getshort(abfd, (bfd_byte *) (&magic));
+
+    if (BADMAG(*((struct filehdr *) & magic))) {
+       bfd_error = wrong_format;
+       return 0;
+    }
+    if (bfd_read((void *) &nscns, 1, sizeof(nscns), abfd) != sizeof(nscns))
+       return 0;
+    nscns = bfd_h_getshort(abfd, (unsigned char *) &nscns);
+    if (bfd_seek(abfd, (file_ptr) & (((struct filehdr *) NULL)->f_opthdr), SEEK_SET)
+       < 0)
+       return (bfd_target *) NULL;
+    if (bfd_read((void *) &opthdr, 1, sizeof(opthdr), abfd) != sizeof(opthdr))
+       return (bfd_target *) NULL;
+    opthdr = bfd_h_getshort(abfd, (unsigned char *) &opthdr);
+
+    return coff_real_object_p(abfd, nscns, opthdr);
+}
+
+static          boolean
+coff_mkobject(abfd)
+    bfd            *abfd;
+{
+    char           *rawptr;
+
+    bfd_error = system_call_error;
+
+    /* Use an intermediate variable for clarity */
+    rawptr = zalloc(sizeof(struct icofdata) + sizeof(AOUTHDR));
+    if (rawptr == NULL) {
+       bfd_error = no_memory;
+       return false;
+    }
+    abfd->tdata = (void *) ((struct icofdata *) rawptr);
+    exec_hdr(abfd) = (AOUTHDR *) (rawptr + sizeof(struct icofdata));
+    obj_relocbase(abfd) =0;
+    return true;
+}
+
+
+
+static void
+coff_count_linenumbers(abfd)
+    bfd            *abfd;
+{
+    unsigned int    limit = bfd_get_symcount(abfd);
+    unsigned int    i;
+    asymbol       **p;
+    {
+       asection       *s = abfd->sections->output_section;
+       while (s) {
+           BFD_ASSERT(s->lineno_count == 0);
+           s = s->next;
+       }
+    }
+
+
+    for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) {
+       asymbol        *q_maybe = *p;
+       if (q_maybe->the_bfd->xvec->flavour == bfd_target_coff_flavour_enum) {
+           coff_symbol_type *q = coffsymbol(q_maybe);
+           if (q->lineno) {
+               /*
+                  This symbol has a linenumber, increment the owning
+                  section's linenumber count
+               */
+               alent          *l = q->lineno;
+               q->symbol.section->output_section->lineno_count++;
+               l++;
+               while (l->line_number) {
+                   q->symbol.section->output_section->lineno_count++;
+                   l++;
+               }
+           }
+       }
+    }
+}
+
+/*
+ This function returns true if the supplied SYMENT has an AUXENT with
+ a tagndx field which should be relocated.
+
+ The coff book says that all auxents have this and should be moved,
+ but all the actual implementations I've looked at do this ..
+ (sac@cygnus.com)
+
+*/
+static boolean
+uses_x_sym_x_tagndx_p(native)
+SYMENT *native;
+{
+    if (BTYPE(native->n_type) == T_STRUCT) return true;
+    if (BTYPE(native->n_type) == T_UNION) return true;
+    if (BTYPE(native->n_type) == T_ENUM)return true;
+    return false;
+}
+
+
+
+
+
+
+/* 
+This procedure runs through the native entries in a coff symbol table
+and links up all the elements which should point to one another, in
+particular these are:
+
+strtag, entag and untags have an auxent endindex which points to the
+first syment after the .eos. This is simple to do, we just keep a
+pointer to the symbol with the most recent pending strtag and patch it
+when we see the eos. This works since coff structs are never nested.
+
+ISFCN type entries have an endindex which points to the next static or
+extern in the table, thereby skipping the function contents.
+The coff book says that an ISFCN's tagindex
+points to the first .bf for the function, so far I havn't seen it
+used. We do this using the same mechanism as strtags.
+
+Each file entry has a value which points to the next file entry,
+the last file entry points to the first extern symbol in the table
+which is not an ISFCN.
+
+Each .bb entry points to the matching .eb entry, but these are nested
+so we keep a stack of them.
+
+The tagndx of .eos items points to the strtag attached to them, this
+is simply the last_tagndx again. 
+
+The tagndx of items with type strtag point to the defining struct.
+This bit is complicated; We know that a struct ref and def must be
+within the same file, so all the natives will be in the same vector.
+This means that we can subtracts two pointers and get the index
+differences between to items, used to work out the true index of the
+target. 
+
+We store in the name field of each syment the actual native index
+applied so we can dig it out through a pointer.
+
+
+*/
+static void
+coff_mangle_symbols(bfd_ptr)
+bfd *bfd_ptr;
+{
+  unsigned int symbol_count = bfd_get_symcount(bfd_ptr);
+  asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;
+  SYMENT *last_tagndx = (SYMENT *)NULL;
+  SYMENT *last_file = (SYMENT *)NULL;
+  SYMENT *last_fcn = (SYMENT *)NULL;
+  SYMENT *block_stack[50];
+  SYMENT **last_block = &block_stack[0];
+  boolean first_time = true;  
+  unsigned int symbol_index;
+  unsigned int native_index = 0;
+
+  for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) {
+    coff_symbol_type *coff_symbol_ptr =
+      coff_symbol_from(bfd_ptr, symbol_ptr_ptr[symbol_index]);
+    if (coff_symbol_ptr == (coff_symbol_type *)NULL) {
+      /* 
+        This symbol has no coff information in it, it will take up
+        only one slot in the output symbol table
+        */
+      native_index++;
+    }
+    else {
+      SYMENT *syment = coff_symbol_ptr->native;
+      if (syment == (SYMENT *)NULL) {
+       native_index++;
+      }
+      else {
+       /* Normalize the symbol flags */
+       if (coff_symbol_ptr->symbol.flags & BSF_FORT_COMM) {
+         /* a common symbol is undefined with a value */
+         syment->n_scnum = N_UNDEF;
+         syment->n_value = coff_symbol_ptr->symbol.value;
+       }
+       else if (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING) {
+         syment->n_value = coff_symbol_ptr->symbol.value;
+       }
+       else if (coff_symbol_ptr->symbol.flags & BSF_UNDEFINED) {
+         syment->n_scnum = N_UNDEF;
+         syment->n_value = 0;
+       }         
+       else if (coff_symbol_ptr->symbol.flags & BSF_ABSOLUTE) {
+         syment->n_scnum = N_ABS;
+         syment->n_value = coff_symbol_ptr->symbol.value;
+       }         
+       else {
+         syment->n_scnum =
+           coff_symbol_ptr->symbol.section->output_section->index+1;
+         syment->n_value = 
+           coff_symbol_ptr->symbol.value +
+             coff_symbol_ptr->symbol.section->output_offset +
+               coff_symbol_ptr->symbol.section->output_section->vma;
+       }
+
+
+       /* If this symbol ties up something then do it */
+
+       if (syment->n_sclass == C_FILE && last_file != (SYMENT *)NULL)
+         {
+           last_file->n_value = native_index;
+         }
+       else if ((syment->n_sclass == C_EXT 
+                 || syment->n_sclass == C_STAT 
+#ifdef C_LEAFEXT
+                 || syment->n_sclass == C_LEAFEXT 
+                 || syment->n_sclass == C_LEAFSTAT
+#endif
+                 )
+                && last_fcn != (SYMENT *)NULL) 
+         {
+           AUXENT *auxent = (AUXENT *)(last_fcn+1);
+           auxent->x_sym.x_fcnary.x_fcn.x_endndx = native_index;
+           last_fcn = (SYMENT *)NULL;
+
+         }
+       else if (syment->n_sclass == C_EOS && last_tagndx != (SYMENT*)NULL)
+         {
+           AUXENT *auxent = (AUXENT *)(last_tagndx+1);
+           /* Remember that we keep the native index in the offset 
+              so patch the beginning of the struct to point to this
+              */
+           auxent->x_sym.x_tagndx = last_tagndx->n_offset;
+           auxent->x_sym.x_fcnary.x_fcn.x_endndx =
+             native_index + syment->n_numaux + 1 ;
+           /* Now point the eos to the structure */
+           auxent = (AUXENT *)(syment+1);
+           auxent->x_sym.x_tagndx = last_tagndx->n_offset;
+             
+           
+         }
+       else if (syment->n_sclass == C_BLOCK 
+                && coff_symbol_ptr->symbol.name[1] == 'e') 
+         {
+           AUXENT *auxent = (AUXENT *)((*(--last_block))+1);
+           auxent->x_sym.x_fcnary.x_fcn.x_endndx = 
+             native_index + syment->n_numaux + 1;
+         }
+       if (syment->n_sclass == C_EXT 
+           && !ISFCN(syment->n_type) 
+           && first_time == true 
+           && last_file != (SYMENT *)NULL) {
+         /* This is the first external symbol seen which isn't a 
+            function place it in the last .file entry */
+         last_file->n_value = native_index;
+         first_time = false;
+       }
+#ifdef C_LEAFPROC
+       if (syment->n_sclass == C_LEAFPROC && syment->n_numaux == 2) {
+         AUXENT *auxent = (AUXENT *)(syment+2);
+         /* This is the definition of a leaf proc, we'll relocate the 
+         address */
+
+         auxent->x_bal.x_balntry +=
+             coff_symbol_ptr->symbol.section->output_offset + 
+           coff_symbol_ptr->symbol.section->output_section->vma ;
+       }
+#endif
+       /* If this symbol needs to be tied up then remember some facts */
+       if (syment->n_sclass == C_FILE) 
+         {
+           last_file = syment;
+         }
+       if (syment->n_numaux != 0) {
+         /*
+            If this symbol would like to point to something in the
+            future then remember where it is 
+            */
+         if (uses_x_sym_x_tagndx_p(syment)) {
+           /* 
+              If this is a ref to a structure then we'll tie it up 
+              now - there are never any forward refs for one 
+              */
+           if (syment->n_sclass == C_STRTAG ||
+               syment->n_sclass == C_ENTAG ||
+               syment->n_sclass == C_UNTAG) {
+             last_tagndx = syment;
+           }
+           else {
+             /*
+                This is a ref to a structure - the structure must
+                have been defined within the same file, and previous
+                to this point, so we can deduce the new tagndx
+                directly.
+                */
+             AUXENT *auxent = (AUXENT *)(syment+1);
+             bfd *bfd_ptr = coff_symbol_ptr->symbol.the_bfd;
+             SYMENT *base = obj_raw_syments(bfd_ptr);        
+             auxent->x_sym.x_tagndx = base[auxent->x_sym.x_tagndx].n_offset;
+
+           }
+         }
+         if (ISFCN(syment->n_type)) {
+           last_fcn = syment;
+         }
+         if (syment->n_sclass == C_BLOCK 
+             && coff_symbol_ptr->symbol.name[1] == 'b')
+           {
+             *last_block++ = syment;
+           }
+       }
+       syment->n_offset = native_index;
+       native_index = native_index + 1 + syment->n_numaux;
+      }
+    }
+  }
+}
+         
+         
+         
+
+         
+         
+
+static void
+coff_write_symbols(abfd)
+    bfd            *abfd;
+{
+  unsigned int    i;
+  unsigned int    limit = bfd_get_symcount(abfd);
+  unsigned int    written = 0;
+  SYMENT          dummy;
+  asymbol       **p;
+  unsigned int    string_size = 0;
+
+
+  /* Seek to the right place */
+  bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET);
+
+  /* Output all the symbols we have */
+
+  written = 0;
+  for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) {
+    asymbol        *symbol = *p;
+    coff_symbol_type *c_symbol = coff_symbol_from(abfd, symbol);
+
+    unsigned int    j;
+    SYMENT         *native;
+    if (c_symbol == (coff_symbol_type *) NULL ||
+       c_symbol->native == (SYMENT *) NULL) {
+      /*
+        This symbol has been created by the loader, or come from a non
+        coff format. It  has no native element to inherit, make our
+        own
+        */
+
+      native = &dummy;
+      native->n_type = T_NULL;
+#ifdef I960
+      native->n_flags = 0;
+#endif
+      if (symbol->flags & BSF_ABSOLUTE) {
+       native->n_scnum = N_ABS;
+       native->n_value = symbol->value;
+      }
+      else if (symbol->flags & (BSF_UNDEFINED | BSF_FORT_COMM)) {
+       native->n_scnum = N_UNDEF;
+       native->n_value = symbol->value;
+      }
+      else if (symbol->flags & BSF_DEBUGGING) {
+       /*
+          remove name so it doesn't take up any space
+          */
+       symbol->name = "";
+#if 0                          /* FIXME -- Steve hasn't decided what to do
+                                  with these */
+       /*
+          Don't do anything with debugs from the loader
+          */
+       native->n_scnum = N_DEBUG;
+#endif
+       continue;
+      }
+      else {
+       native->n_scnum = symbol->section->output_section->index + 1;
+       native->n_value = symbol->value +
+         symbol->section->output_section->vma +
+           symbol->section->output_offset;
+#ifdef I960
+       /* Copy the any flags from the the file hdr into the symbol  */
+       {
+         coff_symbol_type *c = coff_symbol_from(abfd, symbol);
+         if (c != (coff_symbol_type *)NULL) {
+           native->n_flags = c->symbol.the_bfd->flags;
+         }
+       }
+#endif
+       }
+
+
+
+#ifdef HASPAD1
+      native->pad1[0] = 0;
+      native->pad1[0] = 0;
+#endif
+
+      native->pad2[0] = 0;
+      native->pad2[1] = 0;
+
+      native->n_type = 0;
+      native->n_sclass = C_EXT;
+      native->n_numaux = 0;
+    }
+    else
+      /*
+        Does this symbol have an ascociated line number - if so then
+        make it remember this symbol index. Also tag the auxent of
+        this symbol to point to the right place in the lineno table
+        */
+      {
+       alent          *lineno = c_symbol->lineno;
+       native = c_symbol->native;
+       if (lineno) {
+         unsigned int    count = 0;
+         lineno[count].u.offset = written;
+         if (native->n_numaux) {
+           union auxent   *a = (union auxent *) (native + 1);
+           a->x_sym.x_fcnary.x_fcn.x_lnnoptr =
+             c_symbol->symbol.section->output_section->moving_line_filepos;
+         }
+         /*
+            And count and relocate all other linenumbers
+            */
+         count++;
+         while (lineno[count].line_number) {
+           lineno[count].u.offset +=
+             c_symbol->symbol.section->output_section->vma +
+               c_symbol->symbol.section->output_offset;
+           count++;
+         }
+         c_symbol->symbol.section->output_section->moving_line_filepos +=
+           count * sizeof(struct lineno);
+
+       }
+      }        /* if symbol new to coff */
+
+    /* Fix the symbol names */
+    {
+      unsigned int    name_length;
+      if (symbol->name == (char *) NULL) {
+       /*
+          coff symbols always have names, so we'll make one up
+          */
+       symbol->name = "strange";
+      }
+      name_length = strlen(symbol->name);
+      if (name_length <= SYMNMLEN) {
+       /* This name will fit into the symbol neatly */
+       strncpy(native->n_name, symbol->name, SYMNMLEN);
+      }
+      else {
+       native->n_offset = string_size + 4;
+       native->n_zeroes = 0;
+       string_size += name_length + 1;
+      }
+      {
+       unsigned int    numaux = native->n_numaux;
+       int             type = native->n_type;
+       int             class = native->n_sclass;
+       bfd_coff_swap_sym(abfd, native);
+       bfd_write((void *) native, 1, SYMESZ, abfd);
+       for (j = 0; j != native->n_numaux; j++) {
+         bfd_coff_swap_aux(abfd, native + j + 1, type, class);
+         bfd_write((void *) (native + j + 1), 1, AUXESZ, abfd);
+
+       }
+       /*
+          Reuse somewhere in the symbol to keep the index
+          */
+       set_index(symbol, written);
+       written += 1 + numaux;
+      }
+    }
+  } /* for each out symbol */
+
+  bfd_get_symcount(abfd) = written;
+  /* Now write out strings */
+
+  if (string_size) {
+    unsigned int    size = string_size + 4;
+    bfd_h_put_x(abfd, size, &size);
+    bfd_write((void *) &size, 1, sizeof(size), abfd);
+    for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) {
+      asymbol        *q = *p;
+      size_t          name_length = strlen(q->name);
+      if (name_length > SYMNMLEN) {
+       bfd_write((void *) (q->name), 1, name_length + 1, abfd);
+      }
+    }
+  }
+  else {
+    /* We would normally not write anything here, but we'll write
+       out 4 so that any stupid coff reader which tries to read
+       the string table even when there isn't one won't croak.
+       */
+
+    uint32e_type size = 4;
+    bfd_h_put_x(abfd, size, &size);
+    bfd_write((void *)&size, 1, sizeof(size), abfd);
+       
+  }
+
+}
+
+static void
+coff_write_relocs(abfd)
+    bfd            *abfd;
+{
+    asection       *s;
+    for (s = abfd->sections; s != (asection *) NULL; s = s->next) {
+       unsigned int    i;
+       arelent       **p = s->orelocation;
+       bfd_seek(abfd, s->rel_filepos, SEEK_SET);
+       for (i = 0; i < s->reloc_count; i++) {
+           struct reloc    n;
+           arelent        *q = p[i];
+           memset((PTR)&n, 0, sizeof(n));
+           n.r_vaddr = q->address + s->vma;
+           n.r_symndx = get_index((*(q->sym_ptr_ptr)));
+           n.r_type = q->howto->type;
+           swap_reloc(abfd, &n);
+           bfd_write((void *) &n, 1, RELSZ, abfd);
+       }
+    }
+}
+static void
+coff_write_linenumbers(abfd)
+    bfd            *abfd;
+{
+    asection       *s;
+    for (s = abfd->sections; s != (asection *) NULL; s = s->next) {
+       if (s->lineno_count) {
+           asymbol       **q = abfd->outsymbols;
+           bfd_seek(abfd, s->line_filepos, SEEK_SET);
+           /* Find all the linenumbers in this section */
+           while (*q) {
+               asymbol        *p = *q;
+               alent          *l = BFD_SEND(p->the_bfd, _get_lineno, (p->the_bfd, p));
+               if (l) {
+                   /* Found a linenumber entry, output */
+                   struct lineno   out;
+                   bzero( &out, sizeof(out));
+                   out.l_lnno = 0;
+                   out.l_addr.l_symndx = l->u.offset;
+                   bfd_coff_swap_lineno(abfd, &out);
+                   bfd_write((void *) &out, 1, LINESZ, abfd);
+                   l++;
+                   while (l->line_number) {
+                       out.l_lnno = l->line_number;
+                       out.l_addr.l_symndx = l->u.offset;
+                       bfd_coff_swap_lineno(abfd, &out);
+                       bfd_write((void *) &out, 1, LINESZ, abfd);
+                       l++;
+                   }
+               }
+               q++;
+           }
+       }
+    }
+}
+
+
+static asymbol *
+coff_make_empty_symbol(abfd)
+    bfd            *abfd;
+{
+    coff_symbol_type *new = (coff_symbol_type *) malloc(sizeof(coff_symbol_type));
+    if (new == NULL) {
+       bfd_error = no_memory;
+       return (NULL);
+    }                          /* on error */
+    new->native = 0;
+    new->lineno = (alent *) NULL;
+    new->symbol.the_bfd = abfd;
+    return &new->symbol;
+}
+
+static void
+coff_print_symbol(ignore_abfd, file, symbol, how)
+    bfd            *ignore_abfd;
+    FILE           *file;
+    asymbol        *symbol;
+    bfd_print_symbol_enum_type how;
+{
+    switch (how) {
+    case bfd_print_symbol_name_enum:
+       fprintf(file, "%s", symbol->name);
+       break;
+    case bfd_print_symbol_type_enum:
+       fprintf(file, "coff %lx %lx", (unsigned long) coffsymbol(symbol)->native,
+               (unsigned long) coffsymbol(symbol)->lineno);
+       break;
+    case bfd_print_symbol_all_enum:
+       {
+           char           *section_name = symbol->section == (asection *) NULL ?
+           "*abs" : symbol->section->name;
+           bfd_print_symbol_vandf((void *) file, symbol);
+
+           fprintf(file, " %-5s %s %s %s",
+                   section_name,
+                   coffsymbol(symbol)->native ? "n" : "g",
+                   coffsymbol(symbol)->lineno ? "l" : " ",
+                   symbol->name);
+       }
+
+
+       break;
+    }
+}
+static alent   *
+coff_get_lineno(ignore_abfd, symbol)
+    bfd            *ignore_abfd;
+    asymbol        *symbol;
+{
+    return coffsymbol(symbol)->lineno;
+}
+/*
+   Set flags and magic number of a coff file from architecture and machine
+   type.  Result is true if we can represent the arch&type, false if not.
+*/
+static          boolean
+coff_set_flags(abfd, magicp, flagsp)
+    bfd            *abfd;
+    unsigned       *magicp,
+                   *flagsp;
+{
+
+
+    switch (abfd->obj_arch) {
+
+#ifdef I960ROMAGIC
+
+    case bfd_arch_i960:
+
+       {
+           unsigned        flags;
+           *magicp = I960ROMAGIC;
+           /*
+              ((bfd_get_file_flags(abfd) & WP_TEXT) ? I960ROMAGIC :
+              I960RWMAGIC);   FIXME???
+           */
+           switch (abfd->obj_machine) {
+           case bfd_mach_i960_core:
+               flags = F_I960CORE;
+               break;
+           case bfd_mach_i960_kb_sb:
+               flags = F_I960KB;
+               break;
+           case bfd_mach_i960_mc:
+               flags = F_I960MC;
+               break;
+           case bfd_mach_i960_xa:
+               flags = F_I960XA;
+               break;
+           case bfd_mach_i960_ca:
+               flags = F_I960CA;
+               break;
+           case bfd_mach_i960_ka_sa:
+               flags = F_I960KA;
+               break;
+           default:
+               return false;
+           }
+           *flagsp = flags;
+           return true;
+       }
+       break;
+#endif
+#ifdef MC68MAGIC
+    case bfd_arch_m68k:
+       *magicp = MC68MAGIC;
+       return true;
+#endif
+#if M88DMAGIC
+    case bfd_arch_m88k:
+       *magicp = MC88DMAGIC;
+       return true;
+       break;
+#endif
+
+    default:                   /* Unknown architecture */
+       return false;
+    }
+
+    return false;
+}
+
+
+static          boolean
+coff_set_arch_mach(abfd, arch, machine)
+    bfd            *abfd;
+    enum bfd_architecture arch;
+    unsigned long   machine;
+{
+    unsigned        dummy1,
+                    dummy2;
+    abfd->obj_arch = arch;
+    abfd->obj_machine = machine;
+    if (arch != bfd_arch_unknown &&
+       coff_set_flags(abfd, &dummy1, &dummy2) != true)
+       return false;           /* We can't represent this type */
+    return true;               /* We're easy ... */
+}
+
+
+/* Calculate the file position for each section. */
+
+static void
+coff_compute_section_file_positions(abfd)
+    bfd            *abfd;
+{
+    asection       *current;
+    file_ptr        sofar = FILHSZ;
+    if (bfd_get_start_address(abfd)) {
+       /*
+          A start address may have been added to the original file. In this
+          case it will need an optional header to record it.
+       */
+       abfd->flags |= EXEC_P;
+    }
+    if (abfd->flags & EXEC_P)
+       sofar += AOUTSZ;
+
+
+    sofar += abfd->section_count * SCNHSZ;
+
+    for (current = abfd->sections; current != NULL; current = current->next) {
+       current->filepos = sofar;
+       /* Only add sections which have contents */
+       if (current->flags & SEC_HAS_CONTENTS)
+           sofar += current->size;
+    }
+    obj_relocbase(abfd) = sofar;
+}
+
+
+
+
+/* SUPPRESS 558 */
+/* SUPPRESS 529 */
+static          boolean
+coff_write_object_contents(abfd)
+    bfd            *abfd;
+{
+  struct filehdr  file_header;
+  asection       *current;
+  boolean         hasrelocs = false;
+  boolean         haslinno = false;
+  file_ptr        reloc_base;
+  file_ptr        lineno_base;
+  file_ptr        sym_base;
+  file_ptr        scn_base;
+  file_ptr        data_base;
+  unsigned long   reloc_size = 0;
+  unsigned long   lnno_size = 0;
+  asection       *text_sec = NULL;
+  asection       *data_sec = NULL;
+  asection       *bss_sec = NULL;
+  unsigned        magic,
+  flags;
+  bfd_error = system_call_error;
+
+
+  if(abfd->output_has_begun == false) {
+    coff_compute_section_file_positions(abfd);
+  }
+  scn_base = (file_ptr) (sizeof(struct filehdr)
+                        + ((abfd->flags & EXEC_P) ? sizeof(AOUTHDR) : 0));
+
+  if (bfd_seek(abfd, scn_base, SEEK_SET) != 0)
+    return false;
+  reloc_base = obj_relocbase(abfd);
+
+
+      
+
+
+  /*
+     Make a pass through the symbol table to count line number entries and
+     put them into the correct asections
+     */
+  coff_count_linenumbers(abfd);
+  data_base = scn_base;
+  /* Work out the size of the reloc and linno areas */
+
+  for (current = abfd->sections; current != NULL; current = current->next) {
+    reloc_size += current->reloc_count * sizeof(struct reloc);
+    lnno_size += current->lineno_count * sizeof(struct lineno);
+    data_base += sizeof(struct scnhdr);
+  }
+
+
+  lineno_base = reloc_base + reloc_size;
+  sym_base = lineno_base + lnno_size;
+
+  /* Indicate in each section->line_filepos its actual file address */
+  for (current = abfd->sections; current != NULL; current = current->next) {
+    if (current->lineno_count) {
+      current->line_filepos = lineno_base;
+      current->moving_line_filepos = lineno_base;
+      lineno_base += current->lineno_count * sizeof(struct lineno);
+
+    }
+    else {
+      current->line_filepos = 0;
+    }
+    if (current->reloc_count) {
+      current->rel_filepos = reloc_base;
+      reloc_base += current->reloc_count * sizeof(struct reloc);
+    }
+    else {
+      current->rel_filepos = 0;
+    }
+  }
+
+
+
+  bfd_seek(abfd,
+          (file_ptr) ((abfd->flags & EXEC_P) ?
+                      (FILHSZ + AOUTSZ) : FILHSZ),
+          SEEK_SET);
+  {
+#if 0
+    unsigned int    pad = abfd->flags & D_PAGED ? data_base : 0;
+#endif
+    unsigned int    pad = 0;
+    for (current = abfd->sections; current != NULL; current = current->next) {
+      SCNHDR          section;
+      strncpy(&(section.s_name[0]), current->name, 8);
+      section.s_vaddr = current->vma + pad;
+      section.s_paddr = current->vma + pad;
+      section.s_size = current->size - pad;
+      /*
+        If this section has no size or is unloadable then the scnptr
+        will be 0 too
+        */
+      if (current->size - pad == 0 ||
+         (current->flags & SEC_LOAD) == 0) {
+       section.s_scnptr = 0;
+
+      }
+      else {
+       section.s_scnptr = current->filepos;
+      }
+      section.s_relptr = current->rel_filepos;
+      section.s_lnnoptr = current->line_filepos;
+      section.s_nreloc = current->reloc_count;
+      section.s_nlnno = current->lineno_count;
+      if (current->reloc_count != 0)
+       hasrelocs = true;
+      if (current->lineno_count != 0)
+       haslinno = true;
+
+      if (!strcmp(current->name, _TEXT)) {
+       text_sec = current;
+       section.s_flags = STYP_TEXT; /* kind stupid optimisation */
+      }
+      else {
+
+       if (!strcmp(current->name, _DATA)) {
+         data_sec = current;
+         section.s_flags = STYP_DATA; /* kind stupid
+                                         optimisation */
+       }
+       else if (!strcmp(current->name, _BSS)) {
+         bss_sec = current;
+         section.s_flags = STYP_BSS; /* kind stupid optimisation */
+       }
+      }
+
+
+#ifdef I960
+      section.s_align = (current->alignment_power
+                        ? 1 << current->alignment_power
+                        : 0);
+
+#endif
+      swap_scnhdr(abfd, &section);
+      bfd_write((void *) (&section), 1, SCNHSZ, abfd);
+      pad = 0;
+    }
+
+  }
+  /* OK, now set up the filehdr... */
+
+  bfd_h_put_x(abfd, abfd->section_count, &file_header.f_nscns);
+  /*
+     We will NOT put a fucking timestamp in the header here. Every time you
+     put it back, I will come in and take it out again. I'm sorry. This
+     field does not belong here.  We fill it with a 0 so it compares the
+     same but is not a reasonable time. -- gnu@cygnus.com
+     */
+  /*
+     Well, I like it, so I'm conditionally compiling it in.
+     steve@cygnus.com
+     */
+#ifdef COFF_TIMESTAMP
+  bfd_h_put_x(abfd, time(0), &file_header.f_timdat);
+#else
+  bfd_h_put_x(abfd, 0, &file_header.f_timdat);
+#endif
+
+  if (bfd_get_symcount(abfd) != 0)
+    bfd_h_put_x(abfd, sym_base, &file_header.f_symptr);
+  else
+    bfd_h_put_x(abfd, 0, &file_header.f_symptr);
+
+  file_header.f_flags = 0;
+
+  if (abfd->flags & EXEC_P)
+    bfd_h_put_x(abfd, sizeof(AOUTHDR), &file_header.f_opthdr);
+  else
+    bfd_h_put_x(abfd, 0, &file_header.f_opthdr);
+
+  if (!hasrelocs)
+    file_header.f_flags |= F_RELFLG;
+  if (!haslinno)
+    file_header.f_flags |= F_LNNO;
+  if (0 == bfd_get_symcount(abfd))
+    file_header.f_flags |= F_LSYMS;
+  if (abfd->flags & EXEC_P)
+    file_header.f_flags |= F_EXEC;
+  if (!abfd->xvec->byteorder_big_p)
+    file_header.f_flags |= F_AR32WR;
+  /*
+     FIXME, should do something about the other byte orders and
+     architectures.
+     */
+
+  /* Set up architecture-dependent stuff */
+
+  magic = 0;
+  flags = 0;
+  coff_set_flags(abfd, &magic, &flags);
+  file_header.f_flags |= flags;
+
+  bfd_h_put_x(abfd, magic, &file_header.f_magic);
+  bfd_h_put_x(abfd, file_header.f_flags, &file_header.f_flags);
+
+  /* ...and the "opt"hdr... */
+#ifdef I960
+  bfd_h_put_x(abfd, (magic == I960ROMAGIC ? NMAGIC : OMAGIC),
+             &(exec_hdr(abfd)->magic));
+#endif
+#if M88
+  exec_hdr(abfd)->magic = PAGEMAGIC3;
+#endif
+
+  /* Now should write relocs, strings, syms */
+  obj_sym_filepos(abfd) = sym_base;
+
+  if (bfd_get_symcount(abfd) != 0) {
+    coff_mangle_symbols(abfd);
+    coff_write_symbols(abfd);
+    coff_write_linenumbers(abfd);
+    coff_write_relocs(abfd);
+  }
+  if (text_sec) {
+    bfd_h_put_x(abfd, text_sec->size, &exec_hdr(abfd)->tsize);
+    bfd_h_put_x(abfd,
+               text_sec->size ? text_sec->vma : 0,
+               &exec_hdr(abfd)->text_start);
+  }
+  if (data_sec) {
+    bfd_h_put_x(abfd, data_sec->size, &exec_hdr(abfd)->dsize);
+    bfd_h_put_x(abfd,
+               data_sec->size ? data_sec->vma : 0,
+               &exec_hdr(abfd)->data_start);
+  }
+  if (bss_sec) {
+    bfd_h_put_x(abfd, bss_sec->size, &exec_hdr(abfd)->bsize);
+  }
+  bfd_h_put_x(abfd, bfd_get_start_address(abfd), &exec_hdr(abfd)->entry);
+
+
+  /* now write them */
+  bfd_h_put_x(abfd, bfd_get_symcount(abfd), &file_header.f_nsyms);
+  if (bfd_seek(abfd, 0L, SEEK_SET) != 0)
+    return false;
+
+  bfd_write((void *) &file_header, 1, FILHSZ, abfd);
+
+  if (abfd->flags & EXEC_P) {
+
+    bfd_write((void *) exec_hdr(abfd), 1, AOUTSZ, abfd);
+  }
+  return true;
+}
+
+
+
+static          boolean
+coff_set_section_contents(abfd, section, location, offset, count)
+    bfd            *abfd;
+    sec_ptr         section;
+    void           *location;
+    file_ptr        offset;
+    size_t          count;
+{
+    if (abfd->output_has_begun == false)       /* set by bfd.c handler */
+       coff_compute_section_file_positions(abfd);
+
+    bfd_seek(abfd, (file_ptr) (section->filepos + offset), SEEK_SET);
+
+    if (count != 0) {
+       return (bfd_write(location, 1, count, abfd) == count) ? true : false;
+    }
+    return true;
+}
+static          boolean
+coff_get_section_contents(abfd, section, location, offset, count)
+    bfd            *abfd;
+    sec_ptr         section;
+    void           *location;
+    file_ptr        offset;
+    int             count;
+{
+    if (count == 0
+       || offset >= section->size
+       || bfd_seek(abfd, section->filepos + offset, SEEK_SET) == -1
+       || bfd_read(location, 1, count, abfd) != count) {
+       return (false);
+    }                          /* on error */
+    return (true);
+}                              /* coff_get_section_contents() */
+
+
+static          boolean
+coff_close_and_cleanup(abfd)
+    bfd            *abfd;
+{
+  if (!bfd_read_p(abfd))
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents(abfd))
+       return false;
+      break;
+    case bfd_object:
+      if (!coff_write_object_contents(abfd))
+       return false;
+      break;
+    default:
+      bfd_error = invalid_operation;
+      return false;
+    }
+
+#define cleaner(ptr) if (abfd->ptr) free (abfd->ptr)
+  cleaner(tdata);
+
+  if (abfd->my_archive)
+    cleaner(filename);
+
+#undef cleaner
+  return true;
+}
+
+
+
+
+
+
+static void    *
+buy_and_read(abfd, where, seek_direction, size)
+    bfd            *abfd;
+    file_ptr        where;
+    int             seek_direction;
+    size_t          size;
+{
+    void           *area = (void *) malloc(size);
+    if (!area) {
+       bfd_error = no_memory;
+       return (NULL);
+    }
+    bfd_seek(abfd, where, seek_direction);
+    if (bfd_read(area, 1, size, abfd) != size) {
+       bfd_error = system_call_error;
+       free(area);
+       return (NULL);
+    }                          /* on error */
+    return (area);
+}                              /* buy_and_read() */
+
+static void
+offset_symbol_indices(symtab, count, offset)
+    SYMENT         *symtab;
+    unsigned long   count;
+    long            offset;
+{
+    SYMENT         *end = symtab + count;
+    for (; symtab < end; ++symtab) {
+       if (symtab->n_sclass == C_FILE) {
+           symtab->n_value = 0;
+       }
+       else if (symtab->n_sclass == C_ALIAS) {
+           /*
+              These guys have indices in their values.
+           */
+           symtab->n_value += offset;
+
+       }
+       else if (symtab->n_numaux) {
+           /*
+              anybody else without an aux, has no indices.
+           */
+
+           if (symtab->n_sclass == C_EOS
+               || (BTYPE(symtab->n_type) == T_STRUCT
+                   && symtab->n_sclass != C_STRTAG)
+               || BTYPE(symtab->n_type) == T_UNION
+               || BTYPE(symtab->n_type) == T_ENUM) {
+
+               ((AUXENT *) (symtab + 1))->x_sym.x_tagndx += offset;
+
+           }                   /* These guys have a tagndx */
+           if (symtab->n_sclass == C_STRTAG
+               || symtab->n_sclass == C_UNTAG
+               || symtab->n_sclass == C_ENTAG
+               || symtab->n_sclass == C_BLOCK
+               || symtab->n_sclass == C_FCN
+               || ISFCN(symtab->n_type)) {
+
+               ((AUXENT *) (symtab + 1))->x_sym.x_fcnary.x_fcn.x_endndx += offset;
+
+           }                   /* These guys have an endndx */
+#ifndef I960
+           if (ISFCN(symtab->n_type)) {
+               ((AUXENT *) (symtab + 1))->x_sym.x_tvndx += offset;
+           }                   /* These guys have a tvndx.  I think...
+                                  (FIXME) */
+#endif                         /* Not I960 */
+
+       }                       /* if value, else if aux */
+       symtab += symtab->n_numaux;
+    }                          /* walk the symtab */
+
+    return;
+}                              /* offset_symbol_indices() */
+/* swap the entire symbol table */
+static void
+swap_raw_symtab(abfd, raw_symtab)
+    bfd            *abfd;
+    SYMENT         *raw_symtab;
+{
+    long            i;
+    SYMENT         *end = raw_symtab + bfd_get_symcount(abfd);
+    for (; raw_symtab < end; ++raw_symtab) {
+       bfd_coff_swap_sym(abfd, raw_symtab);
+
+       for (i = raw_symtab->n_numaux; i; --i, ++raw_symtab) {
+           bfd_coff_swap_aux(abfd,
+                             raw_symtab + 1,
+                             raw_symtab->n_type,
+                             raw_symtab->n_sclass);
+       }                       /* swap all the aux entries */
+    }                          /* walk the symbol table */
+
+    return;
+}                              /* swap_raw_symtab() */
+/*
+   read a symbol table into freshly mallocated memory, swap it, and knit the
+   symbol names into a normalized form. By normalized here I mean that all
+   symbols have an n_offset pointer that points to a NULL terminated string.
+   Oh, and the first symbol MUST be a C_FILE.  If there wasn't one there
+   before, put one there.
+*/
+
+static SYMENT  *
+get_normalized_symtab(abfd)
+    bfd            *abfd;
+{
+    SYMENT         *end;
+    SYMENT         *retval;
+    SYMENT         *s;
+    char           *string_table = NULL;
+    unsigned long   size;
+    unsigned long   string_table_size = 0;
+    /*
+       I used to SEEK_END here to read the symtab and string table all at
+       once.  This fails if this bfd is really an archive element.  Thus, the
+       somewhat convoluted approach to reading in the string table. xoxorich.
+    */
+    /*
+       $if ((bfd_seek(abfd, 0, SEEK_END) == -1) || ((end_of_file =
+       bfd_tell(abfd)) == -1) || (bfd_seek(abfd, obj_sym_filepos(abfd),
+       SEEK_SET) == -1) || ((beginning_of_symtab = bfd_tell(abfd)) == -1)) {
+    
+    bfd_error = system_call_error; return(NULL); }$
+    *//* on error */
+
+    /* $if ((size = end_of_file - beginning_of_symtab) == 0) {$ */
+
+    if ((size = bfd_get_symcount(abfd) * sizeof(SYMENT)) == 0) {
+       bfd_error = no_symbols;
+       return (NULL);
+    }                          /* no symbols */
+    /*
+       This is a hack.  Some tool chains fail to put a C_FILE symbol at the
+       beginning of the symbol table.  To make life simpler for our users, we
+       inject one if it wasn't there originally.
+    
+    We'd like to keep all of this bfd's native symbols in one block to keep
+       table traversals simple.  To do that, we need to know whether we will
+       be prepending the C_FILE symbol before we read the rest of the table.
+    */
+    if ((s = (SYMENT *) malloc(sizeof(SYMENT) * 2)) == NULL) {
+       bfd_error = no_memory;
+       return (NULL);
+    }                          /* on error */
+    if (bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET) == -1
+       || bfd_read(s, sizeof(SYMENT), 1, abfd) != sizeof(SYMENT)) {
+       bfd_error = system_call_error;
+       return (NULL);
+    }                          /* on error */
+    bfd_coff_swap_sym(abfd, s);
+
+    if (s->n_sclass == C_FILE) {
+       obj_symbol_slew(abfd) = 0;
+
+       if ((retval = (SYMENT *) malloc(size)) == NULL) {
+           bfd_error = no_memory;
+           return (NULL);
+       }                       /* on malloc error */
+    }
+    else {
+       unsigned long   namelength = 0;
+       char           *filename;
+       obj_symbol_slew(abfd) = 2;
+
+       if ((retval = (SYMENT *) malloc(size
+                                       + (obj_symbol_slew(abfd)
+                                          * sizeof(SYMENT)))) == NULL) {
+           bfd_error = no_memory;
+           return (NULL);
+       }                       /* on malloc error */
+       bzero((char *) retval, size + (obj_symbol_slew(abfd) * sizeof(SYMENT)));
+
+#define FILE_ENTRY_NAME        ".file"
+
+       if ((retval->n_offset = (int) malloc(strlen(FILE_ENTRY_NAME)
+                                            + 1)) == NULL) {
+           bfd_error = no_memory;
+           return (NULL);
+       }                       /* on malloc error */
+       strcpy((char *) retval->n_offset, FILE_ENTRY_NAME);
+       retval->n_sclass = C_FILE;
+       retval->n_scnum = N_DEBUG;
+       retval->n_numaux = 1;
+
+#undef FILE_ENTRY_NAME
+
+       if ((filename = bfd_get_filename(abfd)) == NULL) {
+           filename = "fake";
+       }                       /* if we know it's name */
+       if ((namelength = strlen(filename)) <= FILNMLEN) {
+           strncpy(((AUXENT *) (retval + 1))->x_file.x_fname, filename, FILNMLEN);
+       }
+       else {
+           if ((((AUXENT *) (retval + 1))->x_file.x_n.x_offset
+                = (int) malloc(namelength)) == NULL) {
+               bfd_error = no_memory;
+               return (NULL);
+           }                   /* on error */
+           strcpy((char *) (((AUXENT *) (retval + 1))->x_file.x_n.x_offset),
+                  filename);
+
+       }                       /* if "short" name */
+    }                          /* missing file entry. */
+
+    free(s);
+
+    if (bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET) == -1
+       || bfd_read(retval + obj_symbol_slew(abfd), size, 1, abfd) != size) {
+       bfd_error = system_call_error;
+       return (NULL);
+    }                          /* on read error */
+    /* mark the end of the symbols */
+    end = retval + obj_symbol_slew(abfd) + bfd_get_symcount(abfd);
+    /*
+       FIXME SOMEDAY.  A string table size of zero is very weird, but
+       probably possible.  If one shows up, it will probably kill us.
+    */
+
+    swap_raw_symtab(abfd, retval + obj_symbol_slew(abfd));
+
+    /* ...and normalize symbol names. */
+
+    for (s = retval + obj_symbol_slew(abfd); s < end; ++s) {
+
+       if (s->n_zeroes != 0) {
+           /*
+              This is a "short" name.  Make it long.
+           */
+           unsigned long   i = 0;
+           char           *newstring = NULL;
+           /*
+              find the length of this string without walking into memory
+              that isn't ours.
+           */
+
+           for (i = 0; i <= 8; ++i) {
+               if (s->n_name[i] == '\0') {
+                   break;
+               }               /* if end of string */
+           }                   /* possible lengths of this string. */
+
+           if ((newstring = malloc(++i)) == NULL) {
+               bfd_error = no_memory;
+               return (NULL);
+           }                   /* on error */
+           bzero(newstring, i);
+           strncpy(newstring, s->n_name, 8);
+           s->n_offset = (int) newstring;
+           s->n_zeroes = 0;
+
+       }
+       else {
+           if (string_table == NULL) {
+               /*
+                  NOTE: we don't read the string table until now because we
+                  don't necessarily know that we have one until now.
+               */
+               /*
+                  At this point we should be "seek"'d to the end of the
+                  symbols === the symbol table size.
+               */
+
+               if (bfd_read((char *) &string_table_size, sizeof(string_table_size), 1, abfd) != sizeof(string_table_size)) {
+                   bfd_error = system_call_error;
+                   return (NULL);
+               }               /* on error */
+               sp(string_table_size);
+
+               if ((string_table = malloc(string_table_size -= 4)) == NULL) {
+                   bfd_error = no_memory;
+                   return (NULL);
+               }               /* on mallocation error */
+               if (bfd_read(string_table, string_table_size, 1, abfd) != string_table_size) {
+                   bfd_error = system_call_error;
+                   return (NULL);
+               }               /* on error */
+           }                   /* have not yet read the string table. */
+           /*
+              This is a long name already. Just point it at the string in
+              memory.
+           */
+           s->n_offset = (int) (string_table - 4 + s->n_offset);
+       }                       /* switch on type of symbol name */
+
+       s += s->n_numaux;
+    }                          /* for each symbol */
+    /*
+       If we had to insert a C_FILE symbol, then everybody's indices are off
+       by 2, so correct them.
+    */
+
+    if (obj_symbol_slew(abfd) > 0) {
+       offset_symbol_indices(retval + 2, bfd_get_symcount(abfd), 2);
+
+       /* and let the world know there are two more of them. */
+       bfd_get_symcount(abfd) += 2;
+    }                          /* if we added a C_FILE */
+    obj_raw_syments(abfd) = retval;
+    obj_string_table(abfd) = string_table;
+
+    return (retval);
+}                              /* get_normalized_symtab() */
+
+static
+struct sec_struct *
+section_from_bfd_index(abfd, index)
+    bfd            *abfd;
+    int             index;
+{
+    if (index > 0) {
+       struct sec_struct *answer = abfd->sections;
+       while (--index) {
+           answer = answer->next;
+       }
+       return answer;
+    }
+    return 0;
+}
+
+static int
+coff_get_symcount_upper_bound(ignore_abfd)
+    bfd            *ignore_abfd;
+{
+    BFD_ASSERT(0);
+    return 0;
+}
+
+static          symindex
+coff_get_first_symbol(ignore_abfd)
+    bfd            *ignore_abfd;
+{
+    return 0;
+}
+
+static          symindex
+coff_get_next_symbol(abfd, oidx)
+    bfd            *abfd;
+    symindex        oidx;
+{
+    if (oidx == BFD_NO_MORE_SYMBOLS)
+       return BFD_NO_MORE_SYMBOLS;
+    return ++oidx >= bfd_get_symcount(abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
+}
+
+static char    *
+coff_symbol_name(abfd, idx)
+    bfd            *abfd;
+    symindex        idx;
+{
+    return (obj_symbols(abfd) + idx)->symbol.name;
+}
+
+static long
+coff_symbol_value(abfd, idx)
+    bfd            *abfd;
+    symindex        idx;
+{
+    return (obj_symbols(abfd) + idx)->symbol.value;
+}
+
+static          symclass
+coff_classify_symbol(abfd, idx)
+    bfd            *abfd;
+    symindex        idx;
+{
+    coff_symbol_type *sym = obj_symbols(abfd) + idx;
+    if ((sym->symbol.flags & BSF_FORT_COMM) != 0)
+       return bfd_symclass_fcommon;
+    if ((sym->symbol.flags & BSF_GLOBAL) != 0)
+       return bfd_symclass_global;
+    if ((sym->symbol.flags & BSF_DEBUGGING) != 0)
+       return bfd_symclass_debugger;
+    if ((sym->symbol.flags & BSF_UNDEFINED) != 0)
+       return bfd_symclass_undefined;
+
+    return bfd_symclass_unknown;
+}
+
+static          boolean
+coff_symbol_hasclass(abfd, idx, class)
+    bfd            *abfd;
+    symindex        idx;
+    symclass        class;
+{
+
+    coff_symbol_type *sym = obj_symbols(abfd) + idx;
+    switch (class) {
+    case bfd_symclass_fcommon:
+       return (sym->symbol.flags & BSF_FORT_COMM) ? true : false;
+    case bfd_symclass_global:
+       return (sym->symbol.flags & BSF_GLOBAL) ? true : false;
+    case bfd_symclass_debugger:
+       return (sym->symbol.flags & BSF_DEBUGGING) ? true : false;;
+    case bfd_symclass_undefined:
+       return (sym->symbol.flags & BSF_UNDEFINED) ? true : false;;
+    default:
+       return false;
+    }
+
+}
+
+
+
+
+static
+                boolean
+coff_slurp_line_table(abfd, asect)
+    bfd            *abfd;
+    asection       *asect;
+{
+    struct lineno  *native_lineno;
+    alent          *lineno_cache;
+    BFD_ASSERT(asect->lineno == (alent *) NULL);
+
+
+    native_lineno = (struct lineno *) buy_and_read(abfd,
+                                                  asect->line_filepos,
+                                                  SEEK_SET,
+                                          (size_t) (sizeof(struct lineno) *
+                                                    asect->lineno_count));
+    lineno_cache =
+       (alent *) malloc((size_t) ((asect->lineno_count + 1) * sizeof(alent)));
+    if (lineno_cache == NULL) {
+       bfd_error = no_memory;
+       return (BFD_FAILURE);
+    } {                                /* on error */
+       unsigned int    counter = 0;
+       alent          *cache_ptr = lineno_cache;
+       struct lineno  *src = native_lineno;
+       while (counter < asect->lineno_count) {
+           bfd_coff_swap_lineno(abfd, src);
+           cache_ptr->line_number = src->l_lnno;
+
+           if (cache_ptr->line_number == 0) {
+               coff_symbol_type *sym =
+               (coff_symbol_type *) (src->l_addr.l_symndx
+                                     + obj_symbol_slew(abfd)
+                                     + obj_raw_syments(abfd))->n_zeroes;
+               cache_ptr->u.sym = (asymbol *) sym;
+               sym->lineno = cache_ptr;
+           }
+           else {
+               cache_ptr->u.offset = src->l_addr.l_paddr
+                   - bfd_section_vma(abfd, asect);
+           }                   /* If no linenumber expect a symbol index */
+
+           cache_ptr++;
+           src++;
+           counter++;
+       }
+       cache_ptr->line_number = 0;
+
+    }
+    free(native_lineno);
+    asect->lineno = lineno_cache;
+    return true;
+}                              /* coff_slurp_line_table() */
+
+static SYMENT  *
+find_next_file_symbol(current, end)
+    SYMENT         *current;
+    SYMENT         *end;
+{
+    /* ignore the first symbol which is probably a C_FILE. */
+
+    current += current->n_numaux + 1;
+
+    for (; current < end; ++current) {
+       if (current->n_sclass == C_FILE) {
+           return (current);
+       }                       /* found one */
+       current += current->n_numaux;
+    }                          /* walk the remaining table */
+
+    /* not found */
+    return (end);
+}                              /* find_next_file_symbol() */
+/*
+   Note that C_FILE symbols can, and some do, have more than 1 aux entry.
+*/
+
+static void
+force_indices_file_symbol_relative(abfd, symtab)
+    bfd            *abfd;
+    SYMENT         *symtab;
+{
+    SYMENT         *end = symtab + bfd_get_symcount(abfd);
+    SYMENT         *current;
+    SYMENT         *next;
+    /* the first symbol had damn well better be a C_FILE. */
+    BFD_ASSERT(symtab->n_sclass == C_FILE);
+    symtab->n_value = 0;
+
+    for (current = find_next_file_symbol(symtab, end);
+        current < end;
+        current = next) {
+       offset_symbol_indices(current,
+                             ((next =
+                               find_next_file_symbol(current,
+                                                     end)) - current),
+                             symtab - current);
+    }                          /* walk the table */
+
+    return;
+}                              /* force_indices_file_symbol_relative() */
+
+static          boolean
+coff_slurp_symbol_table(abfd)
+    bfd            *abfd;
+{
+    SYMENT         *native_symbols;
+    coff_symbol_type *cached_area;
+    unsigned int   *table_ptr;
+    char           *string_table = (char *) NULL;
+    unsigned int    number_of_symbols = 0;
+    if (obj_symbols(abfd))
+       return true;
+    bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET);
+
+    /* Read in the symbol table */
+    if ((native_symbols = get_normalized_symtab(abfd)) == NULL) {
+       return (false);
+    }                          /* on error */
+    force_indices_file_symbol_relative(abfd, native_symbols);
+
+    /* Allocate enough room for all the symbols in cached form */
+    cached_area =
+       (coff_symbol_type *)
+       malloc((size_t) (bfd_get_symcount(abfd) * sizeof(coff_symbol_type)));
+
+    if (cached_area == NULL) {
+       bfd_error = no_memory;
+       return (BFD_FAILURE);
+    }                          /* on error */
+    table_ptr =
+       (unsigned int *)
+       malloc((size_t) (bfd_get_symcount(abfd) * sizeof(unsigned int)));
+
+    if (table_ptr == NULL) {
+       bfd_error = no_memory;
+       return (BFD_FAILURE);
+    } {                                /* on error */
+       coff_symbol_type *dst = cached_area;
+       unsigned int    last_native_index = bfd_get_symcount(abfd);
+       unsigned int    this_index = 0;
+       while (this_index < last_native_index) {
+           SYMENT         *src = native_symbols + this_index;
+           table_ptr[this_index] = number_of_symbols;
+           dst->symbol.the_bfd = abfd;
+
+           dst->symbol.name = (char *) src->n_offset;  /* which was normalized
+                                                          to point to a null
+                                                          terminated string. */
+           /*
+              We use the native name field to point to the cached field
+           */
+           src->n_zeroes = (int) dst;
+           dst->symbol.section = section_from_bfd_index(abfd, src->n_scnum);
+
+           switch (src->n_sclass) {
+#ifdef I960
+           case C_LEAFEXT:
+#if 0
+               dst->symbol.value = src->n_value - dst->symbol.section->vma;
+               dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
+               dst->symbol.flags |= BSF_NOT_AT_END;
+#endif
+               /* Fall through to next case */
+
+#endif
+
+           case C_EXT:
+               if (src->n_scnum == 0) {
+                   if (src->n_value == 0) {
+                       dst->symbol.flags = BSF_UNDEFINED;
+                   }
+                   else {
+                       dst->symbol.flags = BSF_FORT_COMM;
+                       dst->symbol.value = src->n_value;
+                   }
+               }
+               else {
+                   /*
+                      Base the value as an index from the base of the
+                      section
+                   */
+                   if (dst->symbol.section == (asection *) NULL) {
+                       dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL | BSF_ABSOLUTE;
+                       dst->symbol.value = src->n_value;
+                   }
+                   else {
+                       dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
+                       dst->symbol.value = src->n_value - dst->symbol.section->vma;
+                   }
+                   if (ISFCN(src->n_type)) {
+                       /*
+                          A function ext does not go at the end of a file
+                       */
+                       dst->symbol.flags |= BSF_NOT_AT_END;
+                   }
+               }
+
+               break;
+           case C_STAT:        /* static                        */
+#ifdef I960
+           case C_LEAFSTAT:    /* static leaf procedure        */
+#endif
+           case C_LABEL:       /* label                         */
+               dst->symbol.flags = BSF_LOCAL;
+               /*
+                  Base the value as an index from the base of the section
+               */
+               dst->symbol.value = src->n_value - dst->symbol.section->vma;
+               break;
+
+           case C_MOS: /* member of structure   */
+           case C_EOS: /* end of structure              */
+           case C_REGPARM:     /* register parameter            */
+           case C_REG: /* register variable             */
+#ifdef C_AUTOARG
+           case C_AUTOARG:     /* 960-specific storage class */
+#endif
+           case C_TPDEF:       /* type definition               */
+
+           case C_ARG:
+           case C_AUTO:        /* automatic variable */
+           case C_FIELD:       /* bit field */
+           case C_ENTAG:       /* enumeration tag               */
+           case C_MOE: /* member of enumeration         */
+           case C_MOU: /* member of union               */
+           case C_UNTAG:       /* union tag                     */
+
+               dst->symbol.flags = BSF_DEBUGGING;
+               dst->symbol.value = src->n_value;
+               break;
+
+           case C_FILE:        /* file name                     */
+           case C_STRTAG:      /* structure tag                 */
+               dst->symbol.flags = BSF_DEBUGGING;
+               dst->symbol.value = src->n_value;
+
+               break;
+           case C_BLOCK:       /* ".bb" or ".eb"                */
+           case C_FCN: /* ".bf" or ".ef"                */
+               dst->symbol.flags = BSF_LOCAL;
+               /*
+                  Base the value as an index from the base of the section
+               */
+               dst->symbol.value = src->n_value - dst->symbol.section->vma;
+
+               break;
+           case C_EFCN:        /* physical end of function      */
+           case C_NULL:
+           case C_EXTDEF:      /* external definition           */
+           case C_ULABEL:      /* undefined label               */
+           case C_USTATIC:     /* undefined static              */
+           case C_LINE:        /* line # reformatted as symbol table entry */
+           case C_ALIAS:       /* duplicate tag                 */
+           case C_HIDDEN:      /* ext symbol in dmert public lib */
+
+           default:
+
+               printf("SICK%d\n", src->n_sclass);
+               abort();
+               dst->symbol.flags = BSF_DEBUGGING;
+               dst->symbol.value = src->n_value;
+
+               break;
+           }
+
+
+
+
+           BFD_ASSERT(dst->symbol.flags != 0);
+
+           dst->native = src;
+
+           dst->symbol.udata = 0;
+           dst->lineno = (alent *) NULL;
+           this_index += src->n_numaux + 1;
+           dst++;
+           number_of_symbols++;
+       }                       /* walk the native symtab */
+
+    }                          /* bfdize the native symtab */
+
+    obj_symbols(abfd) = cached_area;
+    obj_raw_syments(abfd) = native_symbols;
+
+    bfd_get_symcount(abfd) = number_of_symbols;
+    obj_convert(abfd) = table_ptr;
+    /* Slurp the line tables for each section too */
+    {
+       asection       *p;
+       p = abfd->sections;
+       while (p) {
+           coff_slurp_line_table(abfd, p);
+           p = p->next;
+       }
+    }
+    return true;
+}                              /* coff_slurp_symbol_table() */
+
+static unsigned int
+coff_get_symtab_upper_bound(abfd)
+    bfd            *abfd;
+{
+    if (!coff_slurp_symbol_table(abfd))
+       return 0;
+
+    return (bfd_get_symcount(abfd) + 1) * (sizeof(coff_symbol_type *));
+}
+
+
+static unsigned int
+coff_get_symtab(abfd, alocation)
+    bfd            *abfd;
+    asymbol       **alocation;
+{
+    unsigned int    counter = 0;
+    coff_symbol_type *symbase;
+    coff_symbol_type **location = (coff_symbol_type **) (alocation);
+    if (!coff_slurp_symbol_table(abfd))
+       return 0;
+
+    for (symbase = obj_symbols(abfd); counter++ < bfd_get_symcount(abfd);)
+       *(location++) = symbase++;
+    *location++ = 0;
+    return bfd_get_symcount(abfd);
+}
+
+static unsigned int
+coff_get_reloc_upper_bound(abfd, asect)
+    bfd            *abfd;
+    sec_ptr         asect;
+{
+  if (bfd_get_format(abfd) != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+  return (asect->reloc_count + 1) * sizeof(arelent *);
+}
+
+
+static          boolean
+coff_slurp_reloc_table(abfd, asect, symbols)
+    bfd            *abfd;
+    sec_ptr         asect;
+    asymbol       **symbols;
+{
+  struct reloc   *native_relocs;
+  arelent        *reloc_cache;
+  if (asect->relocation)
+    return true;
+  if (asect->reloc_count == 0)
+    return true;
+  if (!coff_slurp_symbol_table(abfd))
+    return false;
+  native_relocs =
+    (struct reloc *) buy_and_read(abfd,
+                                 asect->rel_filepos,
+                                 SEEK_SET,
+                                 (size_t) (sizeof(struct reloc) *
+                                           asect->reloc_count));
+  reloc_cache = (arelent *)
+    malloc((size_t) (asect->reloc_count * sizeof(arelent)));
+
+  if (reloc_cache == NULL) {
+    bfd_error = no_memory;
+    return (BFD_FAILURE);
+  } {                          /* on error */
+    arelent        *cache_ptr;
+    struct reloc   *src;
+    for (cache_ptr = reloc_cache,
+        src = native_relocs;
+        cache_ptr < reloc_cache + asect->reloc_count;
+        cache_ptr++,
+        src++) {
+      asymbol        *ptr;
+      swap_reloc(abfd, src);
+      src->r_symndx += obj_symbol_slew(abfd);
+      cache_ptr->sym_ptr_ptr = symbols + obj_convert(abfd)[src->r_symndx];
+
+      ptr = *(cache_ptr->sym_ptr_ptr);
+      cache_ptr->address = src->r_vaddr;
+      /*
+        The symbols definitions that we have read in have been
+        relocated as if their sections started at 0. But the offsets
+        refering to the symbols in the raw data have not been
+        modified, so we have to have a negative addend to compensate.
+        */
+
+      if (ptr->the_bfd == abfd && ptr->section != (asection *) NULL) {
+       cache_ptr->addend = -ptr->section->vma;
+      }
+      else {
+       cache_ptr->addend = 0;
+      }
+
+      cache_ptr->address -= asect->vma;
+
+      cache_ptr->section = (asection *) NULL;
+
+#if I960
+      cache_ptr->howto = howto_table + src->r_type;
+#endif
+#if M88
+      if (src->r_type >= R_PCR16L && src->r_type <= R_VRT32) {
+       cache_ptr->howto = howto_table + src->r_type - R_PCR16L;
+      }
+      else {
+       BFD_ASSERT(0);
+      }
+#endif
+#if M68
+      cache_ptr->howto = howto_table + src->r_type;
+#endif
+
+    }
+
+  }
+
+  free(native_relocs);
+  asect->relocation = reloc_cache;
+  return true;
+}
+
+
+/* This is stupid.  This function should be a boolean predicate */
+static unsigned int
+coff_canonicalize_reloc(abfd, section, relptr, symbols)
+    bfd            *abfd;
+    sec_ptr         section;
+    arelent       **relptr;
+    asymbol       **symbols;
+{
+    arelent        *tblptr = section->relocation;
+    unsigned int    count = 0;
+    if (!(tblptr || coff_slurp_reloc_table(abfd, section, symbols)))
+       return 0;
+    tblptr = section->relocation;
+    if (!tblptr)
+       return 0;
+
+    for (; count++ < section->reloc_count;)
+       *relptr++ = tblptr++;
+
+    *relptr = 0;
+
+    return section->reloc_count;
+}
+
+
+
+
+
+/*
+   provided a bfd, a section and an offset into the section, calculate and
+   return the name of the source file and the line nearest to the wanted
+   location.
+*/
+
+static          boolean
+coff_find_nearest_line(abfd,
+                      section,
+                      symbols,
+                      offset,
+                      filename_ptr,
+                      functionname_ptr,
+                      line_ptr)
+    bfd            *abfd;
+    asection       *section;
+    asymbol       **symbols;
+    bfd_vma         offset;
+    char          **filename_ptr;
+    char          **functionname_ptr;
+    unsigned int   *line_ptr;
+{
+  static bfd     *cache_abfd;
+  static asection *cache_section;
+  static bfd_vma  cache_offset;
+  static unsigned int cache_i;
+  static alent   *cache_l;
+
+  unsigned int    i = 0;
+  struct icofdata *cof = obj_icof(abfd);
+  /* Run through the raw syments if available */
+  SYMENT         *p;
+  alent          *l;
+  unsigned int    line_base = 0;
+
+
+  *filename_ptr = 0;
+  *functionname_ptr = 0;
+  *line_ptr = 0;
+
+  /* Don't try and find line numbers in a non coff file */
+  if (abfd->xvec->flavour != bfd_target_coff_flavour_enum)
+    return false;
+
+  if (cof == (struct icofdata *)NULL)
+    return false;
+
+      
+  p = cof->raw_syments;
+  /*
+     I don't know for sure what's right, but this isn't it. First off, an
+     object file may not have any C_FILE's in it.  After
+     get_normalized_symtab(), it should have at least 1, the one I put
+     there, but otherwise, all bets are off.  Point #2, the first C_FILE
+     isn't necessarily the right C_FILE because any given object may have
+     many.  I think you'll have to track sections as they coelesce in order
+     to find the C_STAT symbol for this section. Then you'll have to work
+     backwards to find the previous C_FILE, or choke if you get to a C_STAT
+     for the same kind of section.  That will mean that the original object
+     file didn't have a C_FILE. xoxorich.
+     */
+
+#ifdef WEREBEINGPEDANTIC
+  return false;
+#endif
+
+
+
+  for (i = 0; i < cof->raw_syment_count; i++) {
+    if (p->n_sclass == C_FILE) {
+      /* File name is embeded in auxent */
+      /*
+        This isn't right.  The fname should probably be normalized
+        during get_normalized_symtab().  In any case, what was here
+        wasn't right because a SYMENT.n_name isn't an
+        AUXENT.x_file.x_fname. xoxorich.
+        */
+
+      *filename_ptr = ((AUXENT *) (p + 1))->x_file.x_fname;
+      break;
+    }
+    p += 1 + p->n_numaux;
+  }
+  /* Now wander though the raw linenumbers of the section */
+
+
+
+
+  /*
+     If this is the same bfd as we were previously called with and this is
+     the same section, and the offset we want is further down then we can
+     prime the lookup loop
+     */
+  if (abfd == cache_abfd &&
+      section == cache_section &&
+      offset >= cache_offset) {
+    i = cache_i;
+    l = cache_l;
+  }
+  else {
+    i = 0;
+    l = section->lineno;
+  }
+
+  for (; i < section->lineno_count; i++) {
+    if (l->line_number == 0) {
+      /* Get the symbol this line number points at */
+      coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
+      *functionname_ptr = coff->symbol.name;
+      if (coff->native) {
+       struct syment  *s = coff->native;
+       s = s + 1 + s->n_numaux;
+       /*
+          S should now point to the .bf of the function
+          */
+       if (s->n_numaux) {
+         /*
+            The linenumber is stored in the auxent
+            */
+         union auxent   *a = (union auxent *) (s + 1);
+         line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
+       }
+      }
+    }
+    else {
+      if (l->u.offset > offset)
+       break;
+      *line_ptr = l->line_number + line_base + 1;
+    }
+    l++;
+  }
+
+  cache_abfd = abfd;
+  cache_section = section;
+  cache_offset = offset;
+  cache_i = i;
+  cache_l = l;
+  return true;
+}
diff --git a/bfd/coff-i960.c b/bfd/coff-i960.c
new file mode 100644 (file)
index 0000000..bd31adb
--- /dev/null
@@ -0,0 +1,271 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define I960 1
+#include <ansidecl.h>
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "libcoff.h"           /* to allow easier abstraction-breaking */
+
+
+
+#include "intel-coff.h"
+
+#define CALLS   0x66003800     /* Template for 'calls' instruction     */
+#define BAL     0x0b000000     /* Template for 'bal' instruction       */
+#define BAL_MASK 0x00ffffff
+
+static bfd_reloc_status_enum_type 
+optcall_callback(abfd, reloc_entry, symbol_in, data, ignore_input_section)
+bfd *abfd;
+arelent *reloc_entry;
+asymbol *symbol_in;
+unsigned char *data;
+asection *ignore_input_section;
+{
+  /* This item has already been relocated correctly, but we may be
+   * able to patch in yet better code - done by digging out the
+   * correct info on this symbol */
+  bfd_reloc_status_enum_type result;
+  coff_symbol_type *cs = coffsymbol(symbol_in);
+
+  /* So the target symbol has to be off coff type, and the symbol 
+     has to have the correct native information within it
+     */
+  if ((cs->symbol.the_bfd->xvec->flavour != bfd_target_coff_flavour_enum)
+      || (cs->native == (struct syment *)NULL)) {
+     /* This is interesting, consider the case where we're outputting */
+     /* coff from a mix n match input, linking from coff to a symbol */
+     /* defined in a bout file will cause this match to be true. Should */
+     /* I complain ? - This will only work if the bout symbol is non */
+     /* leaf. */
+     result = bfd_reloc_dangerous;
+
+  }
+  else  {
+    switch (cs->native->n_sclass) 
+      {
+      case C_LEAFSTAT:
+      case C_LEAFEXT:
+       /* This is a call to a leaf procedure, replace instruction with a bal
+        to the correct location */
+       {
+        union auxent *aux = (union auxent *)(cs->native+2);
+         int word = bfd_getlong(abfd, data + reloc_entry->address);
+         BFD_ASSERT(cs->native->n_numaux==2);
+         /* We replace the original call instruction with a bal to */
+         /* the bal entry point - the offset of which is described in the */
+         /* 2nd auxent of the original symbol. We keep the native sym and */
+         /* auxents untouched, so the delta between the two is the */
+         /* offset of the bal entry point */
+         word = ((word + (aux->x_bal.x_balntry - cs->native->n_value))
+                 & BAL_MASK) | BAL;
+         bfd_putlong(abfd, word,  data+reloc_entry->address);
+       }
+       result = bfd_reloc_ok;
+       break;
+      case C_SCALL:
+       {
+         /* This is a call to a system call, replace with a calls to # */
+         BFD_ASSERT(0);
+       }
+       break;
+      default:
+       result = bfd_reloc_ok;
+       break;
+      }
+  }
+  return result;
+}
+
+
+
+static reloc_howto_type howto_table[] = 
+{
+  {0},
+  {1},
+  {2},
+  {3},
+  {4},
+  {5},
+  {6},
+  {7},
+  {8},
+  {9},
+  {10},
+  {11},
+  {12},
+  {13},
+  {14},
+  {15},
+  {16},
+
+  { (unsigned int) R_RELLONG, 0, 2, 32,false, 0, true, true, 0,"rellong", true, 0xffffffff},
+  {18},
+  {19},
+  {20},
+  {21},
+  {22},
+  {23},
+  {24},
+
+  {  R_IPRMED, 0, 2, 24,true,0, true, true,0,"iprmed ", true, 0x00ffffff},
+  {26},
+  {  R_OPTCALL, 0,2,24,true,0, true, true, optcall_callback, "optcall", true, 0x00ffffff},
+
+};
+
+
+
+#define BADMAG(x) I960BADMAG(x)
+#include "coff-code.h"
+
+
+
+bfd_target icoff_big_vec =
+{
+  "coff-Intel-big",            /* name */
+  bfd_target_coff_flavour_enum,
+  false,                       /* data byte order is little */
+  true,                                /* header byte order is big */
+
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  '/',                         /* ar_pad_char */
+  15,                          /* ar_max_namelen */
+  coff_close_and_cleanup,      /* _close_and_cleanup */
+  coff_set_section_contents,   /* bfd_set_section_contents */
+  coff_get_section_contents,   /* bfd_get_section_contents */
+  coff_new_section_hook,       /* new_section_hook */
+  _bfd_dummy_core_file_failing_command, /* _core_file_failing_command */
+  _bfd_dummy_core_file_failing_signal, /* _core_file_failing_signal */
+  _bfd_dummy_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_coff_armap,                /* bfd_slurp_armap */
+  _bfd_slurp_extended_name_table, /* bfd_slurp_extended_name_table*/
+#if 0                          /*  */
+  bfd_dont_truncate_arname,    /* bfd_truncate_arname */
+#else
+  bfd_bsd_truncate_arname,
+#endif
+
+  coff_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  coff_get_symtab,             /* canonicalize_symtab */
+  (void (*)())bfd_false,       /* bfd_reclaim_symbol_table */
+  coff_get_reloc_upper_bound,  /* get_reloc_upper_bound */
+  coff_canonicalize_reloc,     /* bfd_canonicalize_reloc */
+  (void (*)())bfd_false,       /* bfd_reclaim_reloc */
+
+  coff_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  coff_get_first_symbol,       /* bfd_get_first_symbol */
+  coff_get_next_symbol,                /* bfd_get_next_symbol */
+  coff_classify_symbol,                /* bfd_classify_symbol */
+  coff_symbol_hasclass,                /* bfd_symbol_hasclass */
+  coff_symbol_name,            /* bfd_symbol_name */
+  coff_symbol_value,           /* bfd_symbol_value */
+
+  _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, _bfd_dummy_target},
+  {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+     bfd_false},
+  coff_make_empty_symbol,
+  coff_print_symbol,
+  coff_get_lineno,
+  coff_set_arch_mach,
+  coff_write_armap,
+  bfd_generic_openr_next_archived_file,
+    coff_find_nearest_line,
+    bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+  };
+
+
+
+bfd_target icoff_little_vec =
+{
+  "coff-Intel-little",         /* name */
+  bfd_target_coff_flavour_enum,
+  false,                       /* data byte order is little */
+  false,                       /* header byte order is little */
+
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  '/',                         /* ar_pad_char */
+  15,                          /* ar_max_namelen */
+  coff_close_and_cleanup,      /* _close_and_cleanup */
+  coff_set_section_contents,   /* bfd_set_section_contents */
+  coff_get_section_contents,   /* bfd_get_section_contents */
+  coff_new_section_hook,       /* new_section_hook */
+  _bfd_dummy_core_file_failing_command, /* _core_file_failing_command */
+  _bfd_dummy_core_file_failing_signal, /* _core_file_failing_signal */
+  _bfd_dummy_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_coff_armap,                /* bfd_slurp_armap */
+  _bfd_slurp_extended_name_table, /* bfd_slurp_extended_name_table*/
+#if 1                          /*  */
+  bfd_dont_truncate_arname,    /* bfd_truncate_arname */
+#else
+  bfd_bsd_truncate_arname,
+#endif
+  coff_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  coff_get_symtab,             /* canonicalize_symtab */
+  (void (*)())bfd_false,       /* bfd_reclaim_symbol_table */
+  coff_get_reloc_upper_bound,  /* get_reloc_upper_bound */
+  coff_canonicalize_reloc,     /* bfd_canonicalize_reloc */
+  (void (*)())bfd_false,       /* bfd_reclaim_reloc */
+
+  coff_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  coff_get_first_symbol,       /* bfd_get_first_symbol */
+  coff_get_next_symbol,                /* bfd_get_next_symbol */
+  coff_classify_symbol,                /* bfd_classify_symbol */
+  coff_symbol_hasclass,                /* bfd_symbol_hasclass */
+  coff_symbol_name,            /* bfd_symbol_name */
+  coff_symbol_value,           /* bfd_symbol_value */
+
+  _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
+  _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* hdrs */
+
+  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, _bfd_dummy_target},
+  {bfd_false, coff_mkobject,   /* bfd_set_format */
+     _bfd_generic_mkarchive, bfd_false},
+  coff_make_empty_symbol,
+  coff_print_symbol,
+  coff_get_lineno,
+  coff_set_arch_mach,
+  coff_write_armap,
+  bfd_generic_openr_next_archived_file,
+  coff_find_nearest_line,
+    bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+};
+
+
diff --git a/bfd/coff-m88k.c b/bfd/coff-m88k.c
new file mode 100644 (file)
index 0000000..a261c8f
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* $Id$ */
+
+#define M88 1
+#include <ansidecl.h>
+#include <sysdep.h>
+#include "bfd.h"
+#include "libbfd.h"
+#include "libcoff.h"
+#include "m88k-bcs.h"
+
+
+static reloc_howto_type howto_table[] = 
+{
+/*     type    rtshift size    bitsize pc_rel  bitpos abs ovff sf  name partial inplace mask*/ 
+       R_PCR16L, 2,    1,      16,     true,   0, false, true, 0,"PCR16L", false, 0x0000ffff,
+       R_PCR26L, 2,    2,      26,     true,   0, false, true, 0,"PCR26L", false, 0x03ffffff,
+       R_VRT16, 0,     1,      16,     false,  0, false, true, 0,"VRT16", false, 0x0000ffff,
+       R_HVRT16,16,    1,      16,     false,  0, false, true, 0,"HVRT16", false, 0x0000ffff,
+       R_LVRT16, 0,    1,      16,     false,  0, false, true, 0,"LVRT16", false, 0x0000ffff,
+       R_VRT32,  0,    2,      32,     false,  0, false, true, 0,"VRT32", false, 0xffffffff,
+};
+
+
+
+#define BADMAG(x) MC88BADMAG(x)
+#include "coff-code.h"
+
+
+
+bfd_target m88k_bcs_vec =
+{
+  "m88k-bcs",          /* name */
+  bfd_target_coff_flavour_enum,
+  false,                       /* data byte order is little */
+  true,                                /* header byte order is big */
+
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  '/',                         /* ar_pad_char */
+  15,                          /* ar_max_namelen */
+  coff_close_and_cleanup,      /* _close_and_cleanup */
+  coff_set_section_contents,   /* bfd_set_section_contents */
+  coff_get_section_contents,   /* bfd_get_section_contents */
+  coff_new_section_hook,       /* new_section_hook */
+  _bfd_dummy_core_file_failing_command, /* _core_file_failing_command */
+  _bfd_dummy_core_file_failing_signal, /* _core_file_failing_signal */
+  _bfd_dummy_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_coff_armap,                /* bfd_slurp_armap */
+  _bfd_slurp_extended_name_table, /* bfd_slurp_extended_name_table*/
+#if 0                          /*  */
+  bfd_dont_truncate_arname,    /* bfd_truncate_arname */
+#else
+  bfd_bsd_truncate_arname,
+#endif
+
+  coff_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  coff_get_symtab,             /* canonicalize_symtab */
+  (void (*)())bfd_false,       /* bfd_reclaim_symbol_table */
+  coff_get_reloc_upper_bound,  /* get_reloc_upper_bound */
+  coff_canonicalize_reloc,     /* bfd_canonicalize_reloc */
+  (void (*)())bfd_false,       /* bfd_reclaim_reloc */
+
+  coff_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  coff_get_first_symbol,       /* bfd_get_first_symbol */
+  coff_get_next_symbol,                /* bfd_get_next_symbol */
+  coff_classify_symbol,                /* bfd_classify_symbol */
+  coff_symbol_hasclass,                /* bfd_symbol_hasclass */
+  coff_symbol_name,            /* bfd_symbol_name */
+  coff_symbol_value,           /* bfd_symbol_value */
+
+  _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, _bfd_dummy_target},
+  {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+     bfd_false},
+  coff_make_empty_symbol,
+  coff_print_symbol,
+  coff_get_lineno,
+  coff_set_arch_mach,
+  coff_write_armap,
+  bfd_generic_openr_next_archived_file,
+    coff_find_nearest_line,
+    bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+  };
+
+
+
diff --git a/bfd/cplus-dem.c b/bfd/cplus-dem.c
new file mode 100755 (executable)
index 0000000..edb9e39
--- /dev/null
@@ -0,0 +1,942 @@
+/* Demangler for GNU C++ 
+   Copyright (C) 1989 Free Software Foundation, Inc.
+   written by James Clark (jjc@jclark.uucp)
+   
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is for g++ 1.36.1 (November 6 version). It will probably
+   require changes for any other version.
+
+   Modified for g++ 1.36.2 (November 18 version).  */
+
+/* This file exports one function
+
+   char *cplus_demangle (const char *name)
+   
+   If `name' is a mangled function name produced by g++, then
+   a pointer to a malloced string giving a C++ representation
+   of the name will be returned; otherwise NULL will be returned.
+   It is the caller's responsibility to free the string which
+   is returned.
+
+   For example,
+   
+   cplus_demangle ("_foo__1Ai")
+   
+   returns
+
+   "A::foo(int)"
+
+   This file imports xmalloc and xrealloc, which are like malloc and
+   realloc except that they generate a fatal error if there is no
+   available memory. */
+
+/* #define nounderscore 1 /* define this is names don't start with _ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/* #include "misc.h" */
+
+#ifdef USG
+#include <memory.h>
+#else
+#define memcpy(s1, s2, n) strncpy(s1, s2, n) 
+#define memcmp(s1, s2, n) strncmp(s1, s2, n)
+#define strchr(s, c) index(s, c) 
+#endif
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifdef __STDC__
+extern char *cplus_demangle (const char *type);
+#else
+extern char *cplus_demangle ();
+#endif
+
+static char **typevec = 0;
+static int ntypes = 0;
+static int typevec_size = 0;
+
+static struct {
+  const char *in;
+  const char *out;
+} optable[] = {
+  "new", " new",
+  "delete", " delete",
+  "ne", "!=",
+  "eq", "==",
+  "ge", ">=",
+  "gt", ">",
+  "le", "<=",
+  "lt", "<",
+  "plus", "+",
+  "minus", "-",
+  "mult", "*",
+  "convert", "+",      /* unary + */
+  "negate", "-",       /* unary - */
+  "trunc_mod", "%",
+  "trunc_div", "/",
+  "truth_andif", "&&",
+  "truth_orif", "||",
+  "truth_not", "!",
+  "postincrement", "++",
+  "postdecrement", "--",
+  "bit_ior", "|",
+  "bit_xor", "^",
+  "bit_and", "&",
+  "bit_not", "~",
+  "call", "()",
+  "cond", "?:",
+  "alshift", "<<",
+  "arshift", ">>",
+  "component", "->",
+  "indirect", "*",
+  "method_call", "->()",
+  "addr", "&",         /* unary & */
+  "array", "[]",
+  "nop", "",                   /* for operator= */
+};
+
+/* Beware: these aren't '\0' terminated. */
+
+typedef struct {
+  char *b;                     /* pointer to start of string */
+  char *p;                     /* pointer after last character */
+  char *e;                     /* pointer after end of allocated space */
+} string;
+
+#ifdef __STDC__
+static void string_need (string *s, int n);
+static void string_delete (string *s);
+static void string_init (string *s);
+static void string_clear (string *s);
+static int string_empty (string *s);
+static void string_append (string *p, const char *s);
+static void string_appends (string *p, string *s);
+static void string_appendn (string *p, const char *s, int n);
+static void string_prepend (string *p, const char *s);
+#if 0
+static void string_prepends (string *p, string *s);
+#endif
+static void string_prependn (string *p, const char *s, int n);
+static int get_count (const char **type, int *count);
+static int do_args (const char **type, string *decl);
+static int do_type (const char **type, string *result);
+static int do_arg (const char **type, string *result);
+static int do_args (const char **type, string *decl);
+static void munge_function_name (string *name);
+#else
+static void string_need ();
+static void string_delete ();
+static void string_init ();
+static void string_clear ();
+static int string_empty ();
+static void string_append ();
+static void string_appends ();
+static void string_appendn ();
+static void string_prepend ();
+static void string_prepends ();
+static void string_prependn ();
+static int get_count ();
+static int do_args ();
+static int do_type ();
+static int do_arg ();
+static int do_args ();
+static void munge_function_name ();
+#endif
+
+char *
+cplus_demangle (type)
+     const char *type;
+{
+  string decl;
+  int n;
+  int success = 0;
+  int constructor = 0;
+  int const_flag = 0;
+  int i;
+  const char *p, *premangle;
+
+  if (type == NULL || *type == '\0')
+    return NULL;
+#ifndef nounderscore
+  if (*type++ != '_')
+    return NULL;
+#endif
+  p = type;
+  while (*p != '\0' && !(*p == '_' && p[1] == '_'))
+    p++;
+  if (*p == '\0')
+    {
+      /* destructor */
+      if (type[0] == '_' && type[1] == '$' && type[2] == '_')
+       {
+         unsigned int l = (strlen (type) - 3)*2 + 3 + 2 + 1;
+         char *tem = (char *) zalloc (l);
+         strcpy (tem, type + 3);
+         strcat (tem, "::~");
+         strcat (tem, type + 3);
+         strcat (tem, "()");
+         return tem;
+       }
+      /* static data member */
+      if (*type != '_' && (p = (char *) strchr (type, '$')) != NULL)
+       {
+         int n = strlen (type) + 2;
+         char *tem = (char *) xmalloc (n);
+         memcpy (tem, type, p - type);
+         strcpy (tem + (p - type), "::");
+         strcpy (tem + (p - type) + 2, p + 1);
+         return tem;
+       }
+      /* virtual table */
+      if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
+       {
+         int n = strlen (type + 4) + 14 + 1;
+         char *tem = (char *) xmalloc (n);
+         strcpy (tem, type + 4);
+         strcat (tem, " virtual table");
+         return tem;
+       }
+      return NULL;
+    }
+
+  string_init (&decl);
+
+  if (p == type)
+    {
+      if (!isdigit (p[2]))
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      constructor = 1;
+    }
+  else
+    {
+      string_appendn (&decl, type, p - type);
+      munge_function_name (&decl);
+    }
+  p += 2;
+
+  premangle = p;
+  switch (*p)
+    {
+    case 'C':
+      /* a const member function */
+      if (!isdigit (p[1]))
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      p += 1;
+      const_flag = 1;
+      /* fall through */
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      n = 0;
+      do
+       {
+         n *= 10;
+         n += *p - '0';
+         p += 1;
+       }
+      while (isdigit (*p));
+      if (strlen (p) < n)
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      if (constructor)
+       {
+         string_appendn (&decl, p, n);
+         string_append (&decl, "::");
+         string_appendn (&decl, p, n);
+       }
+      else
+       {
+         string_prepend (&decl, "::");
+         string_prependn (&decl, p, n);
+       }
+#ifndef LONGERNAMES
+      p = premangle;
+#else
+      p += n;
+#endif
+      success = do_args (&p, &decl);
+      if (const_flag)
+       string_append (&decl, " const");
+      break;
+    case 'F':
+      p += 1;
+      success = do_args (&p, &decl);
+      break;
+    }
+
+  for (i = 0; i < ntypes; i++)
+    if (typevec[i] != NULL)
+      free (typevec[i]);
+  ntypes = 0;
+  if (typevec != NULL)
+    {
+      free ((char *)typevec);
+      typevec = NULL;
+      typevec_size = 0;
+    }
+
+  if (success)
+    {
+      string_appendn (&decl, "", 1);
+      return decl.b;
+    }
+  else
+    {
+      string_delete (&decl);
+      return NULL;
+    }
+}
+
+static int
+get_count (type, count)
+     const char **type;
+     int *count;
+{
+  if (!isdigit (**type))
+    return 0;
+  *count = **type - '0';
+  *type += 1;
+  /* see flush_repeats in cplus-method.c */
+  if (isdigit (**type))
+    {
+      const char *p = *type;
+      int n = *count;
+      do 
+       {
+         n *= 10;
+         n += *p - '0';
+         p += 1;
+       } 
+      while (isdigit (*p));
+      if (*p == '_')
+       {
+         *type = p + 1;
+         *count = n;
+       }
+    }
+  return 1;
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (type, result)
+     const char **type;
+     string *result;
+{
+  int n;
+  int done;
+  int non_empty = 0;
+  int success;
+  string decl;
+  const char *remembered_type;
+
+  string_init (&decl);
+  string_init (result);
+
+  done = 0;
+  success = 1;
+  while (success && !done)
+    {
+      int member;
+      switch (**type)
+       {
+       case 'P':
+         *type += 1;
+         string_prepend (&decl, "*");
+         break;
+
+       case 'R':
+         *type += 1;
+         string_prepend (&decl, "&");
+         break;
+
+       case 'T':
+         *type += 1;
+         if (!get_count (type, &n) || n >= ntypes)
+           success = 0;
+         else
+           {
+             remembered_type = typevec[n];
+             type = &remembered_type;
+           }
+         break;
+
+       case 'F':
+         *type += 1;
+         if (!string_empty (&decl) && decl.b[0] == '*')
+           {
+             string_prepend (&decl, "(");
+             string_append (&decl, ")");
+           }
+         if (!do_args (type, &decl) || **type != '_')
+           success = 0;
+         else
+           *type += 1;
+         break;
+
+       case 'M':
+       case 'O':
+         {
+           int constp = 0;
+           int volatilep = 0;
+
+           member = **type == 'M';
+           *type += 1;
+           if (!isdigit (**type))
+             {
+               success = 0;
+               break;
+             }
+           n = 0;
+           do
+             {
+               n *= 10;
+               n += **type - '0';
+               *type += 1;
+             } 
+           while (isdigit (**type));
+           if (strlen (*type) < n)
+             {
+               success = 0;
+               break;
+             }
+           string_append (&decl, ")");
+           string_prepend (&decl, "::");
+           string_prependn (&decl, *type, n);
+           string_prepend (&decl, "(");
+           *type += n;
+           if (member)
+             {
+               if (**type == 'C')
+                 {
+                   *type += 1;
+                   constp = 1;
+                 }
+               if (**type == 'V')
+                 {
+                   *type += 1;
+                   volatilep = 1;
+                 }
+               if (*(*type)++ != 'F')
+                 {
+                   success = 0;
+                   break;
+                 }
+             }
+           if ((member && !do_args (type, &decl)) || **type != '_')
+             {
+               success = 0;
+               break;
+             }
+           *type += 1;
+           if (constp)
+             {
+               if (non_empty)
+                 string_append (&decl, " ");
+               else
+                 non_empty = 1;
+               string_append (&decl, "const");
+             }
+           if (volatilep)
+             {
+               if (non_empty)
+                 string_append (&decl, " ");
+               else
+                 non_empty = 1;
+               string_append (&decl, "volatilep");
+             }
+           break;
+         }
+
+       case 'C':
+         if ((*type)[1] == 'P')
+           {
+             *type += 1;
+             if (!string_empty (&decl))
+               string_prepend (&decl, " ");
+             string_prepend (&decl, "const");
+             break;
+           }
+
+         /* fall through */
+       default:
+         done = 1;
+         break;
+       }
+    }
+
+  done = 0;
+  non_empty = 0;
+  while (success && !done)
+    {
+      switch (**type)
+       {
+       case 'C':
+         *type += 1;
+         if (non_empty)
+           string_append (result, " ");
+         else
+           non_empty = 1;
+         string_append (result, "const");
+         break;
+       case 'U':
+         *type += 1;
+         if (non_empty)
+           string_append (result, " ");
+         else
+           non_empty = 1;
+         string_append (result, "unsigned");
+         break;
+       case 'V':
+         *type += 1;
+         if (non_empty)
+           string_append (result, " ");
+         else
+           non_empty = 1;
+         string_append (result, "volatile");
+         break;
+       default:
+         done = 1;
+         break;
+       }
+    }
+
+  if (success)
+    switch (**type)
+      {
+      case '\0':
+      case '_':
+       break;
+      case 'v':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "void");
+       break;
+      case 'l':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "long");
+       break;
+      case 'i':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "int");
+       break;
+      case 's':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "short");
+       break;
+      case 'c':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "char");
+       break;
+      case 'r':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "long double");
+       break;
+      case 'd':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "double");
+       break;
+      case 'f':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "float");
+       break;
+      case 'G':
+       *type += 1;
+       if (!isdigit (**type))
+         {
+           success = 0;
+           break;
+         }
+       /* fall through */
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+       n = 0;
+       do
+         {
+           n *= 10;
+           n += **type - '0';
+           *type += 1;
+         }
+       while (isdigit (**type));
+       if (strlen (*type) < n)
+         {
+           success = 0;
+           break;
+         }
+       if (non_empty)
+         string_append (result, " ");
+       string_appendn (result, *type, n);
+       *type += n;
+       break;
+      default:
+       success = 0;
+       break;
+      }
+
+  if (success)
+    {
+      if (!string_empty (&decl))
+       {
+         string_append (result, " ");
+         string_appends (result, &decl);
+       }
+      string_delete (&decl);
+      return 1;
+    }
+  else
+    {
+      string_delete (&decl);
+      string_delete (result);
+      return 0;
+    }
+}
+
+/* `result' will be initialised in do_type; it will be freed on failure */
+
+static int
+do_arg (type, result)
+     const char **type;
+     string *result;
+{
+  char *tem;
+  int len;
+  const char *start;
+  const char *end;
+
+  start = *type;
+  if (!do_type (type, result))
+    return 0;
+  end = *type;
+  if (ntypes >= typevec_size)
+    {
+      if (typevec_size == 0)
+       {
+         typevec_size = 3;
+         typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
+       }
+      else
+       {
+         typevec_size *= 2;
+         typevec = (char **) realloc ((char *)typevec, sizeof (char*)*typevec_size);
+       }
+    }
+  len = end - start;
+  tem = (char *) xmalloc (len + 1);
+  memcpy (tem, start, len);
+  tem[len] = '\0';
+  typevec[ntypes++] = tem;
+  return 1;
+}
+
+/* `decl' must be already initialised, usually non-empty;
+   it won't be freed on failure */
+
+static int
+do_args (type, decl)
+     const char **type;
+     string *decl;
+{
+  string arg;
+  int need_comma = 0;
+  int dont_want_first;
+
+#ifndef LONGERNAMES
+  dont_want_first = 1;
+#else
+  dont_want_first = 0;
+#endif
+
+  string_append (decl, "(");
+
+  while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
+    {
+      if (**type == 'N')
+       {
+         int r;
+         int t;
+         *type += 1;
+         if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
+           return 0;
+         while (--r >= 0)
+           {
+             const char *tem = typevec[t];
+             if (need_comma)
+               string_append (decl, ", ");
+             if (!do_arg (&tem, &arg))
+               return 0;
+             string_appends (decl, &arg);
+             string_delete (&arg);
+             need_comma = 1;
+           }
+       }
+      else
+       {
+         if (need_comma)
+           string_append (decl, ", ");
+         if (!do_arg (type, &arg))
+           return 0;
+         if (dont_want_first)
+           dont_want_first = 0;
+         else
+           {
+             string_appends (decl, &arg);
+             need_comma = 1;
+           }
+         string_delete (&arg);
+       }
+    }
+
+  if (**type == 'v')
+    *type += 1;
+  else if (**type == 'e')
+    {
+      *type += 1;
+      if (need_comma)
+       string_append (decl, ",");
+      string_append (decl, "...");
+    }
+
+  string_append (decl, ")");
+  return 1;
+}
+
+static void
+munge_function_name (name)
+     string *name;
+{
+  if (!string_empty (name) && name->p - name->b >= 3 
+      && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
+    {
+      int i;
+      /* see if it's an assignment expression */
+      if (name->p - name->b >= 10 /* op$assign_ */
+         && memcmp (name->b + 3, "assign_", 7) == 0)
+       {
+         for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+           {
+             int len = name->p - name->b - 10;
+             if (strlen (optable[i].in) == len
+                 && memcmp (optable[i].in, name->b + 10, len) == 0)
+               {
+                 string_clear (name);
+                 string_append (name, "operator");
+                 string_append (name, optable[i].out);
+                 string_append (name, "=");
+                 return;
+               }
+           }
+       }
+      else
+       {
+         for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+           {
+             int len = name->p - name->b - 3;
+             if (strlen (optable[i].in) == len 
+                 && memcmp (optable[i].in, name->b + 3, len) == 0)
+               {
+                 string_clear (name);
+                 string_append (name, "operator");
+                 string_append (name, optable[i].out);
+                 return;
+               }
+           }
+       }
+      return;
+    }
+  else if (!string_empty (name) && name->p - name->b >= 5
+          && memcmp (name->b, "type$", 5) == 0)
+    {
+      /* type conversion operator */
+      string type;
+      const char *tem = name->b + 5;
+      if (do_type (&tem, &type))
+       {
+         string_clear (name);
+         string_append (name, "operator ");
+         string_appends (name, &type);
+         string_delete (&type);
+         return;
+       }
+    }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+     string *s;
+     int n;
+{
+  if (s->b == NULL)
+    {
+      if (n < 32)
+       n = 32;
+      s->p = s->b = (char *) xmalloc (n);
+      s->e = s->b + n;
+    }
+  else if (s->e - s->p < n)
+    {
+      int tem = s->p - s->b;
+      n += tem;
+      n *= 2;
+      s->b = (char *) realloc (s->b, n);
+      s->p = s->b + tem;
+      s->e = s->b + n;
+    }
+}
+
+static void
+string_delete (s)
+     string *s;
+{
+  if (s->b != NULL)
+    {
+      free (s->b);
+      s->b = s->e = s->p = NULL;
+    }
+}
+
+static void
+string_init (s)
+     string *s;
+{
+  s->b = s->p = s->e = NULL;
+}
+
+static void 
+string_clear (s)
+     string *s;
+{
+  s->p = s->b;
+}
+
+static int
+string_empty (s)
+     string *s;
+{
+  return s->b == s->p;
+}
+
+static void
+string_append (p, s)
+     string *p;
+     const char *s;
+{
+  int n;
+  if (s == NULL || *s == '\0')
+    return;
+  n = strlen (s);
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_appends (p, s)
+     string *p, *s;
+{
+  int n;
+  if (s->b == s->p)
+    return;
+  n = s->p - s->b;
+  string_need (p, n);
+  memcpy (p->p, s->b, n);
+  p->p += n;
+}
+
+static void
+string_appendn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  if (n == 0)
+    return;
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_prepend (p, s)
+     string *p;
+     const char *s;
+{
+  if (s == NULL || *s == '\0')
+    return;
+  string_prependn (p, s, strlen (s));
+}
+
+static void
+string_prependn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  char *q;
+
+  if (n == 0)
+    return;
+  string_need (p, n);
+  for (q = p->p - 1; q >= p->b; q--)
+    q[n] = q[0];
+  memcpy (p->b, s, n);
+  p->p += n;
+}
diff --git a/bfd/filemode.c b/bfd/filemode.c
new file mode 100644 (file)
index 0000000..1bb5e64
--- /dev/null
@@ -0,0 +1,193 @@
+/* filemode.c -- make a string describing file modes
+   Copyright (C) 1985, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+#include <sys/types.h>
+#include <sys/stat.h>
+
+void mode_string ();
+static char ftypelet ();
+static void rwx ();
+static void setst ();
+
+/* 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. */
+
+void
+filemodestring (statp, str)
+     struct stat *statp;
+     char *str;
+{
+  mode_string (statp->st_mode, str);
+}
+
+/* Like filemodestring, but only the relevant part of the `struct stat'
+   is given as an argument. */
+
+void
+mode_string (mode, str)
+     unsigned short mode;
+     char *str;
+{
+  str[0] = ftypelet (mode);
+  rwx ((mode & 0700) << 0, &str[1]);
+  rwx ((mode & 0070) << 3, &str[4]);
+  rwx ((mode & 0007) << 6, &str[7]);
+  setst (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. */
+
+static char
+ftypelet (bits)
+     unsigned short bits;
+{
+  switch (bits & S_IFMT)
+    {
+    default:
+      return '-';
+    case S_IFDIR:
+      return 'd';
+#ifdef S_IFLNK
+    case S_IFLNK:
+      return 'l';
+#endif
+#ifdef S_IFCHR
+    case S_IFCHR:
+      return 'c';
+#endif
+#ifdef S_IFBLK
+    case S_IFBLK:
+      return 'b';
+#endif
+#ifdef S_IFMPC
+    case S_IFMPC:
+    case S_IFMPB:
+      return 'm';
+#endif
+#ifdef S_IFSOCK
+    case S_IFSOCK:
+      return 's';
+#endif
+#ifdef S_IFIFO
+#if S_IFIFO != S_IFSOCK
+    case S_IFIFO:
+      return 'p';
+#endif
+#endif
+#ifdef S_IFNWK                 /* HP-UX */
+    case S_IFNWK:
+      return 'n';
+#endif
+    }
+}
+
+/* Look at read, write, and execute bits in BITS and set
+   flags in CHARS accordingly. */
+
+static void
+rwx (bits, chars)
+     unsigned short bits;
+     char *chars;
+{
+  chars[0] = (bits & S_IREAD) ? 'r' : '-';
+  chars[1] = (bits & S_IWRITE) ? 'w' : '-';
+  chars[2] = (bits & S_IEXEC) ? 'x' : '-';
+}
+
+/* Set the 's' and 't' flags in file attributes string CHARS,
+   according to the file mode BITS. */
+
+static void
+setst (bits, chars)
+     unsigned short bits;
+     char *chars;
+{
+#ifdef S_ISUID
+  if (bits & S_ISUID)
+    {
+      if (chars[3] != 'x')
+       /* Set-uid, but not executable by owner. */
+       chars[3] = 'S';
+      else
+       chars[3] = 's';
+    }
+#endif
+#ifdef S_ISGID
+  if (bits & S_ISGID)
+    {
+      if (chars[6] != 'x')
+       /* Set-gid, but not executable by group. */
+       chars[6] = 'S';
+      else
+       chars[6] = 's';
+    }
+#endif
+#ifdef S_ISVTX
+  if (bits & S_ISVTX)
+    {
+      if (chars[9] != 'x')
+       /* Sticky, but not executable by others. */
+       chars[9] = 'T';
+      else
+       chars[9] = 't';
+    }
+#endif
+}
+
+
diff --git a/bfd/hosts/dgux.h b/bfd/hosts/dgux.h
new file mode 100644 (file)
index 0000000..b4b102d
--- /dev/null
@@ -0,0 +1,15 @@
+#include <sys/dg_c_generics.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <stdio.h>
+
+#define NO_STDARG 1
+
+
+
diff --git a/bfd/hosts/sparc.h b/bfd/hosts/sparc.h
new file mode 100644 (file)
index 0000000..6f03142
--- /dev/null
@@ -0,0 +1,73 @@
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/file.h>
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+#define SEEK_SET 0
+#define SEEK_CUR 1
+
+extern PROTO(int, abort,(void));
+extern PROTO(int, close,(int));
+extern PROTO(int, fcntl,(int des, int cmd));
+extern PROTO(int, fprintf,(FILE *,char *,...));
+extern PROTO(int, printf,(char *,...));
+extern PROTO(int, oqsort,(void *data,int els, int siz, int func()));
+extern PROTO(int, exit,(int));
+extern PROTO(int, fseek,(FILE*, int, int));
+extern PROTO(int, fclose,(FILE*));
+extern PROTO(void, bcopy,(char*,char*,int));
+extern PROTO(int, bcmp,(char *, char *, int));
+extern PROTO(void, bzero,(char *, int));
+extern PROTO(char *,memset,(char*, int, int));
+PROTO(PTR, memcpy,(PTR,CONST PTR,unsigned int));
+extern char * strchr();
+extern PROTO(void, perror,(char *));
+extern char *getenv();
+extern char *memchr();
+extern char *strrchr();
+extern int chmod();
+extern int fread();
+extern int fstat();
+extern int fwrite();
+extern int sscanf();
+extern int stat();
+extern int strtol();
+void free();
+char *malloc();
+char *realloc();
+PROTO (void, perror, (char *s));
+extern char *strrchr();
+extern char *ctime();
+extern int _flsbuf();
+extern int fclose();
+extern int time();
+extern int utimes();
+extern int vfprintf();
+extern long atol();
+extern char *getenv();
+extern int fputc();
+extern int unlink();
+
+
+/* EXACT TYPES */
+typedef char int8e_type;
+typedef unsigned char uint8e_type;
+typedef short int16e_type;
+typedef unsigned short uint16e_type;
+typedef int int32e_type;
+typedef unsigned int uint32e_type;
+
+/* CORRECT SIZE OR GREATER */
+typedef char int8_type;
+typedef unsigned char uint8_type;
+typedef short int16_type;
+typedef unsigned short uint16_type;
+typedef int int32_type;
+typedef unsigned int uint32_type;
+
diff --git a/bfd/hosts/sun3.h b/bfd/hosts/sun3.h
new file mode 100644 (file)
index 0000000..2d38220
--- /dev/null
@@ -0,0 +1,71 @@
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/file.h>
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+#define SEEK_SET 0
+#define SEEK_CUR 1
+
+extern PROTO(int, abort,(void));
+extern PROTO(int, close,(int));
+extern PROTO(int, fcntl,(int des, int cmd));
+extern PROTO(int, fprintf,(FILE *,char *,...));
+extern PROTO(int, printf,(char *,...));
+extern PROTO(int, qsort,(void *data,int els, int siz, int func()));
+extern PROTO(int, exit,(int));
+extern PROTO(int, fseek,(FILE*, int, int));
+extern PROTO(int, fclose,(FILE*));
+extern PROTO(void, bcopy,(char*,char*,int));
+extern PROTO(int, bcmp,(char *, char *, int));
+extern PROTO(void, bzero,(char *, int));
+extern char * strchr();
+extern PROTO(void, perror,(char *));
+extern char *getenv();
+extern char *memchr();
+extern char *strrchr();
+extern int chmod();
+extern int fread();
+extern int fstat();
+extern int fwrite();
+extern int sscanf();
+extern int stat();
+extern int strtol();
+void free();
+char *malloc();
+char *realloc();
+PROTO (void, perror, (char *s));
+extern char *strrchr();
+extern char *ctime();
+extern int _flsbuf();
+extern int fclose();
+extern int time();
+extern int utimes();
+extern int vfprintf();
+extern long atol();
+extern char *getenv();
+extern int fputc();
+extern int unlink();
+
+
+/* EXACT TYPES */
+typedef char int8e_type;
+typedef unsigned char uint8e_type;
+typedef short int16e_type;
+typedef unsigned short uint16e_type;
+typedef int int32e_type;
+typedef unsigned int uint32e_type;
+
+/* CORRECT SIZE OR GREATER */
+typedef char int8_type;
+typedef unsigned char uint8_type;
+typedef short int16_type;
+typedef unsigned short uint16_type;
+typedef int int32_type;
+typedef unsigned int uint32_type;
+
diff --git a/bfd/ieee.c b/bfd/ieee.c
new file mode 100644 (file)
index 0000000..8a2f86d
--- /dev/null
@@ -0,0 +1,1919 @@
+/*
+   
+ bfd backend for ieee objects.
+
+ IEEE format is a stream of records, which we parse using a simple one
+ token (which is one byte in this lexicon) lookahead recursive decent
+ parser.
+
+ On output, this module creates files with the parts in this order:
+   header
+   external_part,
+   data_part,
+   section_part,
+
+
+
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "ieee.h"
+#include "libieee.h"
+
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free  free
+
+typedef void generic_symbol_type;
+static bfd_byte current_c;
+
+/***************************************************************************
+   Functions for writing to ieee files in the strange way that the
+   standard requires:
+*/
+
+
+static void
+ieee_write_byte(abfd, byte)
+bfd *abfd;
+bfd_byte byte;
+{
+  bfd_write(&byte, 1, 1, abfd);
+}
+
+
+static void
+ieee_write_2bytes(abfd, bytes)
+bfd *abfd;
+int bytes;
+{
+  bfd_byte buffer[2];
+  buffer[0] = bytes >> 8;
+  buffer[1] = bytes & 0xff;
+
+  bfd_write(buffer, 1, 2, abfd);
+}
+
+static void
+ieee_write_int(abfd, value)
+bfd *abfd;
+bfd_vma value;
+{
+  if (value >= 0 && value <= 127) {
+    ieee_write_byte(abfd, value);
+  }
+  else {
+    unsigned int length;
+    /* How many significant bytes ? */
+    /* FIXME FOR LONGER INTS */
+    if (value & 0xff000000) {
+      length = 4;
+    }
+    else if (value & 0x00ff0000) {
+      length  = 3;
+    }
+    else if (value & 0x0000ff00) {
+      length = 2;
+    }
+    else length = 1;
+
+    ieee_write_byte(abfd, ieee_number_repeat_start_enum + length);
+    switch (length) {
+    case 4:
+      ieee_write_byte(abfd, value >> 24);
+    case 3:
+      ieee_write_byte(abfd, value >> 16);
+    case 2:
+      ieee_write_byte(abfd, value >> 8);
+    case 1:
+      ieee_write_byte(abfd, value);
+    }
+  }
+}
+
+static void
+ieee_write_id(abfd, id)
+bfd *abfd;
+char *id;
+{
+  size_t length = strlen(id);
+  if (length >= 0 && length <= 127) {
+    ieee_write_byte(abfd, length);
+  }
+  else if (length < 255) {
+    ieee_write_byte(abfd, ieee_extension_length_1_enum);
+    ieee_write_byte(abfd, length);
+  }
+  else if (length < 65535) {
+    ieee_write_byte(abfd, ieee_extension_length_2_enum);
+    ieee_write_byte(abfd, length >> 8);
+    ieee_write_byte(abfd, length & 0xff);  
+  }
+  else {
+    BFD_FAIL();
+  }
+  bfd_write((bfd_byte *)id, 1, length, abfd);
+}
+/***************************************************************************
+Functions for reading from ieee files in the strange way that the
+standard requires:
+*/
+static bfd_byte 
+this_byte(abfd)
+bfd *abfd;
+{
+  return current_c;
+}
+
+static void
+next_byte(abfd)
+bfd *abfd;
+{
+  if (  bfd_read(&current_c, 1, 1, abfd) != 1) {
+    BFD_FAIL();
+  }
+
+}
+
+
+static bfd_byte this_byte_and_next(abfd)
+bfd *abfd;
+{
+  bfd_byte r = this_byte(abfd);
+  next_byte(abfd);
+  return r;
+}
+
+
+
+static unsigned short read_2bytes(abfd)
+bfd *abfd;
+{
+  unsigned  char c1 = this_byte_and_next(abfd);
+  unsigned  char c2 = this_byte_and_next(abfd);
+  return (c1<<8 ) | c2;
+
+}
+
+static void
+bfd_get_string(abfd, string, length)
+bfd *abfd;
+char *string;
+size_t length;
+{
+  size_t i;
+  for (i= 0; i < length; i++) {
+    string[i] = this_byte_and_next(abfd);
+  }
+}
+
+static char *read_id(abfd)
+bfd *abfd;
+{
+  size_t length;
+  char *string;
+  length = this_byte_and_next(abfd);
+  if (length >= 0x00 && length <= 0x7f) {
+    /* Simple string of length 0 to 127 */
+  }
+  else if (length == 0xde) {
+    /* Length is next byte, allowing 0..255 */
+    length = this_byte_and_next(abfd);
+  }
+  else if (length == 0xdf) {
+    /* Length is next two bytes, allowing 0..65535 */
+    length = this_byte_and_next(abfd) ;
+    length = (length * 256) + this_byte_and_next(abfd);
+  }
+  /* Buy memory and read string */
+  string = malloc(length+1);
+  bfd_get_string(abfd, string, length);
+  string[length] = 0;
+  return string;
+}
+
+static void
+ieee_write_expression(abfd, value, section, symbol)
+bfd*abfd;
+bfd_vma value;
+asection *section;
+asymbol *symbol;
+{
+  unsigned int plus_count = 0;
+  ieee_write_int(abfd, value);
+  if (section != (asection *)NULL) {
+    plus_count++;
+    ieee_write_byte(abfd, ieee_variable_L_enum);
+    ieee_write_byte(abfd, section->index  +IEEE_SECTION_NUMBER_BASE);
+  }
+
+  if (symbol != (asymbol *)NULL) {
+    plus_count++;
+    if ((symbol->flags & BSF_UNDEFINED ) ||
+       (symbol->flags & BSF_FORT_COMM)) {
+      ieee_write_byte(abfd, ieee_variable_X_enum);
+      ieee_write_int(abfd, symbol->value);
+    }
+    else if (symbol->flags & BSF_GLOBAL) {
+      ieee_write_byte(abfd, ieee_variable_I_enum);
+      ieee_write_int(abfd, symbol->value);
+    }
+    else {
+      BFD_FAIL();
+    }
+  }
+
+  while (plus_count != 0) {
+    ieee_write_byte(abfd, ieee_function_plus_enum);
+    plus_count--;
+  }
+
+}
+
+
+
+
+
+
+
+
+
+/*****************************************************************************/
+
+/*
+writes any integer into the buffer supplied and always takes 5 bytes
+*/
+static void
+ieee_write_int5(buffer, value)
+bfd_byte*buffer;
+bfd_vma value;
+{
+  buffer[0] = ieee_number_repeat_4_enum;
+  buffer[1] = (value >> 24 ) & 0xff;
+  buffer[2] = (value >> 16 ) & 0xff;
+  buffer[3] = (value >> 8 ) & 0xff;
+  buffer[4] = (value >> 4 ) & 0xff;
+}
+
+
+
+static boolean 
+parse_int(abfd, value_ptr)
+bfd *abfd;
+bfd_vma *value_ptr;
+{
+  int value = this_byte(abfd);
+  int result;
+  if (value >= 0 && value <= 127) {
+    *value_ptr = value;
+    next_byte(abfd);
+    return true;
+  } 
+  else if (value >= 0x80 && value <= 0x88) {
+    unsigned int count = value & 0xf;
+    result = 0;
+    next_byte(abfd);
+    while (count) {
+      result =(result << 8) | this_byte_and_next(abfd);
+      count--;
+    }
+    *value_ptr = result;
+    return true;
+  } 
+  return false;
+}
+static int parse_i(abfd, ok)
+bfd *abfd;
+boolean *ok;
+{
+  bfd_vma x;
+  *ok = parse_int(abfd, &x);
+  return x;
+}
+
+static bfd_vma must_parse_int(abfd)
+bfd *abfd;
+{
+  bfd_vma result;
+  BFD_ASSERT(parse_int(abfd, &result) == true);
+  return result;
+}
+
+typedef struct 
+{
+  bfd_vma value;
+  asection *section;
+  ieee_symbol_index_type symbol;
+} ieee_value_type;
+
+
+static 
+reloc_howto_type abs32_howto 
+ = {1,0,2,32,0,0,0,true,0,"abs32",false,0xffffffff};
+static
+reloc_howto_type abs16_howto 
+ = {1,0,1,16,0,0,0,true,0,"abs16",false,0x0000ffff};
+
+static ieee_symbol_index_type NOSYMBOL = {  0, 0};
+
+
+void
+frob(abfd, value, section, symbol, pcrel, extra)
+bfd *abfd;
+bfd_vma *value;
+asection **section;
+ieee_symbol_index_type *symbol;
+boolean *pcrel;
+unsigned int *extra;
+{
+#define POS sp[1]
+#define TOS sp[0]
+#define NOS sp[-1]
+#define INC sp++;
+#define DEC sp--;
+
+  boolean loop = true;
+  ieee_value_type stack[10];
+
+  /* The stack pointer always points to the next unused location */
+#define PUSH(x,y,z) TOS.symbol=x;TOS.section=y;TOS.value=z;INC;
+#define POP(x,y,z) DEC;x=TOS.symbol;y=TOS.section;z=TOS.value;
+  ieee_value_type *sp = stack;
+
+  while (loop) {
+    switch (this_byte(abfd)) 
+      {
+      case ieee_variable_P_enum:
+       /* P variable, current program counter for section n */
+       {
+         int section_n ;
+         next_byte(abfd);
+         section_n  = must_parse_int(abfd);
+         PUSH(NOSYMBOL, 0,
+              TOS.value = ieee_data(abfd)->section_table[section_n]->vma +
+              ieee_per_section(ieee_data(abfd)->section_table[section_n])->pc);
+         break;
+       }
+      case ieee_variable_L_enum:
+       /* L variable  address of section N */
+       next_byte(abfd);
+       PUSH(NOSYMBOL,ieee_data(abfd)->section_table[must_parse_int(abfd)],0);
+       break;
+      case ieee_variable_R_enum:
+       /* R variable, logical address of section module */
+       /* FIXME, this should be different to L */
+       next_byte(abfd);
+       PUSH(NOSYMBOL,ieee_data(abfd)->section_table[must_parse_int(abfd)],0);
+       break;
+      case ieee_variable_S_enum:
+       /* S variable, size in MAUS of section module */
+       next_byte(abfd);
+       PUSH(NOSYMBOL,
+            0,
+            ieee_data(abfd)->section_table[must_parse_int(abfd)]->size);
+       break;
+
+      case ieee_variable_X_enum:
+       /* Push the address of external variable n */
+       {
+         ieee_symbol_index_type sy;
+         next_byte(abfd);
+         sy.index  = (int)(must_parse_int(abfd)) ;
+         sy.letter = 'X';
+
+         PUSH(sy, 0, 0);
+       }       
+       break;
+      case ieee_function_minus_enum:
+       {
+         bfd_vma value1, value2;
+         asection *section;
+         ieee_symbol_index_type sy;
+         next_byte(abfd);
+
+         POP(sy, section, value1);
+         POP(sy, section, value2);
+         PUSH(NOSYMBOL, 0, value1-value2);
+       }
+       break;
+      case ieee_function_plus_enum:
+       {
+         bfd_vma value1, value2;
+         asection *section1;
+         asection *section2;
+         ieee_symbol_index_type sy;
+         next_byte(abfd);
+
+         POP(sy, section1, value1);
+         POP(sy, section2, value2);
+         PUSH(NOSYMBOL, section1 ? section1: section2, value1+value2);
+       }
+       break;
+      default: 
+       {
+         bfd_vma va;
+         BFD_ASSERT(this_byte(abfd) < ieee_variable_A_enum 
+                    || this_byte(abfd) > ieee_variable_Z_enum);
+         if (parse_int(abfd, &va)) 
+           {
+             PUSH(NOSYMBOL,0, va);
+           }
+         else {
+           /* 
+              Thats all that we can understand. As far as I can see
+              there is a bug in the Microtec IEEE output which I'm
+              using to scan, whereby the comma operator is ommited
+              sometimes in an expression, giving expressions with too
+              many terms. We can tell if that's the case by ensuring
+              that sp == stack here. If not, then we've pushed
+              something too far. - 
+              */
+
+           POP(*symbol, *section, *value);
+           if (sp != stack) {
+             BFD_ASSERT(*section == 0);
+             *extra = *value;
+             /* Get what should be returned */
+             POP(*symbol, *section, *value);
+           }
+           else {
+             *extra = 0;
+           }
+           loop = false;
+         }
+       }
+
+      }
+  }
+}
+
+static void
+ieee_seek(abfd, offset, rel)
+bfd *abfd;
+file_ptr offset;
+boolean rel;
+{
+  (void) bfd_seek(abfd, offset, rel);
+  /* Prime look ahead token */
+  next_byte(abfd);
+}
+
+static void
+ieee_slurp_external_symbols(abfd)
+bfd *abfd;
+{
+  ieee_data_type *ieee = ieee_data(abfd);
+  file_ptr offset = ieee->w.r.external_part;
+
+  ieee_symbol_type **prev_symbols_ptr = &ieee->external_symbols;
+  ieee_symbol_type **prev_reference_ptr = &ieee->external_reference;
+  ieee_symbol_type  *symbol;
+  unsigned int symbol_count = 0;
+  boolean loop = true;
+
+  ieee->symbol_table_full = true;
+
+  ieee_seek(abfd, offset ,false);
+
+  while (loop) {
+    switch (this_byte(abfd)) {
+    case ieee_external_symbol_enum:
+      next_byte(abfd);
+      symbol =  (ieee_symbol_type *)malloc(sizeof(ieee_symbol_type));
+
+      *prev_symbols_ptr = symbol;
+      prev_symbols_ptr= &symbol->next;
+      symbol->index = must_parse_int(abfd);
+      if (symbol->index > ieee->external_symbol_max_index) {
+       ieee->external_symbol_max_index = symbol->index;
+      }
+      BFD_ASSERT (symbol->index >= ieee->external_symbol_min_index);
+      symbol_count++;
+      symbol->symbol.the_bfd = abfd;
+      symbol->symbol.name = read_id(abfd);
+      symbol->symbol.udata = (void *)NULL;
+      symbol->symbol.flags = BSF_NO_FLAGS;
+      break;
+    case ieee_attribute_record_enum >> 8:
+      {
+       unsigned int symbol_name_index;
+       unsigned int symbol_type_index;
+       unsigned int symbol_attribute_def;
+       bfd_vma value;
+       next_byte(abfd);        /* Skip prefix */
+       next_byte(abfd);
+       symbol_name_index = must_parse_int(abfd);
+       symbol_type_index = must_parse_int(abfd);
+       symbol_attribute_def = must_parse_int(abfd);
+
+       parse_int(abfd,&value);
+
+      }
+      break;
+    case ieee_value_record_enum >> 8:
+      {
+       unsigned int symbol_name_index;
+       ieee_symbol_index_type symbol_ignore;
+       boolean *pcrel_ignore;
+       unsigned int extra_ignore;
+       next_byte(abfd);
+       next_byte(abfd);
+
+       symbol_name_index = must_parse_int(abfd);
+       frob(abfd,
+            &symbol->symbol.value,
+            &symbol->symbol.section,
+            &symbol_ignore, 
+            &pcrel_ignore,
+            &extra_ignore);
+       if (symbol->symbol.section != (asection *)NULL) {
+         symbol->symbol.flags  = BSF_GLOBAL | BSF_EXPORT;
+       }
+       else {
+         symbol->symbol.flags  = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
+       }
+      }
+      break;
+    case ieee_weak_external_reference_enum:
+      { bfd_vma size;
+       bfd_vma value ;
+       next_byte(abfd);
+       /* Throw away the external reference index */
+       (void)must_parse_int(abfd);
+       /* Fetch the default size if not resolved */
+       size = must_parse_int(abfd);
+       /* Fetch the defautlt value if available */
+       if (  parse_int(abfd, &value) == false) {
+         value = 0;
+       }
+       /* This turns into a common */
+       symbol->symbol.flags = BSF_FORT_COMM;
+       symbol->symbol.value = size;
+      }
+      break;
+
+    case ieee_external_reference_enum: 
+      next_byte(abfd);
+      symbol = (ieee_symbol_type *)malloc(sizeof(ieee_symbol_type));
+      symbol_count++;
+      *prev_reference_ptr = symbol;
+      prev_reference_ptr = &symbol->next;
+      symbol->index = must_parse_int(abfd);
+      symbol->symbol.the_bfd = abfd;
+      symbol->symbol.name = read_id(abfd);
+      symbol->symbol.udata = (void *)NULL;
+      symbol->symbol.section = (asection *)NULL;
+      symbol->symbol.value = (bfd_vma)0;
+      symbol->symbol.flags = BSF_UNDEFINED;
+      if (symbol->index > ieee->external_reference_max_index) {
+       ieee->external_reference_max_index = symbol->index;
+      }
+      BFD_ASSERT (symbol->index >= ieee->external_reference_min_index);
+      break;
+
+    default:
+      loop = false;
+    }
+  }
+
+  if (ieee->external_symbol_max_index != 0) {
+    ieee->external_symbol_count = 
+      ieee->external_symbol_max_index -
+       ieee->external_symbol_min_index + 1  ;
+  }
+  else  {
+    ieee->external_symbol_count = 0;
+  }
+
+
+  if(ieee->external_reference_max_index != 0) {
+    ieee->external_reference_count = 
+      ieee->external_reference_max_index -
+       ieee->external_reference_min_index + 1;
+  }
+  else {
+    ieee->external_reference_count = 0;
+  }
+
+  abfd->symcount =
+    ieee->external_reference_count +  ieee->external_symbol_count;
+
+  if (symbol_count != abfd->symcount) {
+    /* There are gaps in the table -- */
+    ieee->symbol_table_full = false;
+  }
+  *prev_symbols_ptr = (ieee_symbol_type *)NULL;
+  *prev_reference_ptr = (ieee_symbol_type *)NULL;
+}
+
+static void
+ieee_slurp_symbol_table(abfd)
+bfd *abfd;
+{
+  if (ieee_data(abfd)->read_symbols == false) {
+    ieee_slurp_external_symbols(abfd);
+    ieee_data(abfd)->read_symbols= true;
+  }
+}
+
+size_t
+ieee_get_symtab_upper_bound (abfd)
+bfd *abfd;
+{
+  ieee_slurp_symbol_table (abfd);
+
+  return (abfd->symcount != 0) ? 
+    (abfd->symcount+1) * (sizeof (ieee_symbol_type *)) : 0;
+}
+
+/* 
+Move from our internal lists to the canon table, and insert in
+symbol index order
+*/
+
+extern bfd_target ieee_vec;
+unsigned int
+ieee_get_symtab (abfd, location)
+bfd *abfd;
+asymbol **location;
+{
+  ieee_symbol_type *symp;
+  static bfd dummy_bfd;
+  static asymbol empty_symbol =
+    { &dummy_bfd," ieee empty",(symvalue)0,BSF_DEBUGGING | BSF_FAKE};
+
+  ieee_data_type *ieee = ieee_data(abfd);
+  dummy_bfd.xvec= &ieee_vec;
+  ieee_slurp_symbol_table(abfd);
+
+  if (ieee->symbol_table_full == false) {
+    /* Arrgh - there are gaps in the table, run through and fill them */
+    /* up with pointers to a null place */
+    unsigned int i;
+    for (i= 0; i < abfd->symcount; i++) {
+      location[i] = &empty_symbol;
+    }
+  }
+
+
+  ieee->external_symbol_base_offset= -  ieee->external_symbol_min_index;
+  for (symp = ieee_data(abfd)->external_symbols;
+       symp != (ieee_symbol_type *)NULL;
+       symp = symp->next) {
+    /* Place into table at correct index locations */
+    location[symp->index + ieee->external_symbol_base_offset] = &symp->symbol;
+
+  }
+
+  /* The external refs are indexed in a bit */
+  ieee->external_reference_base_offset   =
+    -  ieee->external_reference_min_index +ieee->external_symbol_count ;
+
+  for (symp = ieee_data(abfd)->external_reference;
+       symp != (ieee_symbol_type *)NULL;
+       symp = symp->next) {
+    location[symp->index + ieee->external_reference_base_offset] =
+      &symp->symbol;
+
+  }
+
+
+
+  location[abfd->symcount] = (asymbol *)NULL;
+
+  return abfd->symcount;
+}
+
+
+static void
+ieee_slurp_sections(abfd)
+bfd *abfd;
+{
+  ieee_data_type *ieee = ieee_data(abfd);
+  file_ptr offset = ieee->w.r.section_part;
+
+  asection *section = (asection *)NULL;
+
+  if (offset != 0) {
+    bfd_byte section_type[3];
+    ieee_seek(abfd, offset, false);
+    while (true) {
+      switch (this_byte(abfd)) {
+      case ieee_section_type_enum:
+       {
+         unsigned int section_index ;
+         next_byte(abfd);
+         section_index = must_parse_int(abfd);
+         /* Fixme to be nice about a silly number of sections */
+         BFD_ASSERT(section_index < NSECTIONS);
+
+         section = bfd_make_section(abfd, " tempname");
+         ieee->section_table[section_index] = section;
+         section->flags = SEC_NO_FLAGS;
+         section->target_index = section_index;
+         section_type[0] =  this_byte_and_next(abfd);
+         switch (section_type[0]) {
+         case 0xC3:
+           section_type[1] = this_byte(abfd);
+           section->flags = SEC_LOAD;
+           switch (section_type[1]) {
+           case 0xD0:
+             /* Normal code */
+             next_byte(abfd);
+             section->flags |= SEC_LOAD | SEC_CODE;
+             break;
+           case 0xC4:
+             next_byte(abfd);
+             section->flags |= SEC_LOAD  | SEC_DATA;
+             /* Normal data */
+             break;
+           case 0xD2:
+             next_byte(abfd);
+             /* Normal rom data */
+             section->flags |= SEC_LOAD | SEC_ROM | SEC_DATA;
+             break;
+           default:
+             break;
+           }
+         }
+         section->name = read_id(abfd);
+         { bfd_vma parent, brother, context;
+           parse_int(abfd, &parent);
+           parse_int(abfd, &brother);
+           parse_int(abfd, &context);
+         }
+
+
+       }
+       break;
+      case ieee_section_alignment_enum:
+       { 
+         unsigned int section_index;
+         bfd_vma value;
+         next_byte(abfd);
+         section_index = must_parse_int(abfd);
+         if (section_index > ieee->section_count) {
+           ieee->section_count = section_index;
+         }
+         ieee->section_table[section_index]->alignment_power =
+           bfd_log2(must_parse_int(abfd));
+         (void)parse_int(abfd, & value);
+       }
+       break;
+      case ieee_e2_first_byte_enum: 
+       {
+         ieee_record_enum_type t = read_2bytes(abfd);
+         switch (t) {
+         case ieee_section_size_enum:
+           section = ieee->section_table[must_parse_int(abfd)];
+           section->size = must_parse_int(abfd);
+           break;
+         case ieee_physical_region_size_enum:
+           section = ieee->section_table[must_parse_int(abfd)];
+           section->size = must_parse_int(abfd);
+           break;
+         case ieee_region_base_address_enum:
+           section = ieee->section_table[must_parse_int(abfd)];
+           section->vma = must_parse_int(abfd);
+           break;
+         case ieee_mau_size_enum:
+           must_parse_int(abfd);
+           must_parse_int(abfd);
+           break;
+         case ieee_m_value_enum:
+           must_parse_int(abfd);
+           must_parse_int(abfd);
+           break;
+         case ieee_section_base_address_enum:
+           section = ieee->section_table[must_parse_int(abfd)];
+           section->vma = must_parse_int(abfd);
+           break;
+         case ieee_section_offset_enum:
+           (void) must_parse_int(abfd);
+           (void) must_parse_int(abfd);
+           break;
+         default:
+           return;
+         }
+       }
+       break;
+      default:
+       return;
+      }
+    }
+  }
+}
+
+/***********************************************************************
+*  archive stuff 
+*/
+bfd_target *
+ieee_archive_p(abfd)
+bfd *abfd;
+{
+  char *library;
+  boolean loop;
+  ieee_ar_data_type *ar;
+  unsigned int i;
+  ieee_seek(abfd, (file_ptr) 0, false);
+  if (this_byte(abfd) != Module_Beginning) return (bfd_target*)NULL;
+  next_byte(abfd);
+  library= read_id(abfd);
+  if (strcmp(library , "LIBRARY") != 0) {
+    free(library);
+    return (bfd_target *)NULL;
+  }
+  /* Throw away the filename */
+  free( read_id(abfd));
+  /* This must be an IEEE archive, so we'll buy some space to do
+     things */
+  ar = (ieee_ar_data_type *) malloc(sizeof(ieee_ar_data_type));
+  ieee_ar_data(abfd) = ar;
+  ar->element_count = 0;
+  ar->element_index = 0;
+  obstack_init(&ar->element_obstack);
+
+  next_byte(abfd);             /* Drop the ad part */
+  must_parse_int(abfd);                /* And the two dummy numbers */
+  must_parse_int(abfd);
+
+  loop = true;
+  /* Read the index of the BB table */
+  while (loop) {
+    ieee_ar_obstack_type t; 
+    int rec =read_2bytes(abfd);
+    if (rec ==ieee_assign_value_to_variable_enum) {
+      int record_number = must_parse_int(abfd);
+      t.file_offset = must_parse_int(abfd);
+      t.abfd = (bfd *)NULL;
+      ar->element_count++;
+      obstack_grow(&ar->element_obstack, &t, sizeof(t));
+    }
+    else loop = false;
+  }
+  ar->elements = (ieee_ar_obstack_type *)obstack_base(&ar->element_obstack);
+
+  /* Now scan the area again, and replace BB offsets with file */
+  /* offsets */
+
+
+  for (i = 2; i < ar->element_count; i++) {
+    ieee_seek(abfd, ar->elements[i].file_offset, false);
+    next_byte(abfd);           /* Drop F8 */
+    next_byte(abfd);           /* Drop 14 */
+    must_parse_int(abfd);      /* Drop size of block */
+    if (must_parse_int(abfd) != 0) {
+      /* This object has been deleted */
+      ar->elements[i].file_offset = 0;
+    }
+    else {
+      ar->elements[i].file_offset = must_parse_int(abfd);
+    }
+  }
+
+  obstack_finish(&ar->element_obstack);
+  return abfd->xvec;
+}
+
+bfd_target *
+ieee_object_p (abfd)
+bfd *abfd;
+{
+  char *processor;
+  unsigned int part;
+  ieee_data_type ieee;
+  ieee_seek(abfd, (file_ptr)0, false);
+
+
+  if (this_byte(abfd) != Module_Beginning) return (bfd_target*)NULL;
+
+  next_byte(abfd);
+
+  ieee.read_symbols= false;
+  ieee.read_data= false;
+  ieee.section_count = 0;
+  ieee.external_symbol_max_index = 0;
+  ieee.external_symbol_min_index = IEEE_PUBLIC_BASE;
+  ieee.external_reference_min_index =IEEE_REFERENCE_BASE;
+  ieee.external_reference_max_index = 0;
+  memset((PTR)ieee.section_table, 0,    sizeof(ieee.section_table));
+
+  processor = ieee.mb.processor = read_id(abfd);
+  if (strcmp(processor,"LIBRARY") == 0) return (bfd_target *)NULL;
+  ieee.mb.module_name = read_id(abfd);
+  if (abfd->filename == (char *)NULL) {
+    abfd->filename =  ieee.mb.module_name;
+  }
+  /* Determine the architecture and machine type of the object file.  */
+  bfd_scan_arch_mach(processor, &abfd->obj_arch, &abfd->obj_machine);
+
+  if (this_byte(abfd) != ieee_address_descriptor_enum) {
+    return (bfd_target *)NULL;
+  }
+  next_byte(abfd);     
+
+  if (parse_int(abfd, &ieee.ad.number_of_bits_mau) == false) {
+    return (bfd_target *)NULL;
+  }
+  if(parse_int(abfd, &ieee.ad.number_of_maus_in_address) == false) {
+    return (bfd_target *)NULL;
+  }
+
+  /* If there is a byte order info, take it */
+  if (this_byte(abfd) == ieee_variable_L_enum ||
+      this_byte(abfd) == ieee_variable_M_enum)
+    next_byte(abfd);
+
+
+  for (part = 0; part < N_W_VARIABLES; part++) {
+    boolean ok;
+    if (read_2bytes(abfd) != ieee_assign_value_to_variable_enum) {
+      return (bfd_target *)NULL;
+    }
+    if (this_byte_and_next(abfd) != part)  {
+      return (bfd_target *)NULL;
+    }
+
+
+    ieee.w.offset[part] = parse_i(abfd, &ok);
+    if (ok==false) {
+      return (bfd_target *)NULL;
+    }
+
+  }
+  abfd->flags = HAS_SYMS;
+
+  /* Read in the section info */
+  ieee_data(abfd) = (ieee_data_type *)(malloc(sizeof(ieee_data_type)));
+  memcpy(ieee_data(abfd), &ieee, sizeof(ieee));
+  ieee_slurp_sections(abfd);
+  return abfd->xvec;
+}
+
+
+void 
+ieee_print_symbol(ignore_abfd, file,  symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+
+  switch (how) {
+  case bfd_print_symbol_name_enum:
+    fprintf(file,"%s", symbol->name);
+    break;
+  case bfd_print_symbol_type_enum:
+#if 0
+    fprintf(file,"%4x %2x",aout_symbol(symbol)->desc & 0xffff,
+           aout_symbol(symbol)->other  & 0xff);
+#endif
+    BFD_FAIL();
+    break;
+  case bfd_print_symbol_all_enum:
+    {
+      char *section_name = symbol->section == (asection *)NULL ?
+       "*abs" : symbol->section->name;
+
+      bfd_print_symbol_vandf((void *)file,symbol);
+
+      fprintf(file," %-5s %04x %02x %s",
+             section_name,
+             (unsigned)              ieee_symbol(symbol)->index,
+             (unsigned)              0, /*
+                                           aout_symbol(symbol)->desc & 0xffff,
+                                           aout_symbol(symbol)->other  & 0xff,*/
+             symbol->name);
+    }
+    break;
+  }
+}
+
+
+
+/* Read in all the section data and relocation stuff too */
+static boolean ieee_slurp_section_data(abfd)
+bfd *abfd;
+{
+  bfd_byte *location_ptr ;
+  ieee_data_type *ieee = ieee_data(abfd);
+  unsigned int section_number ;
+
+  ieee_per_section_type *current_map;
+  asection *s;
+  /* Seek to the start of the data area */
+  if (ieee->read_data== true)  return true;
+  ieee->read_data = true;
+  ieee_seek(abfd, ieee->w.r.data_part, false);
+
+  /* Allocate enough space for all the section contents */
+
+
+  for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
+    ieee_per_section_type *per = s->used_by_bfd;
+    per->data = (bfd_byte *) malloc(s->size);
+    /*SUPPRESS 68*/
+    obstack_init( &per->reloc_obstack);
+    per->reloc_tail_ptr =
+      (ieee_reloc_type **)&(s->relocation);
+  }
+
+
+
+  while (true) {
+    switch (this_byte(abfd)) 
+      {
+       /* IF we see anything strange then quit */
+      default:
+       return true;
+
+      case ieee_set_current_section_enum:
+       next_byte(abfd);
+       section_number = must_parse_int(abfd);
+       s = ieee->section_table[section_number];
+       current_map = s->used_by_bfd;
+       location_ptr = current_map->data - s->vma;
+       /* The document I have says that Microtec's compilers reset */
+       /* this after a sec section, even though the standard says not */
+       /* to. SO .. */
+       current_map->pc =s->vma;
+       break;
+
+      case ieee_load_constant_bytes_enum:
+       {
+         unsigned int number_of_maus;
+         unsigned int i;
+         next_byte(abfd);
+         number_of_maus = must_parse_int(abfd);
+
+         for (i = 0; i < number_of_maus; i++) {
+           location_ptr[current_map->pc++]= this_byte(abfd);
+           next_byte(abfd);
+         }
+       }
+       break;
+
+      case ieee_e2_first_byte_enum:
+       next_byte(abfd);
+       switch (this_byte(abfd))
+         {
+         case ieee_set_current_pc_enum & 0xff:
+           {
+             bfd_vma value;
+             asection *dsection;
+             ieee_symbol_index_type symbol;
+             unsigned int extra;
+             boolean pcrel;
+             next_byte(abfd);
+             must_parse_int(abfd); /* Thow away section #*/
+             frob(abfd, &value, &dsection, &symbol, &pcrel, &extra);
+             current_map->pc = value;
+             BFD_ASSERT((unsigned)(value - s->vma) < s->size);
+           }
+           break;
+
+         case ieee_value_starting_address_enum & 0xff:
+           /* We've got to the end of the data now - */
+           return true;
+           break;
+         default:
+           BFD_FAIL();
+           return true;
+         }
+       break;
+      case ieee_load_with_relocation_enum:
+       {
+         boolean loop = true;
+         next_byte(abfd);
+         while (loop) 
+           {
+             switch (this_byte(abfd)) 
+               {
+               case ieee_variable_R_enum:
+
+               case ieee_function_signed_open_b_enum:
+               case ieee_function_unsigned_open_b_enum:
+               case ieee_function_either_open_b_enum:
+                 {
+                   unsigned int extra;
+                   boolean pcrel;
+
+                   ieee_reloc_type *r =
+                     (ieee_reloc_type *)
+                       obstack_alloc( &current_map->reloc_obstack,
+                                     sizeof(ieee_reloc_type));
+
+                   *(current_map->reloc_tail_ptr) = r;
+                   current_map->reloc_tail_ptr= &r->next;
+                   r->next = (ieee_reloc_type *)NULL;
+                   next_byte(abfd);
+                   frob(abfd,
+                        &r->relent.addend,
+                        &r->relent.section,
+                        &r->symbol,
+                        &pcrel,
+                        &extra);
+                   r->relent.address = current_map->pc;
+                   s->reloc_count++;
+                   switch (this_byte(abfd)) {
+                   case ieee_function_signed_close_b_enum:
+                     next_byte(abfd);
+                     break;
+                   case ieee_function_unsigned_close_b_enum:
+                     next_byte(abfd);
+                     break;
+                   case ieee_function_either_close_b_enum:
+                     next_byte(abfd);
+                     break;
+                   default:
+                     break;
+                   }
+                   /* Build a relocation entry for this type */
+                   if (this_byte(abfd) == ieee_comma) {
+
+                     next_byte(abfd);
+                     /* Fetch number of bytes to pad */
+                     extra = must_parse_int(abfd);
+                     BFD_FAIL();
+                   }
+                   switch (extra) {
+                   case 0:
+                   case 4:
+                     location_ptr[current_map->pc++] = 0;
+                     location_ptr[current_map->pc++] = 0;
+                     location_ptr[current_map->pc++] = 0;
+                     location_ptr[current_map->pc++] = 0;
+                     r->relent.howto = &abs32_howto;
+                     break;
+                   case 2:
+                     location_ptr[current_map->pc++] = 0;
+                     location_ptr[current_map->pc++] = 0;
+                     r->relent.howto = &abs16_howto;
+                     break;
+
+                   default:
+                     BFD_FAIL();
+                     break;
+                   }
+                 }
+                 break;
+               default: 
+                 {
+                   bfd_vma this_size ;
+                   if (parse_int(abfd, &this_size) == true) {
+                     unsigned int i;
+                     for (i = 0; i < this_size; i++) {
+                       location_ptr[current_map->pc ++] = this_byte(abfd);
+                       next_byte(abfd);
+                     }
+                   }
+                   else {
+                     loop = false;
+                   }
+                 }
+               }
+           }
+       }
+      }
+  }
+}
+
+
+
+boolean
+ieee_new_section_hook (abfd, newsect)
+bfd *abfd;
+asection *newsect;
+{
+  newsect->used_by_bfd = (ieee_per_section_type *)
+    malloc(sizeof(ieee_per_section_type));
+  ieee_per_section( newsect)->data = (bfd_byte *)NULL;
+  ieee_per_section(newsect)->section = newsect;
+  return true;
+}
+
+
+unsigned int
+ieee_get_reloc_upper_bound (abfd, asect)
+bfd *abfd;
+sec_ptr asect;
+{
+  ieee_slurp_section_data(abfd);
+  return (asect->reloc_count+1) * sizeof(arelent *);
+}
+
+static boolean
+ieee_get_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+void  *location;
+file_ptr offset;
+unsigned      int count;
+{
+  ieee_per_section_type *p = section->used_by_bfd;
+  ieee_slurp_section_data(abfd);
+  (void)  memcpy(location, p->data + offset, count);
+  return true;
+}
+
+
+unsigned int
+ieee_canonicalize_reloc (abfd, section, relptr, symbols)
+bfd *abfd;
+sec_ptr section;
+arelent **relptr;
+asymbol **symbols;
+{
+  ieee_per_section_type *p = section->used_by_bfd;
+  ieee_reloc_type *src = (ieee_reloc_type *)(section->relocation);
+  ieee_data_type *ieee = ieee_data(abfd);
+
+  while (src != (ieee_reloc_type *)NULL) {
+    /* Work out which symbol to attatch it this reloc to */
+    switch (src->symbol.letter) {
+    case 'X':
+      src->relent.sym_ptr_ptr =
+       symbols + src->symbol.index +  ieee->external_reference_base_offset;
+      break;
+    case 0:
+      src->relent.sym_ptr_ptr = (asymbol **)NULL;
+      break;
+    default:
+
+      BFD_FAIL();
+    }
+    *relptr++ = &src->relent;
+    src = src->next;
+  }
+  *relptr = (arelent *)NULL;
+  return section->reloc_count;
+}
+
+boolean
+ieee_set_arch_mach (abfd, arch, machine)
+bfd *abfd;
+enum bfd_architecture arch;
+unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  return true;
+}
+
+boolean
+ieee_mkobject(abfd)
+bfd *abfd;
+{
+  ieee_data_type *ieee =  (ieee_data_type *) malloc(sizeof(ieee_data_type));
+  ieee_data(abfd) = ieee;
+  if (ieee == (ieee_data_type *)NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  return true;
+}
+
+
+static int comp(ap, bp)
+arelent **ap;
+arelent **bp;
+{
+  arelent *a = *ap;
+  arelent *b = *bp;
+  return a->address - b->address;
+}
+/*
+Write the section headers
+*/
+
+static void
+ieee_write_section_part(abfd)
+bfd *abfd;
+{
+  ieee_data_type *ieee = ieee_data(abfd);
+  asection *s;
+  ieee->w.r.section_part = bfd_tell(abfd);
+  for (s = abfd->sections; s != (asection *)NULL; s=s->next) {
+    ieee_write_byte(abfd, ieee_section_type_enum);
+    ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+
+    switch (s->flags & (SEC_LOAD | SEC_CODE | SEC_DATA | SEC_ROM)) {
+    case  SEC_LOAD | SEC_CODE:
+      /* Normal named section, code */
+      ieee_write_byte(abfd, ieee_variable_C_enum);
+      ieee_write_byte(abfd, ieee_variable_P_enum);
+      break;
+    case  SEC_LOAD | SEC_DATA:
+      /* Normal named section, data */
+      ieee_write_byte(abfd, ieee_variable_C_enum);
+      ieee_write_byte(abfd, ieee_variable_D_enum);
+      break;
+    case  SEC_LOAD | SEC_DATA | SEC_ROM:
+      /* Normal named section, data rom */
+      ieee_write_byte(abfd, ieee_variable_C_enum);
+      ieee_write_byte(abfd, ieee_variable_R_enum);
+      break;
+    default:
+      ieee_write_byte(abfd, ieee_variable_C_enum);
+      break;
+    }
+
+    ieee_write_id(abfd, s->name);
+    ieee_write_int(abfd, 0);   /* Parent */
+    ieee_write_int(abfd, 0);   /* Brother */
+    ieee_write_int(abfd, 0);   /* Context */
+
+    /* Alignment */
+    ieee_write_byte(abfd, ieee_section_alignment_enum);
+    ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+    ieee_write_int(abfd, 1 << s->alignment_power);
+
+    /* Size */
+    ieee_write_2bytes(abfd, ieee_section_size_enum);
+    ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+    ieee_write_int(abfd, s->size);
+
+    /* Vma */
+    ieee_write_2bytes(abfd, ieee_region_base_address_enum);
+    ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+    ieee_write_int(abfd, s->vma);
+
+  }
+}
+
+
+
+/* write the data in an ieee way */
+static void
+ieee_write_data_part(abfd)
+bfd *abfd;
+{
+  asection *s;
+  ieee_data_type *ieee = ieee_data(abfd);
+  ieee->w.r.data_part = bfd_tell(abfd);
+  for (s = abfd->sections; s != (asection *)NULL; s = s->next) 
+    {
+      bfd_byte  header[11];
+      bfd_byte *stream = ieee_per_section(s)->data;
+      arelent **p = s->orelocation;
+      size_t current_byte_index = 0;
+      /* Sort the reloc records so we can insert them in the correct places */
+      if (s->reloc_count != 0) {
+       qsort(s->orelocation,
+             s->reloc_count,
+             sizeof(arelent **),
+             comp);
+      }
+
+
+      /* Output the section preheader */
+      header[0] =ieee_set_current_section_enum;
+      header[1] = s->index + IEEE_SECTION_NUMBER_BASE;
+
+      header[2] = ieee_set_current_pc_enum >> 8;
+      header[3]= ieee_set_current_pc_enum  & 0xff;
+      header[4] = s->index + IEEE_SECTION_NUMBER_BASE;
+      ieee_write_int5(header+5, s->vma );
+      header[10] = ieee_load_with_relocation_enum;
+      bfd_write(header, 1, sizeof(header), abfd);
+
+      /* Output the data stream as the longest sequence of bytes possible, */
+      /* allowing for the a reasonable packet size and relocation stuffs */
+      if (stream == (void *)NULL) {
+       stream = (bfd_byte *)"UNINITIALIZED AREA! ";
+       s->size =  strlen(stream);
+      }
+      while (current_byte_index < s->size) {
+       size_t run;
+       unsigned int MAXRUN = 32;
+       if (p && *p) {
+         run = (*p)->address - current_byte_index;
+       }
+       else {
+         run = MAXRUN;
+       }
+       if (run > s->size - current_byte_index) {
+         run = s->size - current_byte_index;
+       }
+
+       if (run != 0) {
+         /* Output a stream of bytes */
+         bfd_byte header[1] ;
+         header[0]= run;
+         bfd_write(header, 1, sizeof(header), abfd);
+         bfd_write(stream + current_byte_index, 
+                   1,
+                   run,
+                   abfd);
+         current_byte_index += run;
+       }
+       /* Output any relocations here */
+       if (p && (*p) && (*p)->address == current_byte_index) {
+         while ((*p) && (*p)->address == current_byte_index) {
+
+           arelent *r = *p;
+           ieee_write_byte(abfd, ieee_function_either_open_b_enum);
+           if (r->sym_ptr_ptr != (asymbol **)NULL) {
+             ieee_write_expression(abfd, r->addend,
+                                   r->section,
+                                   *(r->sym_ptr_ptr));
+           }
+           else {
+             ieee_write_expression(abfd, r->addend,
+                                   r->section,
+                                   (asymbol *)NULL);
+           }
+           ieee_write_byte(abfd, ieee_function_either_close_b_enum);
+           p++;
+         }
+         /* FIXME !! Are all relocations 4 bytes ? */
+         current_byte_index += 4;
+       }
+      }
+    }
+}
+
+
+
+
+
+
+static void
+init_for_output(abfd)
+bfd *abfd;
+{
+  asection *s; 
+  for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
+    if (s->size != 0) {
+      ieee_per_section(s)->data = (bfd_byte *)(malloc(s->size));
+    }
+  }
+}
+
+/** exec and core file sections */
+
+/* set section contents is complicated with IEEE since the format is 
+* not a byte image, but a record stream.
+*/
+boolean
+ieee_set_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+unsigned char *location;
+file_ptr offset;
+int count;
+{
+  if (ieee_per_section(section)->data == (bfd_byte *)NULL) {
+    init_for_output(abfd);
+  }
+  (void) memcpy(ieee_per_section(section)->data + offset, location, count);
+  return true;
+}
+
+/*
+write the external symbols of a file, IEEE considers two sorts of
+external symbols, public, and referenced. It uses to internal forms
+to index them as well. When we write them out we turn their symbol
+values into indexes from the right base.
+*/
+static void
+ieee_write_external_part(abfd)
+bfd *abfd;
+{
+  asymbol **q;
+  ieee_data_type *ieee = ieee_data(abfd);
+
+  unsigned int reference_index = IEEE_REFERENCE_BASE;
+  unsigned int public_index = IEEE_PUBLIC_BASE;
+  ieee->w.r.external_part = bfd_tell(abfd);
+  if (abfd->outsymbols != (asymbol **)NULL) {
+    for (q = abfd->outsymbols; *q  != (asymbol *)NULL; q++) {
+      asymbol *p = *q;
+      if (p->flags & BSF_UNDEFINED) {
+       /* This must be a symbol reference .. */
+       ieee_write_byte(abfd, ieee_external_reference_enum);
+       ieee_write_int(abfd, reference_index);
+       ieee_write_id(abfd, p->name);
+       p->value = reference_index;
+       reference_index++;
+      }
+      else if(p->flags & BSF_FORT_COMM) {
+       /* This is a weak reference */
+       ieee_write_byte(abfd, ieee_external_reference_enum);
+       ieee_write_int(abfd, reference_index);
+       ieee_write_id(abfd, p->name);
+       ieee_write_byte(abfd, ieee_weak_external_reference_enum);
+       ieee_write_int(abfd, reference_index);
+       ieee_write_int(abfd, p->value);
+       ieee_write_int(abfd, BFD_FORT_COMM_DEFAULT_VALUE);
+       p->value = reference_index;
+       reference_index++;
+      }
+      else if(p->flags & BSF_GLOBAL) {
+       /* This must be a symbol definition */
+
+       ieee_write_byte(abfd, ieee_external_symbol_enum);
+       ieee_write_int(abfd, public_index );
+       ieee_write_id(abfd, p->name);
+
+       /* Write out the value */
+       ieee_write_2bytes(abfd, ieee_value_record_enum);
+       ieee_write_int(abfd, public_index);
+       if (p->section != (asection *)NULL)
+         {
+           ieee_write_expression(abfd,
+                                 p->value + p->section->output_offset,
+                                 p->section->output_section,
+                                 (asymbol *)NULL);
+         }
+       else
+         {
+           ieee_write_expression(abfd,
+                                 p->value,
+                                 (asection *)NULL,
+                                 (asymbol *)NULL);
+         }
+       p->value = public_index;
+       public_index++;
+      }
+      else {
+       /* This can happen - when there are gaps in the symbols read */
+       /* from an input ieee file */
+      }
+    }
+  }
+
+}
+
+static
+void ieee_write_me_part(abfd)
+bfd *abfd;
+{
+  ieee_data_type *ieee= ieee_data(abfd);
+  ieee->w.r.me_record = bfd_tell(abfd);
+
+  ieee_write_2bytes(abfd, ieee_value_starting_address_enum);
+  ieee_write_int(abfd, abfd->start_address);
+  ieee_write_byte(abfd, ieee_module_end_enum);
+
+}
+boolean
+ieee_write_object_contents (abfd)
+bfd *abfd;
+{
+  ieee_data_type *ieee = ieee_data(abfd);
+  unsigned int i;
+
+  /* Make a guess about the size of the header */
+  bfd_seek(abfd, 100, false);
+  /*
+     First write the symbols, this changes their values into table 
+     indeces so we cant use it after this point
+     */
+  ieee_write_external_part(abfd);     
+  ieee_write_byte(abfd, ieee_record_seperator_enum);
+
+  ieee_write_section_part(abfd);
+  ieee_write_byte(abfd, ieee_record_seperator_enum);
+  /* 
+     Can only write the data once the symbols have been written since
+     the data contains relocation information which points to the
+     symbols 
+     */
+  ieee_write_data_part(abfd);     
+  ieee_write_byte(abfd, ieee_record_seperator_enum);
+
+  /*
+     At the end we put the end !
+     */
+  ieee_write_me_part(abfd);
+  /* Now write the header */
+  /* Generate the header */
+  bfd_seek(abfd, (file_ptr)0, false);
+
+
+  ieee_write_byte(abfd, ieee_module_beginning_enum);
+
+  ieee_write_id(abfd, bfd_printable_arch_mach(abfd->obj_arch,
+                                             abfd->obj_machine));
+  ieee_write_id(abfd, abfd->filename);
+  ieee_write_byte(abfd, ieee_address_descriptor_enum);
+  ieee_write_byte(abfd, 8);    /* Bits per MAU */
+  ieee_write_byte(abfd, 4);    /* MAU's per address */
+
+
+  for (i= 0; i < N_W_VARIABLES; i++) {
+    ieee_write_2bytes(abfd,ieee_assign_value_to_variable_enum);
+    ieee_write_byte(abfd, i);
+    ieee_write_int(abfd, ieee->w.offset[i]);
+  }
+  return true;
+}
+
+
+
+\f
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+function exits.  We read the strings into a buffer large enough to
+hold them all plus all the cached symbol entries. */
+
+asymbol *
+ieee_make_empty_symbol (abfd)
+bfd *abfd;
+{
+
+  ieee_symbol_type  *new =
+    (ieee_symbol_type *)zalloc (sizeof (ieee_symbol_type));
+  new->symbol.the_bfd = abfd;
+  return &new->symbol;
+
+}
+
+void
+ieee_reclaim_symbol_table (abfd)
+bfd *abfd;
+{
+#if 0
+  asection *section;
+
+  if (!bfd_get_symcount (abfd)) return;
+
+  for (section = abfd->sections; section != NULL; section = section->next)
+    if (section->relocation) {
+      free ((void *)section->relocation);
+      section->relocation = NULL;
+      section->reloc_count = 0;
+    }
+
+  bfd_get_symcount (abfd) = 0;
+  free ((void *)obj_aout_symbols (abfd));
+  obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+#endif
+}
+\f
+
+
+\f
+/* Obsolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+ieee_get_symcount_upper_bound (abfd)
+bfd *abfd;
+{
+#if 0
+  /* In case we're doing an output file or something...?  */
+  if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+  return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+#endif
+return 0;
+}
+
+symindex
+ieee_get_first_symbol (ignore_abfd)
+bfd * ignore_abfd;
+{
+  return 0;
+}
+
+symindex
+ieee_get_next_symbol (abfd, oidx)
+bfd *abfd;
+symindex oidx;
+{
+#if 0
+  if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+  return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS :
+  oidx;
+#endif
+return 0;
+}
+
+char *
+ieee_symbol_name (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+  return (obj_aout_symbols (abfd) + idx)->symbol.name;
+#endif
+return 0;
+}
+
+long
+ieee_symbol_value (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+  return (obj_aout_symbols (abfd) + idx)->symbol.value;
+#endif
+return 0;
+}
+
+symclass
+ieee_classify_symbol (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+  if ((sym->symbol.flags & BSF_FORT_COMM) != 0)   return bfd_symclass_fcommon;
+  if ((sym->symbol.flags & BSF_GLOBAL) != 0)    return bfd_symclass_global;
+  if ((sym->symbol.flags & BSF_DEBUGGING) != 0)  return bfd_symclass_debugger;
+  if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+#endif
+  return bfd_symclass_unknown;
+}
+
+boolean
+ieee_symbol_hasclass (abfd, idx, class)
+bfd *abfd;
+symindex idx;
+symclass class;
+{
+#if 0
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+  switch (class) {
+  case bfd_symclass_fcommon:
+    return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+  case bfd_symclass_global:
+    return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+  case bfd_symclass_debugger:
+    return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+  case bfd_symclass_undefined:
+    return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+  default: return false;
+  }
+#endif
+return 0;
+}
+
+
+void
+ieee_reclaim_reloc (ignore_abfd, section)
+bfd *ignore_abfd;
+sec_ptr section;
+{
+#if 0
+  if (section->relocation) {
+    free (section->relocation);
+    section->relocation = NULL;
+    section->reloc_count = 0;
+  }
+#endif
+}
+
+boolean
+ieee_close_and_cleanup (abfd)
+bfd *abfd;
+{
+  if (bfd_read_p (abfd) == false)
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) {
+       return false;
+      }
+      break;
+    case bfd_object:
+      if (!ieee_write_object_contents (abfd)) {
+       return false;
+      }
+      break;
+    default:
+      bfd_error = invalid_operation;
+      return false;
+    }
+
+
+  if (ieee_data(abfd) != (ieee_data_type *)NULL) {
+    /* FIXME MORE LEAKS */
+
+  }
+
+  return true;
+}
+
+static bfd *
+ieee_openr_next_archived_file(arch, prev)
+bfd *arch;
+bfd *prev;
+{
+  ieee_ar_data_type *ar = ieee_ar_data(arch);
+  /* take the next one from the arch state, or reset */
+  if (prev == (bfd *)NULL) {
+    /* Reset the index - the first two entries are bogus*/
+    ar->element_index = 2;
+  }
+  while (true) {  
+    ieee_ar_obstack_type *p = ar->elements + ar->element_index;
+    ar->element_index++;
+    if (ar->element_index <= ar->element_count) {
+      if (p->file_offset != (file_ptr)0) {
+       if (p->abfd == (bfd *)NULL) {
+         p->abfd = _bfd_create_empty_archive_element_shell(arch);
+         p->abfd->origin = p->file_offset;
+       }
+       return p->abfd;
+      }
+    }
+    else {
+      return (bfd *)NULL;
+    }
+
+  }
+}
+
+static boolean
+ieee_find_nearest_line(abfd,
+                        section,
+                        symbols,
+                        offset,
+                        filename_ptr,
+                        functionname_ptr,
+                        line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+  return false;
+
+}
+/*SUPPRESS 460 */
+bfd_target ieee_vec =
+{
+  "ieee",                      /* name */
+  bfd_target_ieee_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
+   |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  ieee_close_and_cleanup,      /* _close_and_cleanup */
+  ieee_set_section_contents,    /* bfd_set_section_contents */
+  ieee_get_section_contents,
+  ieee_new_section_hook,       /*   new_section_hook */
+  0,                           /* _core_file_failing_command */
+  0,                           /* _core_file_failing_signal */
+  0,                           /* _core_file_matches_ex...p */
+
+  0,                           /* bfd_slurp_bsd_armap,               bfd_slurp_armap */
+  bfd_true,                    /* bfd_slurp_extended_name_table */
+  bfd_bsd_truncate_arname,     /* bfd_truncate_arname */
+
+  ieee_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  ieee_get_symtab,             /* canonicalize_symtab */
+  0,                           /* ieee_reclaim_symbol_table,            bfd_reclaim_symbol_table */
+  ieee_get_reloc_upper_bound,  /* get_reloc_upper_bound */
+  ieee_canonicalize_reloc,     /* bfd_canonicalize_reloc */
+  0,                           /*  ieee_reclaim_reloc,                   bfd_reclaim_reloc */
+  0,                           /* ieee_get_symcount_upper_bound,        bfd_get_symcount_upper_bound */
+  0,                           /* ieee_get_first_symbol,                bfd_get_first_symbol */
+  0,                           /* ieee_get_next_symbol,                 bfd_get_next_symbol */
+  0,                           /* ieee_classify_symbol,                 bfd_classify_symbol */
+  0,                           /* ieee_symbol_hasclass,                 bfd_symbol_hasclass */
+  0,                           /* ieee_symbol_name,                     bfd_symbol_name */
+  0,                           /* ieee_symbol_value,                    bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target,
+     ieee_object_p,            /* bfd_check_format */
+     ieee_archive_p,
+     bfd_false
+     },
+  {
+    bfd_false,
+    ieee_mkobject, 
+    _bfd_generic_mkarchive,
+    bfd_false
+    },
+  ieee_make_empty_symbol,
+  ieee_print_symbol,
+  bfd_false,                   /*      ieee_get_lineno,*/
+  ieee_set_arch_mach,          /* bfd_set_arch_mach,*/
+  bfd_false,
+  ieee_openr_next_archived_file,
+  ieee_find_nearest_line,      /* bfd_find_nearest_line */
+};
diff --git a/bfd/libaout.h b/bfd/libaout.h
new file mode 100644 (file)
index 0000000..febe2f4
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/* BFD back-end data structures for a.out (and similar) files.
+
+   We try to encapsulate the differences in a few routines, and otherwise
+   share large masses of code.  This means we only have to fix bugs in
+   one place, most of the time.  */
+
+/** a.out files */
+
+#define exec_hdr(bfd) (((struct sunexdata *) ((bfd)->tdata))->hdr)
+/*#define obj_symbols(bfd) ((((struct sunexdata *) ((bfd)->tdata))->symbols))*/
+#define obj_textsec(bfd)  (((struct sunexdata *) ((bfd)->tdata))->textsec)
+#define obj_datasec(bfd)  (((struct sunexdata *) ((bfd)->tdata))->datasec)
+#define obj_bsssec(bfd)  (((struct sunexdata *) ((bfd)->tdata))->bsssec)
+#define        obj_sym_filepos(bfd) (((struct sunexdata *) ((bfd)->tdata))->sym_filepos)
+#define        obj_str_filepos(bfd) (((struct sunexdata *) ((bfd)->tdata))->str_filepos)
+
+
+
+typedef struct {
+  asymbol symbol;
+  short desc;
+char other;
+unsigned char type;
+} aout_symbol_type;
+
+
+struct sunexdata {
+  struct exec *hdr;               /* exec file header */
+  aout_symbol_type *symbols;           /* symtab for input bfd */
+
+  
+  /* For ease, we do this */
+  asection *textsec;
+  asection *datasec;
+  asection *bsssec;
+
+  /* We remember these offsets so that after check_file_format, we have
+     no dependencies on the particular format of the exec_hdr.  */
+  file_ptr sym_filepos;
+  file_ptr str_filepos;
+};
+
+
+#define obj_outsymbols(bfd) ((void *)(((struct sunexdata *) ((bfd)->tdata))->outsymbols))
+
+
+
+/* We case the address of the first element of a asymbol to ensure that the
+ * macro is only every applied to an asymbol
+ */
+#define aout_symbol(asymbol) ((aout_symbol_type *)(&(asymbol)->the_bfd))
+
+/*#define obj_symbols(bfd) ((((struct sunexdata *) ((bfd)->tdata))->symbols))*/
+#define obj_aout_symbols(bfd) ((((struct sunexdata *) (bfd)->tdata))->symbols)
+#define obj_arch_flags(bfd) ((((struct sunexdata *) (bfd)->tdata))->arch_flags)
+
+#define get_tdata(x)  ((struct sunexdata *)((x)->tdata))
+#define set_tdata(x,y)  ((x)->tdata = (void *) (y))
+
+
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
new file mode 100644 (file)
index 0000000..9998690
--- /dev/null
@@ -0,0 +1,332 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/*** libbfd.c -- random bfd support routines used internally only. */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+\f
+/** Dummies for targets that don't want or need to implement
+   certain operations */
+
+boolean
+_bfd_dummy_new_section_hook (ignore, ignore_newsect)
+     bfd *ignore;
+     asection *ignore_newsect;
+{
+  return true;
+}
+
+boolean
+bfd_false (ignore)
+     bfd *ignore;
+{
+  return false;
+}
+
+boolean
+bfd_true (ignore)
+     bfd *ignore;
+{
+  return true;
+}
+
+void *
+bfd_nullvoidptr(ignore)
+bfd *ignore;
+{
+  return (void *)NULL;
+}
+int 
+bfd_0(ignore)
+bfd *ignore;
+{
+  return 0;
+}
+unsigned int 
+bfd_0u(ignore)
+bfd *ignore;
+{
+   return 0;
+}
+
+void 
+bfd_void(ignore)
+bfd *ignore;
+{
+}
+
+boolean
+_bfd_dummy_core_file_matches_executable_p (ignore_core_bfd, ignore_exec_bfd)
+     bfd *ignore_core_bfd;
+bfd *ignore_exec_bfd;
+{
+  bfd_error = invalid_operation;
+  return false;
+}
+
+/* of course you can't initialize a function to be the same as another, grr */
+
+char *
+_bfd_dummy_core_file_failing_command (ignore_abfd)
+     bfd *ignore_abfd;
+{
+  return (char *)NULL;
+}
+
+int
+_bfd_dummy_core_file_failing_signal (ignore_abfd)
+     bfd *ignore_abfd;
+{
+  return 0;
+}
+
+bfd_target *
+_bfd_dummy_target (ignore_abfd)
+     bfd *ignore_abfd;
+{
+  return 0;
+}
+\f
+/** zalloc -- allocate and clear storage */
+
+
+#ifndef zalloc
+char *
+zalloc (size)
+     size_t size;
+{
+  char *ptr = malloc (size);
+
+  if ((ptr != NULL) && (size != 0))
+    bzero (ptr, size);
+
+  return ptr;
+}
+#endif
+\f
+/* Some IO code */
+
+
+/* Note that archive entries don't have streams; they share their parent's.
+   This allows someone to play with the iostream behind bfd's back.
+
+   Also, note that the origin pointer points to the beginning of a file's
+   contents (0 for non-archive elements).  For archive entries this is the
+   first octet in the file, NOT the beginning of the archive header. */
+
+size_t
+bfd_read (ptr, size, nitems, abfd)
+     void *ptr;
+     size_t size;
+     size_t nitems;
+     bfd *abfd;
+{
+  return fread (ptr, 1, size*nitems, bfd_cache_lookup(abfd));
+}
+
+size_t
+bfd_write (ptr, size, nitems, abfd)
+     void *ptr;
+     size_t size;
+     size_t nitems;
+     bfd *abfd;
+{
+  return  fwrite (ptr, 1, size*nitems, bfd_cache_lookup(abfd));
+}
+
+int
+bfd_seek (abfd, position, direction)
+bfd *abfd;
+file_ptr position;
+int direction;
+{
+       /* For the time being, a bfd may not seek to it's end.  The
+          problem is that we don't easily have a way to recognize
+          the end of an element in an archive. */
+
+       BFD_ASSERT(direction == SEEK_SET
+                  || direction == SEEK_CUR);
+       
+       if (direction == SEEK_SET && abfd->my_archive != NULL) 
+           {
+                   /* This is a set within an archive, so we need to
+                      add the base of the object within the archive */
+                   return(fseek(bfd_cache_lookup(abfd),
+                                position + abfd->origin,
+                                direction));
+           }
+       else 
+           {
+                   return(fseek(bfd_cache_lookup(abfd),  position, direction));
+           }   
+}
+
+long
+bfd_tell (abfd)
+     bfd *abfd;
+{
+       file_ptr ptr;
+
+       ptr = ftell (bfd_cache_lookup(abfd));
+
+       if (abfd->my_archive)
+           ptr -= abfd->origin;
+       return ptr;
+}
+\f
+/** Make a string table */
+
+/* Add string to table pointed to by table, at location starting with free_ptr.
+   resizes the table if necessary (if it's NULL, creates it, ignoring
+   table_length).  Updates free_ptr, table, table_length */
+
+boolean
+bfd_add_to_string_table (table, new_string, table_length, free_ptr)
+     char **table, **free_ptr;
+     char *new_string;
+     unsigned int *table_length;
+{
+  size_t string_length = strlen (new_string) + 1; /* include null here */
+  char *base = *table;
+  size_t space_length = *table_length;
+  unsigned int offset = (base ? *free_ptr - base : 0);
+
+  if (base == NULL) {
+    /* Avoid a useless regrow if we can (but of course we still
+       take it next time */
+    space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ?
+                   DEFAULT_STRING_SPACE_SIZE : string_length+1);
+    base = zalloc (space_length);
+
+    if (base == NULL) {
+      bfd_error = no_memory;
+      return false;
+    }
+  }
+
+  if ((size_t)(offset + string_length) >= space_length) {
+    /* Make sure we will have enough space */
+    while ((size_t)(offset + string_length) >= space_length) 
+      space_length += space_length/2; /* grow by 50% */
+
+    base = (char *) realloc (base, space_length);
+    if (base == NULL) {
+      bfd_error = no_memory;
+      return false;
+    }
+
+  }
+
+  memcpy (base + offset, new_string, string_length);
+  *table = base;
+  *table_length = space_length;
+  *free_ptr = base + offset + string_length;
+  
+  return true;
+}
+\f
+/** The do-it-yourself (byte) sex-change kit */
+
+/* The middle letter e.g. get<b>short indicates Big or Little endian
+   target machine.  It doesn't matter what the byte order of the host
+   machine is; these routines work for either.  */
+
+/* FIXME: Should these take a count argument?
+   Answer (gnu@cygnus.com):  No, but perhaps they should be inline
+                            functions in swap.h #ifdef __GNUC__. 
+                            Gprof them later and find out.  */
+
+short
+_do_getbshort (addr)
+       register bfd_byte *addr;
+{
+       return (addr[0] << 8) | addr[1];
+}
+
+short
+_do_getlshort (addr)
+       register bfd_byte *addr;
+{
+       return (addr[1] << 8) | addr[0];
+}
+
+void
+_do_putbshort (data, addr)
+       int data;               /* Actually short, but ansi C sucks */
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte)(data >> 8);
+       addr[1] = (bfd_byte )data;
+}
+
+void
+_do_putlshort (data, addr)
+       int data;               /* Actually short, but ansi C sucks */
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte )data;
+       addr[1] = (bfd_byte)(data >> 8);
+}
+
+long
+_do_getblong (addr)
+       register bfd_byte *addr;
+{
+       return ((((addr[0] << 8) | addr[1]) << 8) | addr[2]) << 8 | addr[3];
+}
+
+long
+_do_getllong (addr)
+       register bfd_byte *addr;
+{
+       return ((((addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0];
+}
+
+void
+_do_putblong (data, addr)
+       unsigned long data;
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte)(data >> 24);
+       addr[1] = (bfd_byte)(data >> 16);
+       addr[2] = (bfd_byte)(data >>  8);
+       addr[3] = (bfd_byte)data;
+}
+
+void
+_do_putllong (data, addr)
+       unsigned long data;
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte)data;
+       addr[1] = (bfd_byte)(data >>  8);
+       addr[2] = (bfd_byte)(data >> 16);
+       addr[3] = (bfd_byte)(data >> 24);
+}
+
+
+
+
+
+
+
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
new file mode 100644 (file)
index 0000000..790d957
--- /dev/null
@@ -0,0 +1,160 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/*** libbfd.h -- Declarations used by bfd library implementation.
+   This include file is not for users of the library */
+
+
+
+
+
+/* If you want to read and write large blocks, you might want to do it
+   in quanta of this amount */
+#define DEFAULT_BUFFERSIZE 8192
+
+/* tdata for an archive.  For an input archive cache
+   needs to be free()'d.  For an output archive, symdefs do.
+*/
+
+struct artdata {
+  file_ptr first_file_filepos;
+  /* Speed up searching the armap */
+  struct ar_cache *cache;
+  bfd *archive_head;            /* Only interesting in output routines */
+  carsym *symdefs;             /* the symdef entries */
+  symindex symdef_count;             /* how many there are */
+  char *extended_names;                /* clever intel extension */
+};
+
+#define bfd_ardata(bfd) ((struct artdata *) ((bfd)->tdata))
+#define bfd_set_ardata(bfd, v) ((bfd)->tdata = (void *) (v))
+
+/* Goes in bfd's arelt_data slot */
+struct areltdata {
+  char * arch_header;                       /* it's actually a string */
+  unsigned int parsed_size;     /* octets of filesize not including ar_hdr */
+  char *filename;                           /* null-terminated */
+};
+
+#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
+
+/* FIXME -- a lot of my code allocates a large block and subdivides it.
+   This can't always work, because of alignment restrictions.  We should change
+   it before it becomes a problem -- Gumby */
+
+PROTO (char *, zalloc, (size_t size));
+PROTO (char *, realloc, (char * ptr, size_t size));
+PROTO (bfd_target *, bfd_find_target, (char *target_name));
+PROTO (size_t, bfd_read, (void *ptr, size_t size, size_t nitems, bfd *abfd));
+PROTO (size_t, bfd_write, (void *ptr, size_t size, size_t nitems, bfd *abfd));
+
+
+
+PROTO (FILE *, bfd_cache_lookup, (bfd *));
+PROTO (void, bfd_cache_close, (bfd *));
+PROTO (int, bfd_seek,(bfd*, file_ptr, int direction));
+PROTO (long, bfd_tell, (bfd *abfd));
+PROTO (bfd *, _bfd_create_empty_archive_element_shell, (bfd *obfd));
+PROTO (bfd *, look_for_bfd_in_cache, (bfd *arch_bfd, file_ptr index));
+PROTO (boolean, _bfd_generic_mkarchive, (bfd *abfd));
+PROTO (struct areltdata *, snarf_ar_hdr, (bfd *abfd));
+PROTO (bfd_target *, bfd_generic_archive_p, (bfd *abfd));
+PROTO (boolean, bfd_slurp_bsd_armap, (bfd *abfd));
+PROTO (boolean, bfd_slurp_coff_armap, (bfd *abfd));
+PROTO (boolean, _bfd_slurp_extended_name_table, (bfd *abfd));
+PROTO (boolean, _bfd_write_archive_contents, (bfd *abfd));
+PROTO (bfd *, new_bfd, ());
+
+#define DEFAULT_STRING_SPACE_SIZE 0x2000
+PROTO (boolean, bfd_add_to_string_table, (char **table, char *new_string,
+                                         unsigned int *table_length,
+                                         char **free_ptr));
+     
+PROTO (long, _do_getblong, (unsigned char *addr));
+PROTO (long, _do_getllong, (unsigned char *addr));
+PROTO (short, _do_getbshort, (unsigned char *addr));
+PROTO (short, _do_getlshort, (unsigned char *addr));
+PROTO (void, _do_putblong, (unsigned long data, unsigned char *addr));
+PROTO (void, _do_putllong, (unsigned long data, unsigned char *addr));
+PROTO (void, _do_putbshort, (int data, unsigned char *addr));
+PROTO (void, _do_putlshort, (int data, unsigned char *addr));
+
+PROTO (boolean, bfd_false, (bfd *ignore));
+PROTO (boolean, bfd_true, (bfd *ignore));
+PROTO (void *, bfd_nullvoidptr, (bfd *ignore));
+PROTO (int, bfd_0, (bfd *ignore));
+PROTO (unsigned int, bfd_0u, (bfd *ignore));
+PROTO (void, bfd_void, (bfd *ignore));
+
+
+PROTO (bfd *,new_bfd_contained_in,(bfd *));
+PROTO (boolean, _bfd_dummy_new_section_hook, (bfd *ignore, asection *newsect));
+PROTO (char *, _bfd_dummy_core_file_failing_command, (bfd *abfd));
+PROTO (int, _bfd_dummy_core_file_failing_signal, (bfd *abfd));
+PROTO (boolean, _bfd_dummy_core_file_matches_executable_p, (bfd *core_bfd,
+                                                           bfd *exec_bfd));
+PROTO (bfd_target *, _bfd_dummy_target, (bfd *abfd));
+
+PROTO (void, bfd_dont_truncate_arname, (bfd *abfd, char *filename, char *hdr));
+PROTO (void, bfd_bsd_truncate_arname, (bfd *abfd, char *filename, char *hdr));
+PROTO (void, bfd_gnu_truncate_arname, (bfd *abfd, char *filename, char *hdr));
+
+PROTO (boolean, bsd_write_armap, (bfd *arch, unsigned int elength,
+                                 struct orl *map, int orl_count, int stridx));
+
+PROTO (boolean, coff_write_armap, (bfd *arch, unsigned int elength,
+                                  struct orl *map, int orl_count, int stridx));
+
+PROTO ( bfd *,bfd_generic_openr_next_archived_file, (bfd *archive, bfd *last_file));
+
+PROTO(int, bfd_generic_stat_arch_elt, (bfd *, struct stat *));
+/* Macros to tell if bfds are read or write enabled.
+
+   Note that bfds open for read may be scribbled into if the fd passed
+   to bfd_fdopenr is actually open both for read and write
+   simultaneously.  However an output bfd will never be open for
+   read.  Therefore sometimes you want to check bfd_read_p or
+   !bfd_read_p, and only sometimes bfd_write_p.
+*/
+
+#define bfd_read_p(abfd) ((abfd)->direction == read_direction || (abfd)->direction == both_direction)
+#define bfd_write_p(abfd) ((abfd)->direction == write_direction || (abfd)->direction == both_direction)
+
+PROTO (void, bfd_assert,(char*,int));
+#define BFD_ASSERT(x) \
+{ if (!(x)) bfd_assert(__FILE__,__LINE__); }
+
+#define BFD_FAIL() \
+{ bfd_assert(__FILE__,__LINE__); }
+
+PROTO (FILE *, bfd_cache_lookup_worker, (bfd *));
+
+extern bfd *bfd_last_cache;
+#define bfd_cache_lookup(x) \
+     (x==bfd_last_cache?(FILE*)(bfd_last_cache->iostream):bfd_cache_lookup_worker(x))
+    
+/* Now Steve, what's the story here? */
+#ifdef lint
+#define itos(x) "l"
+#define stoi(x) 1
+#else
+#define itos(x) ((char*)(x))
+#define stoi(x) ((int)(x))
+#endif
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
new file mode 100644 (file)
index 0000000..46f5a78
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/* BFD COFF object file private structure.  */
+
+/* Object file tdata; access macros */
+
+#define obj_icof(bfd)          ((struct icofdata *) ((bfd)->tdata))
+#define exec_hdr(bfd)          (obj_icof(bfd)->hdr)
+#define obj_symbols(bfd)       (obj_icof(bfd)->symbols)
+#define        obj_sym_filepos(bfd)    (obj_icof(bfd)->sym_filepos)
+
+#define obj_relocbase(bfd)     (obj_icof(bfd)->relocbase)
+#define obj_raw_syments(bfd)   (obj_icof(bfd)->raw_syments)
+#define obj_convert(bfd)       (obj_icof(bfd)->conversion_table)
+#define obj_symbol_slew(bfd)   (obj_icof(bfd)->symbol_index_slew)
+#define obj_string_table(bfd)  (obj_icof(bfd)->string_table)
+
+typedef struct {
+  asymbol symbol;
+  struct syment *native;
+  struct lineno_cache_entry *lineno;
+} coff_symbol_type;
+
+struct icofdata {
+  struct aouthdr *hdr;         /* exec file header */
+  coff_symbol_type  *symbols;  /* symtab for input bfd */
+  unsigned int *conversion_table;
+  file_ptr sym_filepos;
+
+  long symbol_index_slew;      /* used during read to mark whether a
+                                  C_FILE symbol as been added. */
+
+  struct syment *raw_syments;
+  struct lineno *raw_linenos;
+  unsigned int raw_syment_count;
+  char *string_table;
+  /* These are only valid once writing has begun */
+  long int relocbase;
+
+};
+
+/* We cast the address of the first element of a asymbol to ensure that the
+ * macro is only ever applied to an asymbol.  */
+#define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd)))
diff --git a/bfd/libieee.h b/bfd/libieee.h
new file mode 100644 (file)
index 0000000..aefc5fd
--- /dev/null
@@ -0,0 +1,90 @@
+typedef struct {
+  unsigned int index:24;
+  char letter;
+} ieee_symbol_index_type;
+
+typedef struct ieee_symbol_struct {
+  asymbol symbol;
+  struct ieee_symbol_struct *next;
+
+unsigned int index;
+} ieee_symbol_type;
+
+
+typedef struct ieee_reloc_struct {
+  arelent relent;
+  struct ieee_reloc_struct *next;
+  ieee_symbol_index_type symbol;
+
+} ieee_reloc_type;
+
+#define ieee_symbol(x) ((ieee_symbol_type *)(x))
+
+typedef struct ieee_per_section_struct
+{
+  asection *section;
+  bfd_byte *data;
+  bfd_vma offset;
+  struct  obstack reloc_obstack;
+  ieee_reloc_type **reloc_tail_ptr;
+bfd_vma pc;
+  /* For output */
+  file_ptr current_pos;
+  unsigned int current_byte;
+  boolean initialized;
+} ieee_per_section_type;
+
+#define ieee_per_section(x) ((ieee_per_section_type *)((x)->used_by_bfd))
+#define NSECTIONS 10
+
+  
+
+typedef struct {
+  boolean read_symbols;
+boolean read_data;
+  file_ptr output_cursor;
+  /* Map of section indexes to section ptrs */
+ asection * section_table[NSECTIONS];
+  ieee_address_descriptor_type ad;
+  ieee_module_begin_type mb;
+  ieee_w_variable_type w;
+
+  unsigned int section_count;
+
+  unsigned int map_idx;
+  /* List of GLOBAL EXPORT symbols */
+  ieee_symbol_type *external_symbols;
+ /* List of UNDEFINED symbols */
+  ieee_symbol_type *external_reference;
+
+/* When the symbols have been canonicalized, they are in a
+ * special order, we remember various bases here.. */
+  unsigned int external_symbol_max_index;
+  unsigned int external_symbol_min_index;
+  unsigned int external_symbol_count;
+  int external_symbol_base_offset;
+
+  unsigned int external_reference_max_index;
+  unsigned int external_reference_min_index;
+  unsigned int external_reference_count;
+  int external_reference_base_offset;
+
+
+boolean symbol_table_full;
+} ieee_data_type;
+
+typedef struct {
+  file_ptr file_offset;
+  bfd *abfd;
+} ieee_ar_obstack_type;
+
+typedef struct {
+  ieee_ar_obstack_type *elements;
+  struct  obstack element_obstack;
+  unsigned  int element_index ;
+  unsigned int element_count;
+} ieee_ar_data_type;
+#define ieee_data(abfd) ((ieee_data_type *)((abfd)->tdata))
+#define ieee_ar_data(abfd) ((ieee_ar_data_type *)((abfd)->tdata))
+
+
diff --git a/bfd/liboasys.h b/bfd/liboasys.h
new file mode 100644 (file)
index 0000000..59e4a89
--- /dev/null
@@ -0,0 +1,70 @@
+
+
+typedef struct {
+  asymbol symbol;
+} oasys_symbol_type;
+
+typedef struct oasys_reloc_struct {
+  arelent relent;
+  struct oasys_reloc_struct *next;
+  unsigned int symbol;
+} oasys_reloc_type;
+
+
+#define oasys_symbol(x) ((oasys_symbol_type *)(x))
+#define oasys_per_section(x) ((oasys_per_section_type *)(x->used_by_bfd))
+typedef struct oasys_per_section_struct
+{
+  asection *section;
+  bfd_byte *data;
+  bfd_vma offset;
+
+  oasys_reloc_type **reloc_tail_ptr;
+  bfd_vma pc;
+  /* For output */
+  struct obstack reloc_obstack;
+  file_ptr current_pos;
+  unsigned int current_byte;
+  boolean initialized;
+} oasys_per_section_type;
+
+#define NSECTIONS 10
+
+  
+
+
+
+typedef struct {
+  file_ptr file_offset;
+  bfd *abfd;
+} oasys_ar_obstack_type;
+
+
+typedef struct {
+  file_ptr pos;
+  unsigned int size;
+  bfd *abfd;
+char *name;
+
+} oasys_module_info_type;
+
+typedef struct {
+  oasys_module_info_type *module;
+  unsigned int module_count;
+  unsigned int module_index;
+} oasys_ar_data_type;
+
+typedef struct {
+
+  char *strings;
+  asymbol *symbols;
+  unsigned int symbol_string_length;
+  asection *sections[OASYS_MAX_SEC_COUNT];
+  file_ptr first_data_record;
+} oasys_data_type;
+
+#define oasys_data(abfd) ((oasys_data_type *)((abfd)->tdata))
+#define oasys_ar_data(abfd) ((oasys_ar_data_type *)((abfd)->tdata))
+
+
+
diff --git a/bfd/misc.c b/bfd/misc.c
new file mode 100755 (executable)
index 0000000..041fcde
--- /dev/null
@@ -0,0 +1,98 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#if 0
+ /* xoxorich.  coelesced from other binutils. */
+/* This crap should all be bundled with the binutils, or else be in its
+   own library, but for expediency we are doing it this way right now. */
+
+/*
+ * Last Mod Mon Feb 18 14:49:39 PST 1991, by rich@cygint.cygnus.com
+ */
+
+#include <stdio.h>
+#include "misc.h"
+#if __STDC__
+extern char *realloc (char * ptr, int size);
+extern char *malloc (int size);
+#else
+extern char *realloc ();
+extern char *malloc ();
+#endif
+
+/* Print the filename of the current file on 'outfile' (a stdio stream).  */
+
+/* Current file's name */
+
+char *input_name;
+
+/* Current member's name, or 0 if processing a non-library file.  */
+
+char *input_member;
+
+void print_file_name (outfile)
+     FILE *outfile;
+{
+  fprintf (outfile, "%s", input_name);
+  if (input_member)
+    fprintf (outfile, "(%s)", input_member);
+}
+\f
+/* process one input file */
+void scan_library ();
+
+char *program_name;
+
+/* Report a nonfatal error.
+   STRING is a format for printf, and ARG1 ... ARG3 are args for it.  */
+/*VARARGS*/
+void
+error (string, arg1, arg2, arg3)
+     char *string, *arg1, *arg2, *arg3;
+{
+  fprintf (stderr, "%s: ", program_name);
+  fprintf (stderr, string, arg1, arg2, arg3);
+  fprintf (stderr, "\n");
+}
+
+
+
+/* Report a nonfatal error.
+   STRING is printed, followed by the current file name.  */
+
+void
+error_with_file (string)
+     char *string;
+{
+  fprintf (stderr, "%s: ", program_name);
+  print_file_name (stderr);
+  fprintf (stderr, ": ");
+  fprintf (stderr, string);
+  fprintf (stderr, "\n");
+}
+
+/* Like malloc but get fatal error if memory is exhausted.  */
+
+
+/* Like realloc but get fatal error if memory is exhausted.  */
+
+
+/* end of misc.c */
+#endif
diff --git a/bfd/misc.h b/bfd/misc.h
new file mode 100755 (executable)
index 0000000..05935c2
--- /dev/null
@@ -0,0 +1,93 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/* xoxorich. coelesced from binutils.
+ *
+ * Last Mod Mon Feb 18 14:49:51 PST 1991, by rich@cygint.cygnus.com
+ */
+
+#ifndef MISC_H
+#define MISC_H 1
+
+#include "ranlib.h"
+
+#ifdef USG
+#include <string.h>
+#else
+#include <strings.h>
+#endif /* USG */
+
+#ifdef never
+#ifdef LOCKS
+#undef LOCKS
+#endif /* LOCKS */
+#endif /* never */
+
+ /* used for masking system io calls into stdio. */
+
+/* the name, ie, argv[0], of this program. */
+
+extern char *program_name;
+
+/* Current file's name */
+
+extern char *input_name;
+
+/* Current member's name, or 0 if processing a non-library file.  */
+
+extern char *input_member;
+
+/* Report an error using the message for the last failed system call,
+   followed by the string NAME.  */
+
+#define perror_name(name)      perror(concat(program_name, ": error on ", name))
+#define pfatal_with_name(name) {perror_name(name);exit(-1);}
+
+#ifdef __STDC__
+
+extern char *concat(char *a, char *b, char *c);
+extern void *xmalloc(unsigned int size);
+extern void * xrealloc(char *ptr, int size);
+extern void error(char *string, char *arg1, char *arg2, char *arg3);
+extern void error_with_file(char *string);
+extern void fatal(char *string, char*a1, char*a2, char*a3);
+extern void print_file_name(FILE *outfile);
+extern void swap_symdef_table(struct symdef *sym, int count);
+#else
+extern char *alloca();
+extern char *concat();
+extern void * xmalloc();
+extern void *xrealloc();
+extern void error();
+extern void error_with_file();
+extern void fatal();
+extern void print_file_name();
+extern void swap_symdef_table();
+#endif /* __STDC__ */
+
+#endif /* MISC_H */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * End:
+ */
+
+/* end of misc.h */
diff --git a/bfd/oasys.c b/bfd/oasys.c
new file mode 100644 (file)
index 0000000..995d962
--- /dev/null
@@ -0,0 +1,986 @@
+/*
+   
+ bfd backend for oasys objects.
+
+
+ Object files contain records in order:
+
+ optional header
+ symbol records
+ section records
+ data records
+ debugging records
+ end record
+
+
+
+   Written by Steve Chamberlain
+   steve@cygnus.com
+
+
+
+ */
+
+
+#include <ansidecl.h>
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "oasys.h"
+#include "liboasys.h"
+
+
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+typedef void generic_symbol_type;
+
+
+void DEFUN(oasys_read_record,(abfd, record),
+      bfd *abfd AND 
+      oasys_record_union_type *record)
+{
+
+  bfd_read(record, 1, sizeof(record->header), abfd);
+
+  bfd_read(((char *)record )+ sizeof(record->header),
+          1, record->header.length - sizeof(record->header),
+          abfd);
+}
+static size_t
+oasys_string_length(record)
+oasys_record_union_type *record;
+{
+return  record->header.length
+       - ((char *)record->symbol.name - (char *)record);
+}
+
+/*****************************************************************************/
+
+/*
+
+Slurp the symbol table by reading in all the records at the start file
+till we get to the first section record.
+
+We'll sort the symbols into  two lists, defined and undefined. The
+undefined symbols will also be sorted by refno. We do this by placing
+all undefined symbols at the front of the table moving in, and the
+defined symbols at the end of the table moving back.
+
+*/
+
+static boolean
+oasys_slurp_symbol_table(abfd)
+bfd *abfd;
+{
+  oasys_record_union_type record;
+  oasys_data_type *data = oasys_data(abfd);
+  boolean loop = true;
+  asymbol *dest_undefined;
+  asymbol *dest_defined;
+  asymbol *dest;
+  char *string_ptr;
+
+
+  if (data->symbols != (asymbol *)NULL) {
+    return true;
+  }
+  /* Buy enough memory for all the symbols and all the names */
+  data->symbols = 
+    (asymbol *)malloc(sizeof(asymbol) * abfd->symcount);
+  data->strings = malloc(data->symbol_string_length);
+
+  dest_undefined = data->symbols;
+  dest_defined = data->symbols + abfd->symcount -1;
+
+  string_ptr = data->strings;
+  bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+  while (loop) {
+    oasys_read_record(abfd, &record);
+    switch (record.header.type) {
+    case oasys_record_is_header_enum:
+      break;
+    case oasys_record_is_local_enum:
+    case oasys_record_is_symbol_enum:
+       {
+         size_t length = oasys_string_length(&record);
+         switch (record.symbol.relb[0] & RELOCATION_TYPE_BITS) {
+         case RELOCATION_TYPE_ABS:
+           dest = dest_defined--;
+           dest->section = 0;
+           dest->flags = BSF_ABSOLUTE | BSF_EXPORT | BSF_GLOBAL;
+           dest_defined--;
+           break;
+         case RELOCATION_TYPE_REL:
+           dest = dest_defined--;
+           dest->section =
+             oasys_data(abfd)->sections[record.symbol.relb[0] &
+                                        RELOCATION_SECT_BITS];
+           if (record.header.type == oasys_record_is_local_enum) 
+               {
+                 dest->flags =  BSF_LOCAL;
+               }
+           else {
+
+             dest->flags = BSF_EXPORT | BSF_GLOBAL;
+           }
+           break;
+         case RELOCATION_TYPE_UND:
+           dest = dest_undefined++;
+           dest->section = (asection *)NULL;
+           dest->flags = BSF_UNDEFINED;
+           break;
+         case RELOCATION_TYPE_COM:
+           dest = dest_defined--;
+           dest->name = string_ptr;
+           dest->the_bfd = abfd;
+
+           dest->section = (asection *)NULL;
+           dest->flags = BSF_FORT_COMM;
+           break;
+         }
+         dest->name = string_ptr;
+         dest->the_bfd = abfd;
+
+         dest->value = bfd_h_getlong(abfd, &record.symbol.value);
+         memcpy(string_ptr, record.symbol.name, length);
+         string_ptr[length] =0;
+         string_ptr += length +1;
+       }
+      break;
+    default:
+      loop = false;
+    }
+  }
+  return true;
+
+}
+
+size_t
+oasys_get_symtab_upper_bound (abfd)
+bfd *abfd;
+{
+  oasys_slurp_symbol_table (abfd);
+
+  return (abfd->symcount != 0) ? 
+    (abfd->symcount+1) * (sizeof (oasys_symbol_type *)) : 0;
+}
+
+/* 
+*/
+
+extern bfd_target oasys_vec;
+
+unsigned int
+oasys_get_symtab (abfd, location)
+bfd *abfd;
+asymbol **location;
+{
+  asymbol *symbase ;
+  unsigned int counter ;
+  if (oasys_slurp_symbol_table(abfd) == false) {
+    return 0;
+  }
+  symbase = oasys_data(abfd)->symbols;
+  for (counter = 0; counter < abfd->symcount; counter++) {
+    *(location++) = symbase++;
+  }
+  *location = 0;
+  return abfd->symcount;
+}
+
+/***********************************************************************
+*  archive stuff 
+*/
+#define swap(x) x = bfd_h_get_x(abfd, &x);
+bfd_target *
+oasys_archive_p(abfd)
+bfd *abfd;
+{
+  oasys_archive_header_type header;
+  unsigned int i;
+  
+  bfd_seek(abfd, (file_ptr) 0, false);
+
+  
+  bfd_read(&header, 1, sizeof(header), abfd);
+
+  
+  swap(header.version);
+  swap(header.mod_count);
+  swap(header.mod_tbl_offset);
+  swap(header.sym_tbl_size);
+  swap(header.sym_count);
+  swap(header.sym_tbl_offset);
+  swap(header.xref_count);
+  swap(header.xref_lst_offset);
+
+  /*
+     There isn't a magic number in an Oasys archive, so the best we
+     can do to verify reasnableness is to make sure that the values in
+     the header are too weird
+     */
+
+  if (header.version>10000 ||
+      header.mod_count>10000 ||
+      header.sym_count>100000 ||
+      header.xref_count > 100000) return (bfd_target *)NULL;
+
+  /*
+     That all worked, lets buy the space for the header and read in
+     the headers.
+     */
+  {
+    oasys_ar_data_type *ar =
+      (oasys_ar_data_type*) malloc(sizeof(oasys_ar_data_type));
+
+
+    oasys_module_info_type *module = 
+      (oasys_module_info_type*)
+       malloc(sizeof(oasys_module_info_type) * header.mod_count);
+
+    oasys_module_table_type record;
+
+    oasys_ar_data(abfd) =ar;
+    ar->module = module;
+    ar->module_count = header.mod_count;
+
+    bfd_seek(abfd , header.mod_tbl_offset, SEEK_SET);
+    for (i = 0; i < header.mod_count; i++) {
+
+      bfd_read(&record, 1, sizeof(record), abfd);
+      swap(record.mod_size);
+      swap(record.file_offset);
+      swap(record.mod_name_length);
+      module[i].name = malloc(record.mod_name_length+1);
+
+      bfd_read(module[i].name, 1, record.mod_name_length +1, abfd);
+      /* SKip some stuff */
+      bfd_seek(abfd, record.dep_count * sizeof(int32_type),
+           SEEK_CUR);
+
+      module[i].size = record.mod_size;
+      module[i].pos = record.file_offset;
+    }
+      
+  }
+  return abfd->xvec;
+}
+
+#define MAX_SECS 16
+bfd_target *
+oasys_object_p (abfd)
+bfd *abfd;
+{
+  oasys_data_type *oasys;
+  oasys_data_type static_data;
+
+  boolean loop = true;
+
+
+  boolean had_usefull = false;
+
+  memset((PTR)static_data.sections, 0xff, sizeof(static_data.sections));
+    
+  /* Point to the start of the file */
+  bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+  static_data.symbol_string_length = 0;
+  /* Inspect the records, but only keep the section info -
+     remember the size of the symbols
+     */
+  while (loop) {
+    oasys_record_union_type record;
+    oasys_read_record(abfd, &record);
+    if (record.header.length < sizeof(record.header))
+      return (bfd_target *)NULL;
+
+    switch ((oasys_record_enum_type)(record.header.type)) {
+    case oasys_record_is_header_enum:
+      had_usefull = true;
+      break;
+    case oasys_record_is_symbol_enum:
+    case oasys_record_is_local_enum:
+      /* Count symbols and remember their size for a future malloc   */
+      abfd->symcount++;
+      static_data.symbol_string_length += 1 + oasys_string_length(&record);
+      had_usefull = true;
+      break;
+    case oasys_record_is_section_enum:
+      {
+       asection *s;
+       char *buffer;
+       unsigned int section_number;
+       if (record.section.header.length != sizeof(record.section))
+         {
+           return (bfd_target *)NULL;
+         }
+       buffer = malloc(3);
+       section_number= record.section.relb & RELOCATION_SECT_BITS;
+       sprintf(buffer,"%u", section_number);
+       s = bfd_make_section(abfd,buffer);
+       static_data.sections[section_number] = s;
+       switch (record.section.relb & RELOCATION_TYPE_BITS) {
+       case RELOCATION_TYPE_ABS:
+       case RELOCATION_TYPE_REL:
+         break;
+       case RELOCATION_TYPE_UND:
+       case RELOCATION_TYPE_COM:
+         BFD_FAIL();
+       }
+
+
+       s->size  = bfd_h_getlong(abfd, & record.section.value) ;
+       s->vma = bfd_h_getlong(abfd, &record.section.vma);
+       s->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
+       had_usefull = true;
+      }
+      break;
+    case oasys_record_is_data_enum:
+      static_data.first_data_record = bfd_tell(abfd) - record.header.length;
+    case oasys_record_is_debug_enum:
+    case oasys_record_is_module_enum:
+    case oasys_record_is_named_section_enum:
+    case oasys_record_is_end_enum:
+      if (had_usefull == false) return (bfd_target *)NULL;
+      loop = false;
+      break;
+    default:
+      return (bfd_target *)NULL;
+    }
+  }
+  oasys_data(abfd) = (oasys_data_type
+                     *)malloc(sizeof(oasys_data_type));
+  oasys = oasys_data(abfd);
+  * oasys = static_data;
+
+  oasys->symbols = (asymbol *)NULL;
+  /* 
+     Oasys support several architectures, but I can't see a simple way
+     to discover which one is in a particular file - we'll guess 
+     */
+  abfd->obj_arch = bfd_arch_m68k;
+  abfd->obj_machine =0;
+  if (abfd->symcount != 0) {
+    abfd->flags |= HAS_SYMS;
+  }
+  return abfd->xvec;
+}
+
+
+void 
+oasys_print_symbol(ignore_abfd, file,  symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+  switch (how) {
+  case bfd_print_symbol_name_enum:
+  case bfd_print_symbol_type_enum:
+    fprintf(file,"%s", symbol->name);
+    break;
+  case bfd_print_symbol_all_enum:
+    {
+      char *section_name = symbol->section == (asection *)NULL ?
+       "*abs" : symbol->section->name;
+
+      bfd_print_symbol_vandf((void *)file,symbol);
+
+      fprintf(file," %-5s %s",
+             section_name,
+             symbol->name);
+    }
+    break;
+  }
+}
+/*
+ The howto table is build using the top two bits of a reloc byte to
+ index into it. The bits are PCREL,WORD/LONG
+*/
+static reloc_howto_type howto_table[]= 
+{
+/* T rs size bsz pcrel bitpos abs ovr sf name partial inplace mask */
+
+{  0, 0,  1,   16, false,0,   true,true,0,"abs16",true,0x0000ffff},
+{  0, 0,  2,   32, false,0,   true,true,0,"abs32",true,0xffffffff},
+{  0, 0,  1,   16, true,0,   true,true,0,"pcrel16",true,0x0000ffff},
+{  0, 0,  2,   32, true,0,   true,true,0,"pcrel32",true,0xffffffff}
+};
+
+/* Read in all the section data and relocation stuff too */
+static boolean oasys_slurp_section_data(abfd)
+bfd *abfd;
+{
+  oasys_record_union_type record;
+  oasys_data_type *data = oasys_data(abfd);
+  boolean loop = true;
+
+  oasys_per_section_type *per ;
+
+  asection *s;
+
+  /* Buy enough memory for all the section data and relocations */
+  for (s = abfd->sections; s != (asection *)NULL; s= s->next) {
+    per =  oasys_per_section(s);
+    if (per->data != (bfd_byte*)NULL) return true;
+    per->data = (bfd_byte *) malloc(s->size);
+    obstack_init(&per->reloc_obstack);
+    per->reloc_tail_ptr = (oasys_reloc_type **)&(s->relocation);
+  }
+
+  bfd_seek(abfd, data->first_data_record, SEEK_SET);
+  while (loop) {
+    oasys_read_record(abfd, &record);
+    switch (record.header.type) {
+    case oasys_record_is_header_enum:
+      break;
+    case oasys_record_is_data_enum:
+      {
+
+       uint8e_type *src = record.data.data;
+       uint8e_type *end_src = ((uint8e_type *)&record) + record.header.length;
+       unsigned int relbit;
+       bfd_byte *dst_ptr ;
+       bfd_byte *dst_base_ptr ;
+       asection *section;
+       unsigned int count;
+
+       bfd_vma dst_offset = bfd_h_getlong(abfd, record.data.addr);
+       section = data->sections[record.data.relb & RELOCATION_SECT_BITS];
+       per =  oasys_per_section(section);
+dst_base_ptr =         dst_ptr = oasys_per_section(section)->data + dst_offset;
+
+       while (src < end_src) {
+         uint8e_type mod_byte = *src++;
+         count = 8;
+
+         for (relbit = 1; count-- != 0; relbit <<=1) 
+           {
+             if (relbit & mod_byte) 
+               {
+                 uint8e_type reloc = *src;
+                 /* This item needs to be relocated */
+                 switch (reloc & RELOCATION_TYPE_BITS) {
+                 case RELOCATION_TYPE_ABS:
+
+                   break;
+
+                 case RELOCATION_TYPE_REL: 
+                   {
+                     /* Relocate the item relative to the section */
+                     oasys_reloc_type *r =
+                       (oasys_reloc_type *)
+                         obstack_alloc(&per->reloc_obstack,
+                                       sizeof(oasys_reloc_type));
+                     *(per->reloc_tail_ptr) = r;
+                     per->reloc_tail_ptr = &r->next;
+                     r->next= (oasys_reloc_type *)NULL;
+                     /* Reference to undefined symbol */
+                     src++;
+                     /* There is no symbol */
+                     r->symbol = 0;
+                     /* Work out the howto */
+                     r->relent.section =
+                       data->sections[reloc & RELOCATION_SECT_BITS];
+                     r->relent.addend = 0;
+                     r->relent.address = dst_ptr - dst_base_ptr;
+                     r->relent.howto = &howto_table[reloc>>6];
+                     section->reloc_count++;
+
+                   }
+                   break;
+
+
+                 case RELOCATION_TYPE_UND:
+                   { 
+                     oasys_reloc_type *r =
+                       (oasys_reloc_type *)
+                         obstack_alloc(&per->reloc_obstack,
+                                       sizeof(oasys_reloc_type));
+                     *(per->reloc_tail_ptr) = r;
+                     per->reloc_tail_ptr = &r->next;
+                     r->next= (oasys_reloc_type *)NULL;
+                     /* Reference to undefined symbol */
+                     src++;
+                     /* Get symbol number */
+                     r->symbol = (src[0]<<8) | src[1];
+                     /* Work out the howto */
+                     r->relent.section = (asection *)NULL;
+                     r->relent.addend = 0;
+                     r->relent.address = dst_ptr - dst_base_ptr;
+                     r->relent.howto = &howto_table[reloc>>6];
+
+                     section->reloc_count++;
+                     src+=2;
+                   }
+                   break;
+                 case RELOCATION_TYPE_COM:
+                   BFD_FAIL();
+                 }
+               }
+             *dst_ptr++ = *src++;
+           }
+       }         
+      }
+      break;
+    case oasys_record_is_local_enum:
+    case oasys_record_is_symbol_enum:
+    case oasys_record_is_section_enum:
+      break;
+    default:
+      loop = false;
+    }
+  }
+  return true;
+
+}
+
+
+
+
+
+boolean
+oasys_new_section_hook (abfd, newsect)
+bfd *abfd;
+asection *newsect;
+{
+  newsect->used_by_bfd = (oasys_per_section_type *)
+    malloc(sizeof(oasys_per_section_type));
+  oasys_per_section( newsect)->data = (bfd_byte *)NULL;
+  oasys_per_section(newsect)->section = newsect;
+  oasys_per_section(newsect)->offset  = 0;
+  return true;
+}
+
+
+unsigned int
+oasys_get_reloc_upper_bound (abfd, asect)
+bfd *abfd;
+sec_ptr asect;
+{
+  oasys_slurp_section_data(abfd);
+  return (asect->reloc_count+1) * sizeof(arelent *);
+}
+
+static boolean
+oasys_get_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+void  *location;
+file_ptr offset;
+unsigned      int count;
+{
+  oasys_per_section_type *p = section->used_by_bfd;
+  oasys_slurp_section_data(abfd);
+  (void)  memcpy(location, p->data + offset, count);
+  return true;
+}
+
+
+unsigned int
+oasys_canonicalize_reloc (abfd, section, relptr, symbols)
+bfd *abfd;
+sec_ptr section;
+arelent **relptr;
+asymbol **symbols;
+{
+  oasys_reloc_type *src = (oasys_reloc_type *)(section->relocation);
+  while (src != (oasys_reloc_type *)NULL) {
+    if (src->relent.section == (asection *)NULL) {
+    src->relent.sym_ptr_ptr = symbols + src->symbol;
+  }
+    *relptr ++ = &src->relent;
+    src = src->next;
+  }
+  *relptr = (arelent *)NULL;
+  return section->reloc_count;
+}
+
+boolean
+oasys_set_arch_mach (abfd, arch, machine)
+bfd *abfd;
+enum bfd_architecture arch;
+unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  return true;
+}
+
+boolean
+oasys_mkobject(abfd)
+bfd *abfd;
+{
+  oasys_data_type *oasys =
+    (oasys_data_type *) malloc(sizeof(oasys_data_type));
+  oasys_data(abfd) = oasys;
+  if (oasys == (oasys_data_type *)NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  return true;
+}
+
+
+
+
+
+
+
+static void
+init_for_output(abfd)
+bfd *abfd;
+{
+  asection *s; 
+  for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
+    if (s->size != 0) {
+      oasys_per_section(s)->data = (bfd_byte *)(malloc(s->size));
+    }
+  }
+}
+
+/** exec and core file sections */
+
+/* set section contents is complicated with OASYS since the format is 
+* not a byte image, but a record stream.
+*/
+boolean
+oasys_set_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+unsigned char *location;
+file_ptr offset;
+int count;
+{
+  if (oasys_per_section(section)->data == (bfd_byte *)NULL) {
+    init_for_output(abfd);
+  }
+  (void) memcpy(oasys_per_section(section)->data + offset, location, count);
+  return true;
+}
+
+
+
+\f
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+function exits.  We read the strings into a buffer large enough to
+hold them all plus all the cached symbol entries. */
+
+asymbol *
+oasys_make_empty_symbol (abfd)
+bfd *abfd;
+{
+
+  oasys_symbol_type  *new =
+    (oasys_symbol_type *)zalloc (sizeof (oasys_symbol_type));
+  new->symbol.the_bfd = abfd;
+  return &new->symbol;
+
+}
+
+void
+oasys_reclaim_symbol_table (abfd)
+bfd *abfd;
+{
+#if 0
+  asection *section;
+
+  if (!bfd_get_symcount (abfd)) return;
+
+  for (section = abfd->sections; section != NULL; section = section->next)
+    if (section->relocation) {
+      free ((void *)section->relocation);
+      section->relocation = NULL;
+      section->reloc_count = 0;
+    }
+
+  bfd_get_symcount (abfd) = 0;
+  free ((void *)obj_aout_symbols (abfd));
+  obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+#endif
+}
+\f
+
+
+\f
+/* Obsbolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+oasys_get_symcount_upper_bound (abfd)
+bfd *abfd;
+{
+#if 0
+  /* In case we're doing an output file or something...?  */
+  if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+  return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+#endif
+}
+
+symindex
+oasys_get_first_symbol (ignore_abfd)
+bfd * ignore_abfd;
+{
+  return 0;
+}
+
+symindex
+oasys_get_next_symbol (abfd, oidx)
+bfd *abfd;
+symindex oidx;
+{
+#if 0
+  if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+  return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS :
+  oidx;
+#endif
+}
+
+char *
+oasys_symbol_name (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+  return (obj_aout_symbols (abfd) + idx)->symbol.name;
+#endif
+}
+
+long
+oasys_symbol_value (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+  return (obj_aout_symbols (abfd) + idx)->symbol.value;
+#endif
+}
+
+symclass
+oasys_classify_symbol (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+  if ((sym->symbol.flags & BSF_FORT_COMM) != 0)   return bfd_symclass_fcommon;
+  if ((sym->symbol.flags & BSF_GLOBAL) != 0)    return bfd_symclass_global;
+  if ((sym->symbol.flags & BSF_DEBUGGING) != 0)  return bfd_symclass_debugger;
+  if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+#endif
+  return bfd_symclass_unknown;
+}
+
+boolean
+oasys_symbol_hasclass (abfd, idx, class)
+bfd *abfd;
+symindex idx;
+symclass class;
+{
+#if 0
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+  switch (class) {
+  case bfd_symclass_fcommon:
+    return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+  case bfd_symclass_global:
+    return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+  case bfd_symclass_debugger:
+    return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+  case bfd_symclass_undefined:
+    return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+  default: return false;
+  }
+#endif
+}
+
+
+void
+oasys_reclaim_reloc (ignore_abfd, section)
+bfd *ignore_abfd;
+sec_ptr section;
+{
+#if 0
+  if (section->relocation) {
+    free (section->relocation);
+    section->relocation = NULL;
+    section->reloc_count = 0;
+  }
+#endif
+}
+
+boolean
+oasys_close_and_cleanup (abfd)
+bfd *abfd;
+{
+  if (bfd_read_p (abfd) == false)
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) {
+       return false;
+      }
+      break;
+    case bfd_object:
+/*      if (!oasys_write_object_contents (abfd)) */{
+       return false;
+      }
+      break;
+    default:
+      bfd_error = invalid_operation;
+      return false;
+    }
+
+
+  if (oasys_data(abfd) != (oasys_data_type *)NULL) {
+    /* FIXME MORE LEAKS */
+
+  }
+
+  return true;
+}
+
+static bfd *
+oasys_openr_next_archived_file(arch, prev)
+bfd *arch;
+bfd *prev;
+{
+  oasys_ar_data_type *ar = oasys_ar_data(arch);
+  oasys_module_info_type *p;
+  /* take the next one from the arch state, or reset */
+  if (prev == (bfd *)NULL) {
+    /* Reset the index - the first two entries are bogus*/
+    ar->module_index = 0;
+  }
+
+  p = ar->module + ar->module_index;
+  ar->module_index++;
+
+  if (ar->module_index <= ar->module_count) {
+    if (p->abfd == (bfd *)NULL) {
+      p->abfd = _bfd_create_empty_archive_element_shell(arch);
+      p->abfd->origin = p->pos;
+      p->abfd->filename = p->name;
+
+      /* Fixup a pointer to this element for the member */
+      p->abfd->arelt_data = (void *)p;
+    }
+    return p->abfd;
+  }
+  else {
+    bfd_error = no_more_archived_files;
+    return (bfd *)NULL;
+  }
+}
+
+static boolean
+oasys_find_nearest_line(abfd,
+                        section,
+                        symbols,
+                        offset,
+                        filename_ptr,
+                        functionname_ptr,
+                        line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+  return false;
+
+}
+
+static int
+oasys_stat_arch_elt(abfd, buf)
+bfd *abfd;
+struct stat *buf;
+{
+  oasys_module_info_type *mod = abfd->arelt_data;
+  if (mod == (oasys_module_info_type *)NULL) {
+    bfd_error = invalid_operation;
+    return -1;
+  }
+  else {
+    buf->st_size = mod->size;
+    buf->st_mode = 0666;
+  return 0;
+  }
+
+
+}
+
+
+/*SUPPRESS 460 */
+bfd_target oasys_vec =
+{
+  "oasys",                     /* name */
+  bfd_target_oasys_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
+   |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  oasys_close_and_cleanup,     /* _close_and_cleanup */
+  oasys_set_section_contents,  /* bfd_set_section_contents */
+  oasys_get_section_contents,
+  oasys_new_section_hook,      /*   new_section_hook */
+  0,                           /* _core_file_failing_command */
+  0,                           /* _core_file_failing_signal */
+  0,                           /* _core_file_matches_ex...p */
+
+  0,                           /* bfd_slurp_bsd_armap,               bfd_slurp_armap */
+  bfd_true,                    /* bfd_slurp_extended_name_table */
+  bfd_bsd_truncate_arname,     /* bfd_truncate_arname */
+
+  oasys_get_symtab_upper_bound,        /* get_symtab_upper_bound */
+  oasys_get_symtab,            /* canonicalize_symtab */
+  0,                           /* oasys_reclaim_symbol_table,            bfd_reclaim_symbol_table */
+  oasys_get_reloc_upper_bound, /* get_reloc_upper_bound */
+  oasys_canonicalize_reloc,    /* bfd_canonicalize_reloc */
+  0,                           /*  oasys_reclaim_reloc,                   bfd_reclaim_reloc */
+  0,                           /* oasys_get_symcount_upper_bound,        bfd_get_symcount_upper_bound */
+  0,                           /* oasys_get_first_symbol,                bfd_get_first_symbol */
+  0,                           /* oasys_get_next_symbol,                 bfd_get_next_symbol */
+  0,                           /* oasys_classify_symbol,                 bfd_classify_symbol */
+  0,                           /* oasys_symbol_hasclass,                 bfd_symbol_hasclass */
+  0,                           /* oasys_symbol_name,                     bfd_symbol_name */
+  0,                           /* oasys_symbol_value,                    bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target,
+     oasys_object_p,           /* bfd_check_format */
+     oasys_archive_p,
+     bfd_false
+     },
+  {
+    bfd_false,
+    oasys_mkobject, 
+    _bfd_generic_mkarchive,
+    bfd_false
+    },
+  oasys_make_empty_symbol,
+  oasys_print_symbol,
+  bfd_false,                   /*      oasys_get_lineno,*/
+  oasys_set_arch_mach,         /* bfd_set_arch_mach,*/
+  bfd_false,
+  oasys_openr_next_archived_file,
+  oasys_find_nearest_line,     /* bfd_find_nearest_line */
+  oasys_stat_arch_elt,         /* bfd_stat_arch_elt */
+};
diff --git a/bfd/obstack.c b/bfd/obstack.c
new file mode 100755 (executable)
index 0000000..52258d3
--- /dev/null
@@ -0,0 +1,335 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+   Copyright (C) 1988 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "obstack.h"
+
+#ifdef __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment.  */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+   But in fact it might be less smart and round addresses to as much as
+   DEFAULT_ROUNDING.  So we prepare for it to do that.  */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+   On some machines, copying successive ints does not work;
+   in such a case, redefine COPYING_UNIT to `long' (if that works)
+   or `char' as a last resort.  */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+/* The non-GNU-C macros copy the obstack into this global variable
+   to avoid multiple evaluation.  */
+
+struct obstack *_obstack;
+\f
+/* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
+   Objects start on multiples of ALIGNMENT (0 means use default).
+   CHUNKFUN is the function to use to allocate chunks,
+   and FREEFUN the function to free them.  */
+
+void
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+     struct obstack *h;
+     int size;
+     int alignment;
+     POINTER (*chunkfun) ();
+     void (*freefun) ();
+{
+  register struct _obstack_chunk* chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+        Use the values for range checking, because if range checking is off,
+        the extra bytes won't be missed terribly, but if range checking is on
+        and we used a larger request, a whole extra 4096 bytes would be
+        allocated.
+
+        These number are irrelevant to the new GNU malloc.  I suspect it is
+        less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+                   + 4 + DEFAULT_ROUNDING - 1)
+                  & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+  h->chunkfun = chunkfun;
+  h->freefun = freefun;
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+
+  chunk        = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (h->chunk_size);
+  h->next_free = h->object_base = chunk->contents;
+  h->chunk_limit = chunk->limit
+   = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+}
+
+/* Allocate a new current chunk for the obstack *H
+   on the assumption that LENGTH bytes need to be added
+   to the current object, or a new object of length LENGTH allocated.
+   Copies any partial object from the end of the old chunk
+   to the beginning of the new one.  
+
+   The function must be "int" so it can be used in non-ANSI C
+   compilers in a : expression.  */
+
+int
+_obstack_newchunk (h, length)
+     struct obstack *h;
+     int length;
+{
+  register struct _obstack_chunk*      old_chunk = h->chunk;
+  register struct _obstack_chunk*      new_chunk;
+  register long        new_size;
+  register int obj_size = h->next_free - h->object_base;
+  register int i;
+  int already;
+
+  /* Compute size for new chunk.  */
+  new_size = (obj_size + length) + (obj_size >> 3) + 100;
+  if (new_size < h->chunk_size)
+    new_size = h->chunk_size;
+
+  /* Allocate and initialize the new chunk.  */
+  new_chunk = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (new_size);
+  new_chunk->prev = old_chunk;
+  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+  /* Move the existing object to the new chunk.
+     Word at a time is fast and is safe if the object
+     is sufficiently aligned.  */
+  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+    {
+      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+          i >= 0; i--)
+       ((COPYING_UNIT *)new_chunk->contents)[i]
+         = ((COPYING_UNIT *)h->object_base)[i];
+      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+        but that can cross a page boundary on a machine
+        which does not do strict alignment for COPYING_UNITS.  */
+      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+    }
+  else
+    already = 0;
+  /* Copy remaining bytes one by one.  */
+  for (i = already; i < obj_size; i++)
+    new_chunk->contents[i] = h->object_base[i];
+
+  h->object_base = new_chunk->contents;
+  h->next_free = h->object_base + obj_size;
+return 0;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+   This is here for debugging.
+   If you use it in a program, you are probably losing.  */
+
+int
+_obstack_allocated_p (h, obj)
+     struct obstack *h;
+     POINTER obj;
+{
+  register struct _obstack_chunk*  lp; /* below addr of any objects in this chunk */
+  register struct _obstack_chunk*  plp;        /* point to previous chunk if any */
+
+  lp = (h)->chunk;
+  while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
+    {
+      plp = lp -> prev;
+      lp = plp;
+    }
+  return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+   more recently than OBJ.  If OBJ is zero, free everything in H.  */
+
+#ifdef __STDC__
+#undef obstack_free
+void
+obstack_free (struct obstack *h, POINTER obj)
+#else
+int
+_obstack_free (h, obj)
+     struct obstack *h;
+     POINTER obj;
+#endif
+{
+  register struct _obstack_chunk*  lp; /* below addr of any objects in this chunk */
+  register struct _obstack_chunk*  plp;        /* point to previous chunk if any */
+
+  lp = (h)->chunk;
+  /* We use >= because there cannot be an object at the beginning of a chunk.
+     But there can be an empty object at that address
+     at the end of another chunk.  */
+  while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+    {
+      plp = lp -> prev;
+      (*h->freefun) ((POINTER) lp);
+      lp = plp;
+    }
+  if (lp)
+    {
+      (h)->object_base = (h)->next_free = (char *)(obj);
+      (h)->chunk_limit = lp->limit;
+      (h)->chunk = lp;
+    }
+  else if (obj != 0)
+    /* obj is not in any of the chunks! */
+    abort ();
+}
+
+/* Let same .o link with output of gcc and other compilers.  */
+
+#ifdef __STDC__
+int
+_obstack_free (h, obj)
+     struct obstack *h;
+     POINTER obj;
+{
+  obstack_free (h, obj);
+  return 0;
+}
+#endif
+\f
+/* #if 0 */
+/* These are now turned off because the applications do not use it
+   and it uses bcopy via obstack_grow, which causes trouble on sysV.  */
+
+/* Now define the functional versions of the obstack macros.
+   Define them to simply use the corresponding macros to do the job.  */
+
+#ifdef __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+   they won't pass through the macro names in parentheses.  */
+
+/* The function names appear in parentheses in order to prevent
+   the macro-definitions of the names from being expanded there.  */
+
+POINTER (obstack_base) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_room (obstack);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+     struct obstack *obstack;
+     int character;
+{
+  obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+     struct obstack *obstack;
+     int character;
+{
+  obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+
diff --git a/bfd/obstack.h b/bfd/obstack.h
new file mode 100755 (executable)
index 0000000..0f3b37c
--- /dev/null
@@ -0,0 +1,416 @@
+/* obstack.h - object stack macros
+   Copyright (C) 1988 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects.  Each object starts life
+small, and may grow to maturity.  (Consider building a word syllable
+by syllable.)  An object can move while it is growing.  Once it has
+been "finished" it never changes address again.  So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'.  On occasion, they free chunks,
+by calling `obstack_chunk_free'.  You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables.  Unless you are "fascist pig with a read-only mind"
+[Gosper's immortal quote from HAKMEM item 154, out of context] you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols.  At the time you are reading a symbol you don't know
+how long it is.  One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer.  This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently.  Use one obstack for all symbol
+names.  As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it.  Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses.  When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk.  When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies.  No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk.  We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object.  This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+       We allocate large chunks.
+       We carve out one object at a time from the current chunk.
+       Once carved, an object never moves.
+       We are free to append data of any size to the currently
+         growing object.
+       Exactly one object is growing in an obstack at any one time.
+       You can run one obstack per control block.
+       You may have as many control blocks as you dare.
+       Because of the way we do it, you can `unwind' a obstack
+         back to a previous state. (You may remove objects much
+         as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once.  */
+
+#ifndef __OBSTACKS__
+#define __OBSTACKS__
+\f
+/* We use subtraction of (char *)0 instead of casting to int
+   because on word-addressable machines a simple cast to int
+   may ignore the byte-within-word field of the pointer.  */
+
+#ifndef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((P) - (char *)0)
+#endif
+
+#ifndef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((P) + (char *)0)
+#endif
+
+struct _obstack_chunk          /* Lives at front of each chunk. */
+{
+  char  *limit;                        /* 1 past end of this chunk */
+  struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+  char contents[4];            /* objects begin here */
+};
+
+struct obstack         /* control current object in current chunk */
+{
+  long chunk_size;             /* preferred size to allocate chunks in */
+  struct _obstack_chunk* chunk;        /* address of current struct obstack_chunk */
+  char *object_base;           /* address of object we are building */
+  char *next_free;             /* where to add next char to current object */
+  char *chunk_limit;           /* address of char after current chunk */
+  int  temp;                   /* Temporary for some macros.  */
+  int   alignment_mask;                /* Mask of alignment for each object. */
+#ifdef __STDC__
+  void  *(*chunkfun) ();       /* User's fcn to allocate a chunk.  */
+#else
+  char  *(*chunkfun) ();       /* User's fcn to allocate a chunk.  */
+#endif
+  void (*freefun) ();          /* User's function to free a chunk.  */
+};
+\f
+#ifdef __STDC__
+
+/* Do the function-declarations after the structs
+   but before defining the macros.  */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, void *data, int size);
+void obstack_grow0 (struct obstack *obstack, void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+   so we do not declare them.  */
+\f
+/* Pointer to beginning of object being allocated or to be allocated next.
+   Note that this might not be the final address of the object
+   because a new chunk might be needed to hold the final size.  */
+
+#define obstack_base(h) ((h)->object_base)
+
+/* Size for allocating ordinary chunks.  */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk.  */
+
+#define obstack_next_free(h)   ((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object.  */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+#define obstack_init(h) \
+  _obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+  _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+\f
+#if defined (__GNUC__) && defined (__STDC__)
+
+/* For GNU C, if not -traditional,
+   we can define these macros to compute all args only once
+   without using a global variable.
+   Also, we can avoid using the `temp' slot, to make faster code.  */
+
+#define obstack_object_size(OBSTACK)                                   \
+  ({ struct obstack *__o = (OBSTACK);                                  \
+     (unsigned) (__o->next_free - __o->object_base); })
+
+#define obstack_room(OBSTACK)                                          \
+  ({ struct obstack *__o = (OBSTACK);                                  \
+     (unsigned) (__o->chunk_limit - __o->next_free); })
+
+#define obstack_grow(OBSTACK,where,length)                             \
+({ struct obstack *__o = (OBSTACK);                                    \
+   int __len = (length);                                               \
+   ((__o->next_free + __len > __o->chunk_limit)                                \
+    ? _obstack_newchunk (__o, __len) : 0);                             \
+   bcopy (where, __o->next_free, __len);                               \
+   __o->next_free += __len;                                            \
+   (void) 0; })
+
+#define obstack_grow0(OBSTACK,where,length)                            \
+({ struct obstack *__o = (OBSTACK);                                    \
+   int __len = (length);                                               \
+   ((__o->next_free + __len + 1 > __o->chunk_limit)                    \
+    ? _obstack_newchunk (__o, __len + 1) : 0),                         \
+   bcopy (where, __o->next_free, __len),                               \
+   __o->next_free += __len,                                            \
+   *(__o->next_free)++ = 0;                                            \
+   (void) 0; })
+
+#define obstack_1grow(OBSTACK,datum)                                   \
+({ struct obstack *__o = (OBSTACK);                                    \
+   ((__o->next_free + 1 > __o->chunk_limit)                            \
+    ? _obstack_newchunk (__o, 1) : 0),                                 \
+   *(__o->next_free)++ = (datum);                                      \
+   (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers or ints,
+   and that the data added so far to the current object
+   shares that much alignment.  */
+   
+#define obstack_ptr_grow(OBSTACK,datum)                                        \
+({ struct obstack *__o = (OBSTACK);                                    \
+   ((__o->next_free + sizeof (void *) > __o->chunk_limit)              \
+    ? _obstack_newchunk (__o, sizeof (void *)) : 0),                   \
+   *((void **)__o->next_free)++ = ((void *)datum);                     \
+   (void) 0; })
+
+#define obstack_int_grow(OBSTACK,datum)                                        \
+({ struct obstack *__o = (OBSTACK);                                    \
+   ((__o->next_free + sizeof (int) > __o->chunk_limit)                 \
+    ? _obstack_newchunk (__o, sizeof (int)) : 0),                      \
+   *((int *)__o->next_free)++ = ((int)datum);                          \
+   (void) 0; })
+
+#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr)
+#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(OBSTACK,length)                                  \
+({ struct obstack *__o = (OBSTACK);                                    \
+   int __len = (length);                                               \
+   ((__o->chunk_limit - __o->next_free < __len)                                \
+    ? _obstack_newchunk (__o, __len) : 0);                             \
+   __o->next_free += __len;                                            \
+   (void) 0; })
+
+#define obstack_alloc(OBSTACK,length)                                  \
+({ struct obstack *__h = (OBSTACK);                                    \
+   obstack_blank (__h, (length));                                      \
+   obstack_finish (__h); })
+
+#define obstack_copy(OBSTACK,where,length)                             \
+({ struct obstack *__h = (OBSTACK);                                    \
+   obstack_grow (__h, (where), (length));                              \
+   obstack_finish (__h); })
+
+#define obstack_copy0(OBSTACK,where,length)                            \
+({ struct obstack *__h = (OBSTACK);                                    \
+   obstack_grow0 (__h, (where), (length));                             \
+   obstack_finish (__h); })
+
+#define obstack_finish(OBSTACK)                                        \
+({ struct obstack *__o = (OBSTACK);                                    \
+   void *value = (void *) __o->object_base;                            \
+   __o->next_free                                                      \
+     = __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
+                    & ~ (__o->alignment_mask));                        \
+   ((__o->next_free - (char *)__o->chunk                               \
+     > __o->chunk_limit - (char *)__o->chunk)                          \
+    ? (__o->next_free = __o->chunk_limit) : 0);                                \
+   __o->object_base = __o->next_free;                                  \
+   value; })
+
+#define obstack_free(OBSTACK, OBJ)                                     \
+({ struct obstack *__o = (OBSTACK);                                    \
+   void *__obj = (OBJ);                                                        \
+   if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit)  \
+     __o->next_free = __o->object_base = __obj;                                \
+   else (obstack_free) (__o, __obj); })
+\f
+#else /* not __GNUC__ or not __STDC__ */
+
+#define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+#define obstack_room(h)                \
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+#define obstack_grow(h,where,length)                                   \
+( (h)->temp = (length),                                                        \
+  (((h)->next_free + (h)->temp > (h)->chunk_limit)                     \
+   ? _obstack_newchunk ((h), (h)->temp) : 0),                          \
+  bcopy (where, (h)->next_free, (h)->temp),                            \
+  (h)->next_free += (h)->temp)
+
+#define obstack_grow0(h,where,length)                                  \
+( (h)->temp = (length),                                                        \
+  (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit)                 \
+   ? _obstack_newchunk ((h), (h)->temp + 1) : 0),                      \
+  bcopy (where, (h)->next_free, (h)->temp),                            \
+  (h)->next_free += (h)->temp,                                         \
+  *((h)->next_free)++ = 0)
+
+#define obstack_1grow(h,datum)                                         \
+( (((h)->next_free + 1 > (h)->chunk_limit)                             \
+   ? _obstack_newchunk ((h), 1) : 0),                                  \
+  *((h)->next_free)++ = (datum))
+
+#define obstack_ptr_grow(h,datum)                                      \
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit)               \
+   ? _obstack_newchunk ((h), sizeof (char *)) : 0),                    \
+  *((char **)(h)->next_free)++ = ((char *)datum))
+
+#define obstack_int_grow(h,datum)                                      \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit)                  \
+   ? _obstack_newchunk ((h), sizeof (int)) : 0),                       \
+  *((int *)(h)->next_free)++ = ((int)datum))
+
+#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr)
+#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(h,length)                                                \
+( (h)->temp = (length),                                                        \
+  (((h)->chunk_limit - (h)->next_free < (h)->temp)                     \
+   ? _obstack_newchunk ((h), (h)->temp) : 0),                          \
+  (h)->next_free += (h)->temp)
+
+#define obstack_alloc(h,length)                                                \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+#define obstack_copy(h,where,length)                                   \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_copy0(h,where,length)                                  \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_finish(h)                                              \
+( (h)->temp = __PTR_TO_INT ((h)->object_base),                         \
+  (h)->next_free                                                       \
+    = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask)        \
+                   & ~ ((h)->alignment_mask)),                         \
+  (((h)->next_free - (char *)(h)->chunk                                        \
+    > (h)->chunk_limit - (char *)(h)->chunk)                           \
+   ? ((h)->next_free = (h)->chunk_limit) : 0),                         \
+  (h)->object_base = (h)->next_free,                                   \
+  __INT_TO_PTR ((h)->temp))
+
+#ifdef __STDC__
+#define obstack_free(h,obj)                                            \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk,                     \
+  (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+   ? (int) ((h)->next_free = (h)->object_base                          \
+           = (h)->temp + (char *) (h)->chunk)                          \
+   : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
+#else
+#define obstack_free(h,obj)                                            \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk,                     \
+  (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+   ? (int) ((h)->next_free = (h)->object_base                          \
+           = (h)->temp + (char *) (h)->chunk)                          \
+   : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
+#endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+/* Declare the external functions we use; they are in obstack.c.  */
+
+#ifdef __STDC__
+  extern int _obstack_newchunk (struct obstack *h, int length);
+  extern int _obstack_free (struct obstack *h, void *obj);
+  extern void _obstack_begin (struct obstack *h, int size, int alignment,
+                             void *(*chunkfun) (), void (*freefun) ());
+#else
+  extern int _obstack_newchunk ();
+  extern int _obstack_free ();
+  extern void _obstack_begin ();
+#endif
+
+#endif /* not __OBSTACKS__ */
+
diff --git a/bfd/opncls.c b/bfd/opncls.c
new file mode 100644 (file)
index 0000000..63e9c51
--- /dev/null
@@ -0,0 +1,281 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/*** opncls.c -- open and close a bfd. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+extern void bfd_cache_init();
+FILE *bfd_open_file();
+
+/* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
+   if we do that we can't use fcntl.  */
+\f
+/** Locking 
+
+   Locking is loosely controlled by the preprocessor variable
+   BFD_LOCKS.  I say loosely because Unix barely understands locking
+   -- at least in BSD it doesn't affect programs which don't
+   explicitly use it!  That is to say it's practically useless, though
+   if everyone uses this library you'll be OK.
+
+   From among the many and varied lock facilities available, (none of
+   which, of course, knows about any other) we use the fcntl locks,
+   because they're Posix.
+
+   The reason that bfd_openr and bfd_fdopenr exist, yet only bfd_openw
+   exists is because of locking.  When we do output, we lock the
+   filename file for output, then open a temporary file which does not
+   actually get its correct filename until closing time.  This is
+   safest, but requires the asymmetry in read and write entry points.
+
+   Perhaps, since unix has so many different kinds of locking anyway,
+   we should use the emacs lock scheme?... */
+\f
+
+bfd *new_bfd()
+{
+  bfd *nbfd = (bfd *)zalloc(sizeof(bfd));
+
+  nbfd->direction = no_direction;
+  nbfd->iostream = NULL;
+  nbfd->where = 0;
+  nbfd->sections = (asection *)NULL;
+  nbfd->format = bfd_unknown;
+  nbfd->my_archive = (bfd *)NULL;
+  nbfd->origin = 0;                               
+  nbfd->opened_once = false;
+  nbfd->output_has_begun = false;
+  nbfd->section_count = 0;
+  nbfd->usrdata = (void *)NULL;
+  nbfd->sections = (asection *)NULL;
+  nbfd->cacheable = false;
+  nbfd->flags = NO_FLAGS;
+  return nbfd;
+}
+bfd *new_bfd_contained_in(obfd)
+bfd *obfd;
+{
+       bfd *nbfd = new_bfd(obfd);
+       nbfd->xvec = obfd->xvec;
+       nbfd->my_archive = obfd;
+       nbfd->direction = read_direction;
+       return nbfd;
+}
+
+/** bfd_openr, bfd_fdopenr -- open for reading.
+  Returns a pointer to a freshly-allocated bfd on success, or NULL. */
+
+bfd *
+bfd_openr (filename, target)
+     char *filename;
+     char *target;
+{
+  bfd *nbfd;
+  bfd_target *target_vec;
+
+  target_vec = bfd_find_target (target);
+  if (target_vec == NULL) {
+    bfd_error = invalid_target;
+    return NULL;
+  }
+
+  bfd_error = system_call_error;
+  nbfd = new_bfd();
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  nbfd->filename = filename;
+  nbfd->xvec = target_vec;
+  nbfd->direction = read_direction; 
+
+  if (bfd_open_file (nbfd) == NULL) {
+    bfd_error = system_call_error;     /* File didn't exist, or some such */
+    free (nbfd);
+    return NULL;
+  }
+  return nbfd;
+}
+
+
+/* Don't try to `optimize' this function:
+
+   o - We lock using stack space so that interrupting the locking
+       won't cause a storage leak.
+   o - We open the file stream last, since we don't want to have to
+       close it if anything goes wrong.  Closing the stream means closing
+       the file descriptor too, even though we didn't open it.
+ */
+
+bfd *
+bfd_fdopenr (filename, target, fd)
+     char *filename;
+     char *target;
+     int fd;
+{
+  bfd *nbfd;
+  bfd_target *target_vec;
+  int fdflags;
+#ifdef BFD_LOCKS
+  struct flock lock, *lockp = &lock;
+#endif
+
+  target_vec = bfd_find_target (target);
+  if (target_vec == NULL) {
+    bfd_error = invalid_target;
+    return NULL;
+  }
+
+  bfd_error = system_call_error;
+  
+  fdflags = fcntl (fd, F_GETFL);
+  if (fdflags == -1) return NULL;
+
+#ifdef BFD_LOCKS
+  lockp->l_type = F_RDLCK;
+  if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
+#endif
+
+  nbfd = new_bfd();
+
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+#ifdef BFD_LOCKS
+  nbfd->lock = (struct flock *) (nbfd + 1);
+#endif
+  /* if the fd were open for read only, this still would not hurt: */
+  nbfd->iostream = (char *) fdopen (fd, "r+"); 
+  if (nbfd->iostream == NULL) {
+    free (nbfd);
+    return NULL;
+  }
+  
+  /* OK, put everything where it belongs */
+
+  nbfd->filename = filename;
+  nbfd->xvec = target_vec;
+
+  /* As a special case we allow a FD open for read/write to
+     be written through, although doing so requires that we end
+     the previous clause with a preposition.  */
+  switch (fdflags & O_ACCMODE) {
+  case O_RDONLY: nbfd->direction = read_direction; break;
+  case O_WRONLY: nbfd->direction = write_direction; break;  
+  case O_RDWR: nbfd->direction = both_direction; break;
+  default: abort ();
+  }
+                                  
+#ifdef BFD_LOCKS
+  memcpy (nbfd->lock, lockp, sizeof (struct flock))
+#endif
+
+    bfd_cache_init (nbfd);
+
+  return nbfd;
+}
+\f
+/** bfd_openw -- open for writing.
+  Returns a pointer to a freshly-allocated bfd on success, or NULL.
+
+  See comment by bfd_fdopenr before you try to modify this function. */
+
+bfd *
+bfd_openw (filename, target)
+     char *filename;
+     char *target;
+{
+  bfd *nbfd;
+  bfd_target *target_vec;
+  
+  target_vec = bfd_find_target (target);
+  if (target_vec == NULL) return NULL;
+
+  bfd_error = system_call_error;
+
+  /* nbfd has to point to head of malloc'ed block so that bfd_close may
+     reclaim it correctly. */
+
+  nbfd = new_bfd();
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  nbfd->filename = filename;
+  nbfd->xvec = target_vec;
+  nbfd->direction = write_direction;
+
+  if (bfd_open_file (nbfd) == NULL) {
+    bfd_error = system_call_error;     /* File not writeable, etc */
+    free (nbfd);
+    return NULL;
+  }
+  return nbfd;
+}
+
+
+\f
+/** Close up shop, get your deposit back. */
+boolean
+bfd_close (abfd)
+     bfd *abfd;
+{
+  if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
+
+  bfd_cache_close(abfd);
+/* If the file was open for writing and is now executable
+  make it so */
+  if (abfd->direction == write_direction 
+      && abfd->flags & EXEC_P) {
+    struct stat buf;
+    stat(abfd->filename, &buf);
+    chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
+  }
+  free (abfd);
+  return true;
+}
+/* 
+ called to create a bfd with no ascociated file or target 
+ */
+bfd *
+bfd_create(filename, template)
+char *filename;
+bfd *template;
+{
+  bfd *nbfd = new_bfd();
+  if (nbfd == (bfd *)NULL) {
+    bfd_error = no_memory;
+    return (bfd *)NULL;
+  }
+  nbfd->filename = filename;
+  nbfd->xvec = template->xvec;
+  nbfd->direction = no_direction;
+  return nbfd;
+
+
+
+}
diff --git a/bfd/srec.c b/bfd/srec.c
new file mode 100644 (file)
index 0000000..cf77496
--- /dev/null
@@ -0,0 +1,471 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+
+ bfd backend for srecord objects.
+
+ Srecords cannot hold anything but addresses and data, so that's all
+ that we impliment.
+ The only interesting thing is that srecords may come out of order and
+ there is no header, so an initial scan is required to discover the
+ minimum and maximum addresses used to create the vma and size of the
+ only section we create. We arbitarily call this section ".text".
+
+ When bfd_get_section_contents is called the file is read again, and
+ this time the data is placed into a malloced area.
+
+ Any number of sections may be created for output, we just output them
+ in the order provided to bfd_set_section_contents.
+
+
+ Steve Chamberlain steve@cygnus.com
+
+ */
+
+
+/* $Id$
+ * $Log$
+ * Revision 1.2  1991/04/03 22:10:51  steve
+ * Fixed typo
+ *
+ * Revision 1.1.1.1  1991/03/21  21:11:22  gumby
+ * Back from Intel with Steve
+ *
+ * Revision 1.1  1991/03/21  21:11:20  gumby
+ * Initial revision
+ *
+ * Revision 1.1  1991/03/13  00:22:29  chrisb
+ * Initial revision
+ *
+ * Revision 1.3  1991/03/10  19:11:40  rich
+ *  Modified Files:
+ *     bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
+ *
+ * Working bugs out of coff support.
+ *
+ * Revision 1.2  1991/03/07  02:26:18  sac
+ * Tidied up xfer table
+ *
+ * Revision 1.1  1991/03/05  16:28:12  sac
+ * Initial revision
+ *
+ */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+static char digs[] = "0123456789ABCDEF";
+
+/* Macros for converting between hex and binary */
+
+#define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
+#define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
+#define TOHEX(d,x) \
+  ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
+
+typedef struct {
+  char high;
+  char low;
+} byte_as_two_char_type;
+
+/* The maximum number of bytes on a line is FF */
+#define MAXCHUNK 0xff 
+/* The number of bytes we fit onto a line on output */
+#define CHUNK 16 
+
+/* The shape of an srecord .. */
+typedef struct 
+{
+  char S;
+  char type;
+  byte_as_two_char_type size;
+  union {
+    struct {
+      byte_as_two_char_type address[4];
+      byte_as_two_char_type data[MAXCHUNK];
+      /* If there isn't MAXCHUNK bytes of data then the checksum will 
+        appear earlier */
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_3;
+    struct {
+      byte_as_two_char_type address[4];
+      byte_as_two_char_type data[MAXCHUNK];
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_6;
+
+    struct {
+      byte_as_two_char_type address[3];
+      byte_as_two_char_type data[MAXCHUNK];
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_2;
+
+    struct {
+      byte_as_two_char_type address[2];
+      byte_as_two_char_type data[MAXCHUNK];
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_1;
+    byte_as_two_char_type data[MAXCHUNK];
+  } u;
+} srec_type;
+
+
+/* 
+   called once per input srecord, used to work out vma and size of data.
+ */
+
+static void
+size_srec(abfd, section, address, raw, length)
+bfd *abfd;
+asection *section;
+bfd_vma address;
+byte_as_two_char_type *raw;
+unsigned int length;
+{
+  if (address < section->vma)
+    section->vma = address;
+
+  if (address + length  > section->vma + section->size)
+    section->size = (address+length) -  section->vma;
+}
+
+/*
+ called once per input srecord, copies data from input into malloced area
+ */
+
+static void
+fillup(abfd, section, address, raw, length)
+bfd *abfd;
+asection *section;
+bfd_vma address;
+byte_as_two_char_type *raw;
+unsigned int length;
+{
+  unsigned int i;
+  bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) +  address - section->vma;
+  for (i = 0; i < length; i++) {
+    *dst = HEX(raw);
+    dst++;
+    raw++;
+  }
+}
+
+/*
+ pass over an srecord file calling one of the above functions on each
+ record
+ */
+static void
+pass_over(abfd, func, section)
+bfd *abfd;
+void (*func)();
+asection *section;
+{
+  unsigned int bytes_on_line;
+  boolean eof = false;
+  bfd_vma address;
+  /* To the front of the file */
+  bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+  while (eof == false)
+    {
+      srec_type buffer;
+
+      /* Find first 'S' */
+      eof =  bfd_read(&buffer.S, 1, 1, abfd) != 1;
+      while (buffer.S != 'S' && !eof) {
+       eof =  bfd_read(&buffer.S, 1, 1, abfd) != 1;
+      }
+      if (eof) break;
+
+      bfd_read(&buffer.type, 1, 3, abfd);
+
+      bytes_on_line = HEX(&buffer.size);
+    
+      bfd_read(buffer.u.data, 1 , bytes_on_line * 2, abfd);
+
+      switch (buffer.type) {
+      case '6':
+       /* Prologue - ignore */
+       break;
+      case '3':
+       address = (HEX(buffer.u.type_3.address+0) << 24)
+         + (HEX(buffer.u.type_3.address+1) << 16)
+           + (HEX(buffer.u.type_3.address+2) << 8) 
+             + (HEX(buffer.u.type_3.address+3));
+        func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
+
+       break;
+
+      case '2':
+       address = (HEX(buffer.u.type_2.address+0) << 16)+
+         (HEX(buffer.u.type_2.address+1) << 8) +
+       (HEX(buffer.u.type_2.address+2));
+        func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
+
+       break;
+      case '1':
+       address =
+         (HEX(buffer.u.type_1.address+0) << 8) 
+           + (HEX(buffer.u.type_1.address+1));
+        func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
+       break;
+
+      }
+    }
+}
+
+
+bfd_target *
+srec_object_p (abfd)
+bfd *abfd;
+{
+  char b;
+  asection *section;
+  bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+  bfd_read(&b, 1,1,abfd);
+  if (b != 'S') return (bfd_target*)NULL;
+
+  /* 
+     We create one section called data for all the contents, 
+     and allocate enough room for the entire file
+     */
+
+
+  section =  bfd_make_section(abfd, ".text");
+  section->size = 0;
+  section->vma = 0xffffffff;
+  pass_over(abfd, size_srec, section);
+
+  return abfd->xvec;
+}
+
+
+
+
+
+
+
+
+static boolean
+srec_get_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+void  *location;
+file_ptr offset;
+unsigned      int count;
+{
+  if (section->used_by_bfd == (bfd_byte *)NULL) {
+    section->used_by_bfd = (bfd_byte *)malloc(section->size);
+    pass_over(abfd, fillup, section);
+  }
+  (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
+  return true;
+}
+      
+
+
+boolean
+srec_set_arch_mach (abfd, arch, machine)
+bfd *abfd;
+enum bfd_architecture arch;
+unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  return true;
+}
+
+
+
+boolean
+srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
+bfd *abfd;
+sec_ptr section;
+unsigned char *location;
+file_ptr offset;
+int bytes_to_do;
+{
+  bfd_vma address;
+  int bytes_written;
+
+  int type;
+  unsigned int i;
+  srec_type buffer;
+  bytes_written = 0;
+  if (section->size <= 0xffff) 
+    type = 1;
+  else if (section->size <= 0xffffff) 
+    type = 2;
+  else
+    type = 3;
+
+  buffer.S = 'S';
+  buffer.type = '0' + type;
+
+  while (bytes_written < bytes_to_do) {
+    unsigned int size;
+    unsigned int check_sum;
+    byte_as_two_char_type *data; 
+ unsigned   int bytes_this_chunk = bytes_to_do - bytes_written;
+
+    if (bytes_this_chunk > CHUNK) {
+      bytes_this_chunk = CHUNK;
+    }
+
+    address = section->vma + offset + bytes_written;
+
+    switch (type) {
+    case 3:
+      check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
+      check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
+      check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
+      check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
+      size = bytes_this_chunk + 5;
+      data = buffer.u.type_3.data;
+
+    case 2:
+      check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
+      check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
+      check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
+      size = bytes_this_chunk + 4;
+      data = buffer.u.type_2.data;
+      break;
+
+    case 1:
+      check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
+      check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
+      size = bytes_this_chunk + 3;
+      data = buffer.u.type_1.data;
+    }
+
+    for (i = 0; i < bytes_this_chunk; i++) {
+      check_sum += TOHEX(data, (location[i]));
+      data++;
+    }
+
+    check_sum += TOHEX(&(buffer.size), size );
+    (void) TOHEX(data, ~check_sum);
+    data++;
+
+    * ( (char *)(data)) = '\n';
+    bfd_write(&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
+
+    bytes_written += bytes_this_chunk;
+    location += bytes_this_chunk;
+  }
+
+
+  return true;
+}
+
+
+boolean
+srec_close_and_cleanup (abfd)
+bfd *abfd;
+{
+  asection *s;
+  if (bfd_read_p (abfd) == false) {
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) {
+       return false;
+      }
+      break;
+    case bfd_object:
+      bfd_write("S9030000FC\n", 1,11,abfd);
+      break;
+    default:
+      bfd_error = invalid_operation;
+      return false;
+    }
+  }
+  for (s = abfd->sections; s != (asection *)NULL;s = s->next) {
+    if (s->used_by_bfd != (void *)NULL) {
+      free(s->used_by_bfd);
+    }
+  }
+  return true;
+}
+
+/*SUPPRESS 460 */
+bfd_target srec_vec =
+{
+  "srec",                      /* name */
+  bfd_target_srec_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_CODE|SEC_DATA|SEC_ROM
+   |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  srec_close_and_cleanup,      /* _close_and_cleanup */
+  srec_set_section_contents,    /* bfd_set_section_contents */
+  srec_get_section_contents,
+  bfd_true,                    /*   new_section_hook */
+  0,                           /* _core_file_failing_command */
+  0,                           /* _core_file_failing_signal */
+  0,                           /* _core_file_matches_ex...p */
+
+  bfd_false,                   /* bfd_slurp_armap */
+  bfd_false,                   /* bfd_slurp_extended_name_table */
+  bfd_void,                    /* bfd_truncate_arname */
+  bfd_0u,                      /* get_symtab_upper_bound */
+  bfd_0u,                      /* canonicalize_symtab */
+  bfd_void,                    /* bfd_reclaim_symbol_table */
+  bfd_0u,                      /* get_reloc_upper_bound */
+  bfd_0u,                      /* bfd_canonicalize_reloc */
+  bfd_void,                    /* bfd_reclaim_reloc */
+  bfd_0,                       /* bfd_get_symcount_upper_bound */
+  (symindex (*)())bfd_0,       /* bfd_get_first_symbol */
+  (symindex (*)())bfd_0,       /* bfd_get_next_symbol */
+  bfd_false,                   /* bfd_classify_symbol */
+  bfd_false,                   /* bfd_symbol_hasclass */
+  (char* (*)())bfd_0,          /* bfd_symbol_name */
+  bfd_0,                       /* bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target,
+     srec_object_p,            /* bfd_check_format */
+     (struct bfd_target *(*)()) bfd_nullvoidptr,
+     (struct bfd_target *(*)())     bfd_nullvoidptr,
+   },
+  {
+    bfd_false,
+    bfd_true,                  /* mkobject */
+    _bfd_generic_mkarchive,
+    bfd_false,
+  },
+  (asymbol * (*)())  bfd_nullvoidptr, /* bfd_make_empty_symbol */
+  bfd_void,                    /* bfd_prit_symbol */
+  (alent *(*)())bfd_nullvoidptr, /* srec_get_lineno,*/
+  srec_set_arch_mach,          /* bfd_set_arch_mach,*/
+  bfd_false,                   /* write_armap*/
+  (bfd *(*)())bfd_nullvoidptr, /* openr_next_archived_file */
+  bfd_false,                   /* bfd_find_nearest_line */
+};
diff --git a/bfd/sunos.c b/bfd/sunos.c
new file mode 100644 (file)
index 0000000..9b554b6
--- /dev/null
@@ -0,0 +1,2119 @@
+/*** bfd backend for sunos binaries */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$
+ *
+ */
+
+#define TARGET_BYTE_ORDER_BIG_P 1
+
+#include <ansidecl.h>
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+void (*bfd_error_trap)();
+/*SUPPRESS558*/
+/*SUPPRESS529*/
+
+
+
+
+typedef void generic_symbol_type;
+/* These values are correct for the SPARC.  I dunno about anything else */
+#define PAGE_SIZE 0x02000
+#define SEGMENT_SIZE PAGE_SIZE
+#define TEXT_START_ADDR PAGE_SIZE
+#include "a.out.gnu.h"
+#include "stab.gnu.h"
+#include "ar.h"
+#include "liba.out.h"           /* BFD a.out internal data structures */
+
+#include "a.out.sun4.h"
+
+#define CTOR_TABLE_RELOC_IDX 2
+static CONST reloc_howto_type howto_table_ext[] = 
+{
+  /* type                   rs   size bsz  pcrel bitpos  abs ovrf sf name partial inplace mask*/
+{ (unsigned int) RELOC_8,      0,  0,          8,  false, 0, true,  true,0,"8",        false, 0x000000ff},
+{ (unsigned int) RELOC_16,     0,  1,  16, false, 0, true,  true,0,"16",       false, 0x0000ffff},
+{ (unsigned int) RELOC_32,     0,  2,  32, false, 0, true,  true,0,"32",       false,  0xffffffff},
+{ (unsigned int) RELOC_DISP8,  0,  0,  8,  true,  0, false, true,0,"DISP8",    false, 0x000000ff},
+{ (unsigned int) RELOC_DISP16, 0,  1,  16, true,  0, false, true,0,"DISP16",   false, 0x0000ffff},
+{ (unsigned int) RELOC_DISP32, 0,  2,  32, true,  0, false, true,0,"DISP32",   false, 0xffffffff},
+{ (unsigned int) RELOC_WDISP30,2,  2,  30, true,  0, false, true,0,"WDISP30",  false, 0x3fffffff},
+{ (unsigned int) RELOC_WDISP22,2,  2,  22, true,  0, false, true,0,"WDISP22",  false, 0x003fffff},
+{ (unsigned int) RELOC_HI22,   10, 2,  22, false, 0, false, true,0,"HI22",     false, 0x003fffff},
+{ (unsigned int) RELOC_22,      0, 2,  22, false, 0, false, true,0,"22",       false, 0x003fffff},
+{ (unsigned int) RELOC_13,     0, 2,   13, false, 0, false, true,0,"13",       false, 0x00001fff},
+{ (unsigned int) RELOC_LO10,   0, 2,   10, false, 0, false, true,0,"LO10",     false, 0x000003ff},
+{ (unsigned int) RELOC_SFA_BASE,0, 2,  32, false, 0, false, true,0,"SFA_BASE", false, 0xffffffff},
+{ (unsigned int) RELOC_SFA_OFF13,0,2,  32, false, 0, false, true,0,"SFA_OFF13",false, 0xffffffff},
+{ (unsigned int) RELOC_BASE10, 0,  2,  16, false, 0, false, true,0,"BASE10",   false, 0x0000ffff},
+{ (unsigned int) RELOC_BASE13, 0,  2,  13, false, 0, false, true,0,"BASE13",   false, 0x00001fff},
+{ (unsigned int) RELOC_BASE22, 0,  2,  0,  false, 0, false, true,0,"BASE22",   false, 0x00000000},
+{ (unsigned int) RELOC_PC10,   0,  2,  10, false, 0, false, true,0,"PC10",     false, 0x000003ff},
+{ (unsigned int) RELOC_PC22,   0,  2,  22, false, 0, false, true,0,"PC22",     false, 0x003fffff},
+{ (unsigned int) RELOC_JMP_TBL,0,  2,  32, false, 0, false, true,0,"JMP_TBL",  false, 0xffffffff},
+{ (unsigned int) RELOC_SEGOFF16,0, 2,  0,  false, 0, false, true,0,"SEGOFF16", false, 0x00000000},
+{ (unsigned int) RELOC_GLOB_DAT,0, 2,  0,  false, 0, false, true,0,"GLOB_DAT", false, 0x00000000},
+{ (unsigned int) RELOC_JMP_SLOT,0, 2,  0,  false, 0, false, true,0,"JMP_SLOT", false, 0x00000000},
+{ (unsigned int) RELOC_RELATIVE,0, 2,  0,  false, 0, false, true,0,"RELATIVE", false, 0x00000000},
+{ (unsigned int) RELOC_JUMPTARG,2, 13, 16, true,  0, false, true,0,"JUMPTARG", false, 0x0000ffff},
+{ (unsigned int) RELOC_CONST,  0, 13,  16, false, 0, false, true,0,"CONST",    false, 0x0000ffff},
+{ (unsigned int) RELOC_CONSTH, 16, 13, 16, false, 0, false, true,0,"CONSTH",   false, 0x0000ffff},
+};
+
+/* Convert standard reloc records to "arelent" format (incl byte swap).  */
+
+static CONST reloc_howto_type howto_table_std[] = {
+  /* type                   rs   size bsz  pcrel bitpos  abs ovrf sf name*/
+{ (unsigned int) 0,           0,  0,   8,  false, 0, true,  true,0,"8",        true, 0x000000ff},
+{ (unsigned int) 1,           0,  1,   16, false, 0, true,  true,0,"16",       true, 0x0000ffff},
+{ (unsigned int) 2,           0,  2,   32, false, 0, true,  true,0,"32",       true, 0xffffffff},
+{ (unsigned int) 3,           0,  3,   64, false, 0, true,  true,0,"64",       true, 0xdeaddead},
+{ (unsigned int) 4,           0,  0,   8,  true,  0, false, true,0,"DISP8",    true, 0x000000ff},
+{ (unsigned int) 5,           0,  1,   16, true,  0, false, true,0,"DISP16",   true, 0x0000ffff},
+{ (unsigned int) 6,           0,  2,   32, true,  0, false, true,0,"DISP32",   true, 0xffffffff},
+{ (unsigned int) 7,           0,  3,   64, true,  0, false, true,0,"DISP64",   true, 0xfeedface},
+};
+
+/** a.out files */
+
+
+PROTO (void , sunos4_write_syms, ());
+PROTO (static boolean,sunos4_squirt_out_relocs,(bfd *abfd, asection *section));
+
+
+static size_t
+reloc_size_func(abfd)
+bfd *abfd;
+{
+  switch (bfd_get_architecture (abfd)) {
+  case bfd_arch_sparc:
+  case bfd_arch_a29k:
+    return  RELOC_EXT_SIZE;
+  default:
+    return  RELOC_STD_SIZE;
+  }
+}
+
+void
+bfd_aout_swap_exec_header_in (abfd, raw_bytes, execp)
+     bfd *abfd;
+     unsigned char *raw_bytes;
+     struct exec *execp;
+{
+  struct exec_bytes *bytes = (struct exec_bytes *)raw_bytes;
+
+  /* Now fill in fields in the execp, from the bytes in the raw data.  */
+  execp->a_info   = bfd_h_getlong (abfd, bytes->a_info);
+  execp->a_text   = bfd_h_getlong (abfd, bytes->a_text);
+  execp->a_data   = bfd_h_getlong (abfd, bytes->a_data);
+  execp->a_bss    = bfd_h_getlong (abfd, bytes->a_bss);
+  execp->a_syms   = bfd_h_getlong (abfd, bytes->a_syms);
+  execp->a_entry  = bfd_h_getlong (abfd, bytes->a_entry);
+  execp->a_trsize = bfd_h_getlong (abfd, bytes->a_trsize);
+  execp->a_drsize = bfd_h_getlong (abfd, bytes->a_drsize);
+}
+
+void
+bfd_aout_swap_exec_header_out (abfd, execp, raw_bytes)
+     bfd *abfd;
+     struct exec *execp;
+     unsigned char *raw_bytes;
+{
+  struct exec_bytes *bytes = (struct exec_bytes *)raw_bytes;
+
+  /* Now fill in fields in the raw data, from the fields in the exec struct. */
+  bfd_h_putlong (abfd, execp->a_info  , bytes->a_info);
+  bfd_h_putlong (abfd, execp->a_text  , bytes->a_text);
+  bfd_h_putlong (abfd, execp->a_data  , bytes->a_data);
+  bfd_h_putlong (abfd, execp->a_bss   , bytes->a_bss);
+  bfd_h_putlong (abfd, execp->a_syms  , bytes->a_syms);
+  bfd_h_putlong (abfd, execp->a_entry , bytes->a_entry);
+  bfd_h_putlong (abfd, execp->a_trsize, bytes->a_trsize);
+  bfd_h_putlong (abfd, execp->a_drsize, bytes->a_drsize);
+}
+
+/* Steve wants some way to frob this stuff from Saber while he's debugging
+   ld, so we have these funny shadow functions */
+/* ZMAGIC's start at 0 (making the exec part of the text section),
+  other formats start after the exec
+*/
+static unsigned int n_txtoff(ptr)
+struct exec *ptr;
+{return N_MAGIC(*ptr)== ZMAGIC ? 0: sizeof(struct exec);}
+
+static unsigned int n_datoff(ptr)
+struct exec *ptr;
+{return n_txtoff(ptr) + ptr->a_text;}
+
+static unsigned int n_treloff(ptr)
+struct exec *ptr;
+{return n_datoff(ptr) + ptr->a_data;}
+
+static unsigned int n_dreloff(ptr)
+struct exec *ptr;
+{return n_treloff(ptr) + ptr->a_trsize;}
+
+static unsigned int n_symoff(ptr)
+struct exec *ptr;
+{return n_dreloff(ptr) + ptr->a_drsize;}
+
+static unsigned int n_stroff(ptr)
+struct exec *ptr;
+{return n_symoff(ptr) + ptr->a_syms;}
+
+unsigned int n_badmag(ptr)
+     struct exec *ptr;
+{
+  switch (N_MAGIC(*ptr)) {
+  case OMAGIC: case NMAGIC: case ZMAGIC: return 0;
+  default: return 1;
+  }
+}
+
+bfd_target *
+sunos4_object_p (abfd)
+     bfd *abfd;
+{
+  unsigned char magicbuf[4];   /* Raw bytes of magic number from file */
+  unsigned long magic;         /* Swapped magic number */
+  unsigned char exec_bytes[EXEC_BYTES_SIZE];   /* Raw bytes of exec hdr */
+  struct exec *execp;
+  void *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)magicbuf, 1, sizeof (magicbuf), abfd) !=
+      sizeof (magicbuf))
+    return 0;
+  magic = bfd_h_getlong (abfd, magicbuf);
+
+  /* Baroque syntax to mask deficiencies of the Sun compiler */
+  /* if (N_BADMAG (*((struct exec *) &magic))) return 0; */
+  if (n_badmag ((struct exec *) &magic)) return 0;
+
+  if (bfd_seek (abfd, 0L, false) < 0) return 0;
+
+  if (bfd_read ((void *) exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+      != EXEC_BYTES_SIZE) {
+    bfd_error = wrong_format;
+    return 0;
+  }
+
+  /* Use an intermediate variable for clarity */
+  rawptr = (void *) zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  set_tdata (abfd, ((struct sunexdata *) rawptr));
+  exec_hdr (abfd) = execp =
+    (struct exec *) ((char *)rawptr + sizeof (struct sunexdata));
+
+  bfd_aout_swap_exec_header_in (abfd, exec_bytes, execp);
+
+  /* Set the file flags */
+  abfd->flags = NO_FLAGS;
+  if (execp->a_drsize || execp->a_trsize)
+    abfd->flags |= HAS_RELOC;
+  if (execp->a_entry) 
+    abfd->flags |= EXEC_P;
+  if (execp->a_syms) 
+    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+
+  if (N_MAGIC (*execp) == ZMAGIC) abfd->flags |= D_PAGED;
+  if (N_MAGIC (*execp) == NMAGIC) abfd->flags |= WP_TEXT;
+
+  /* Determine the architecture and machine type of the object file.  */
+  abfd->obj_arch = bfd_arch_unknown;   /* Default values */
+  abfd->obj_machine = 0;
+  switch (N_MACHTYPE (*execp)) {
+
+  case M_UNKNOWN:
+       break;
+
+  case M_68010:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68010;
+       break;
+
+  case M_68020:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68020;
+       break;
+
+  case M_SPARC:
+       abfd->obj_arch = bfd_arch_sparc;
+       break;
+
+  case M_386:
+       abfd->obj_arch = bfd_arch_i386;
+       break;
+
+  case M_29K:
+       abfd->obj_arch = bfd_arch_a29k;
+       break;
+
+  default:
+       abfd->obj_arch = bfd_arch_obscure;
+       break;
+  }
+
+  bfd_get_start_address (abfd) = execp->a_entry;
+
+  /* Remember the positions of the string table and symbol table.  */
+  obj_str_filepos (abfd) = n_stroff (execp);
+  obj_sym_filepos (abfd) = n_symoff (execp);
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  obj_aout_symbols(abfd) = (aout_symbol_type *)NULL;
+  (void)bfd_make_section(abfd, ".text");
+  (void)bfd_make_section(abfd, ".data");
+  (void)bfd_make_section(abfd, ".bss");
+
+  obj_datasec (abfd)->size = execp->a_data;
+  obj_bsssec (abfd)->size = execp->a_bss;
+  obj_textsec (abfd)->size = execp->a_text;
+  obj_datasec (abfd)->vma = N_DATADDR(*execp);
+  obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
+  obj_textsec (abfd)->vma = N_TXTADDR(*execp);
+
+  obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
+  obj_datasec (abfd)->filepos = N_DATOFF(*execp);
+
+  obj_textsec (abfd)->rel_filepos = N_TROFF(*execp);
+  obj_datasec (abfd)->rel_filepos = N_DROFF(*execp);
+
+  obj_textsec (abfd)->flags = (execp->a_trsize != 0 ?
+                               (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
+                               (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
+  obj_datasec (abfd)->flags = (execp->a_drsize != 0 ?
+                               (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
+                               (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
+  obj_bsssec (abfd)->flags = SEC_ALLOC;
+
+  abfd->sections = obj_textsec (abfd);
+  obj_textsec (abfd)->next = obj_datasec (abfd);
+  obj_datasec (abfd)->next = obj_bsssec (abfd);
+  return abfd->xvec;
+}
+
+
+boolean
+sunos4_mkobject (abfd)
+     bfd *abfd;
+{
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  /* Use an intermediate variable for clarity */
+  rawptr =  zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  abfd->tdata = (void *)((struct sunexdata *) rawptr);
+  exec_hdr (abfd) = (struct exec *) (rawptr + sizeof (struct sunexdata));
+
+  /* For simplicity's sake we just make all the sections right here. */
+
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  bfd_make_section (abfd, ".text");
+  bfd_make_section (abfd, ".data");
+  bfd_make_section (abfd, ".bss");
+
+  return true;
+}
+
+/* Keep track of machine architecture and machine type for a.out's.
+   Return the machine_type for a particular arch&machine, or M_UNKNOWN
+   if that exact arch&machine can't be represented in a.out format.
+
+   If the architecture is understood, machine type 0 (default) should
+   always be understood.  */
+
+static enum machine_type
+aout_machine_type (arch, machine)
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  enum machine_type arch_flags;
+
+  arch_flags = M_UNKNOWN;
+
+  switch (arch) {
+  case bfd_arch_sparc:
+       if (machine == 0)       arch_flags = M_SPARC;
+       break;
+
+  case bfd_arch_m68k:
+       switch (machine) {
+       case 0:                 arch_flags = M_UNKNOWN; break;
+       case 68000:             arch_flags = M_UNKNOWN; break;
+       case 68010:             arch_flags = M_68010; break;
+       case 68020:             arch_flags = M_68020; break;
+       default:                arch_flags = M_UNKNOWN; break;
+       }
+       break;
+
+  case bfd_arch_i386:
+       if (machine == 0)       arch_flags = M_386;
+       break;
+
+  case bfd_arch_a29k:
+       if (machine == 0)       arch_flags = M_29K;
+       break;
+
+  default:
+       arch_flags = M_UNKNOWN;
+       break;
+  }
+  return arch_flags;
+}
+
+boolean
+sunos4_set_arch_mach (abfd, arch, machine)
+     bfd *abfd;
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  if (arch != bfd_arch_unknown &&
+      aout_machine_type (arch, machine) == M_UNKNOWN)
+    return false;              /* We can't represent this type */
+  return true;                 /* We're easy ... */
+}
+
+boolean
+sunos4_write_object_contents (abfd)
+     bfd *abfd;
+{
+  unsigned int data_pad = 0;
+  unsigned char exec_bytes[EXEC_BYTES_SIZE];
+  struct exec *execp = exec_hdr (abfd);
+
+  execp->a_text = obj_textsec (abfd)->size;
+
+  /* Magic number, maestro, please!  */
+  switch (bfd_get_architecture(abfd)) {
+  case bfd_arch_m68k:
+    switch (bfd_get_machine(abfd)) {
+    case 68010:
+      N_SET_MACHTYPE(*execp, M_68010);
+      break;
+    default:
+    case 68020:
+      N_SET_MACHTYPE(*execp, M_68020);
+      break;
+    }
+    break;
+  case bfd_arch_sparc:
+    N_SET_MACHTYPE(*execp, M_SPARC);
+    break;
+  case bfd_arch_i386:
+    N_SET_MACHTYPE(*execp, M_386);
+    break;
+  case bfd_arch_a29k:
+    N_SET_MACHTYPE(*execp, M_29K);
+    break;
+  default:
+    N_SET_MACHTYPE(*execp, M_UNKNOWN);
+  }
+
+  N_SET_MAGIC (*execp, OMAGIC);
+  if (abfd->flags & D_PAGED) {
+    execp->a_text = obj_textsec (abfd)->size + sizeof(struct exec);
+    N_SET_MAGIC (*execp, ZMAGIC);
+  } else if (abfd->flags & WP_TEXT) {
+    N_SET_MAGIC (*execp, NMAGIC);
+  }
+  N_SET_FLAGS (*execp, 0x1);   /* copied from ld.c; who the hell knows? */
+
+  if (abfd->flags & D_PAGED) 
+    {
+      data_pad = ((obj_datasec(abfd)->size + PAGE_SIZE -1)
+                 & (- PAGE_SIZE)) - obj_datasec(abfd)->size;
+
+      if (data_pad > obj_bsssec(abfd)->size)
+       execp->a_bss = 0;
+      else 
+       execp->a_bss = obj_bsssec(abfd)->size - data_pad;
+      execp->a_data = obj_datasec(abfd)->size + data_pad;
+
+    }
+  else {
+    execp->a_data = obj_datasec (abfd)->size;
+    execp->a_bss = obj_bsssec (abfd)->size;
+  }
+
+  execp->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
+  execp->a_entry = bfd_get_start_address (abfd);
+
+  execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
+                    reloc_size_func(abfd));
+                      
+  execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
+                    reloc_size_func(abfd));
+
+  bfd_aout_swap_exec_header_out (abfd, execp, exec_bytes);
+
+  bfd_seek (abfd, 0L, false);
+  bfd_write ((void *) exec_bytes, 1, EXEC_BYTES_SIZE, abfd);
+
+  /* Now write out reloc info, followed by syms and strings */
+
+  if (bfd_get_symcount (abfd) != 0) 
+    {
+      bfd_seek (abfd,
+               (long)(N_SYMOFF(*execp)), false);
+
+      sunos4_write_syms (abfd);
+
+      bfd_seek (abfd,  (long)(N_TROFF(*execp)), false);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
+      bfd_seek (abfd, (long)(N_DROFF(*execp)), false);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
+    }
+  return true;
+}
+
+/** core files */
+/** core files */
+
+#define CORE_MAGIC 0x080456
+#define CORE_NAMELEN 16
+
+/* The core structure is taken from the Sun documentation.
+   Unfortunately, they don't document the FPA structure, or at least I
+   can't find it easily.  Fortunately the core header contains its own
+   length.  So this shouldn't cause problems, except for c_ucode, which
+   so far we don't use but is easy to find with a little arithmetic. */
+
+/* But the reg structure can be gotten from the SPARC processor handbook.
+   This really should be in a GNU include file though so that gdb can use
+   the same info. */
+struct regs {
+  int r_psr;
+  int r_pc;
+  int r_npc;
+  int r_y;
+  int r_g1;
+  int r_g2;
+  int r_g3;
+  int r_g4;
+  int r_g5;
+  int r_g6;
+  int r_g7;
+  int r_o0;
+  int r_o1;
+  int r_o2;
+  int r_o3;
+  int r_o4;
+  int r_o5;
+  int r_o6;
+  int r_o7;
+};
+
+/* Taken from Sun documentation: */
+
+/* FIXME:  It's worse than we expect.  This struct contains TWO substructs
+   neither of whose size we know, WITH STUFF IN BETWEEN THEM!  We can't
+   even portably access the stuff in between!  */
+
+struct core {
+  int c_magic;                 /* Corefile magic number */
+  int c_len;                   /* Sizeof (struct core) */
+  struct regs c_regs;          /* General purpose registers */
+  struct exec c_aouthdr;       /* A.out header */
+  int c_signo;                 /* Killing signal, if any */
+  int c_tsize;                 /* Text size (bytes) */
+  int c_dsize;                 /* Data size (bytes) */
+  int c_ssize;                 /* Stack size (bytes) */
+  char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+  double fp_stuff[1];          /* external FPU state (size unknown by us) */
+               /* The type "double" is critical here, for alignment.
+                  SunOS declares a struct here, but the struct's alignment
+                  is double since it contains doubles.  */
+  int c_ucode;                 /* Exception no. from u_code */
+               /* (this member is not accessible by name since we don't
+                   portably know the size of fp_stuff.) */
+};
+
+/* Supposedly the user stack grows downward from the bottom of kernel memory.
+   Presuming that this remains true, this definition will work. */
+#define USRSTACK (-(128*1024*1024))
+
+PROTO (static void, swapcore, (bfd *abfd, struct core *core));
+
+/* need this cast b/c ptr is really void * */
+#define core_hdr(bfd) (((struct suncordata *) (bfd->tdata))->hdr)
+#define core_datasec(bfd) (((struct suncordata *) ((bfd)->tdata))->data_section)
+#define core_stacksec(bfd) (((struct suncordata*)((bfd)->tdata))->stack_section)
+#define core_regsec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg_section)
+#define core_reg2sec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg2_section)
+
+/* These are stored in the bfd's tdata */
+struct suncordata {
+  struct core *hdr;             /* core file header */
+  asection *data_section;
+  asection *stack_section;
+  asection *reg_section;
+  asection *reg2_section;
+};
+
+bfd_target *
+sunos4_core_file_p (abfd)
+     bfd *abfd;
+{
+  unsigned char longbuf[4];    /* Raw bytes of various header fields */
+  int core_size;
+  int core_mag;
+  struct core *core;
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)longbuf, 1, sizeof (longbuf), abfd) !=
+        sizeof (longbuf))
+    return 0;
+  core_mag = bfd_h_getlong (abfd, longbuf);
+
+  if (core_mag != CORE_MAGIC) return 0;
+
+  /* SunOS core headers can vary in length; second word is size; */
+  if (bfd_read ((void *)longbuf, 1, sizeof (longbuf), abfd) !=
+        sizeof (longbuf))
+    return 0;
+  core_size = bfd_h_getlong (abfd, longbuf);
+  /* Sanity check */
+  if (core_size > 20000)
+    return 0;
+
+  if (bfd_seek (abfd, 0L, false) < 0) return 0;
+
+  rawptr = zalloc (core_size + sizeof (struct suncordata));
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  core = (struct core *) (rawptr + sizeof (struct suncordata));
+
+  if ((bfd_read ((void *) core, 1, core_size, abfd)) != core_size) {
+    bfd_error = system_call_error;
+    free ((void *)rawptr);
+    return 0;
+  }
+
+  swapcore (abfd, core);
+  set_tdata (abfd, ((struct suncordata *) rawptr));
+  core_hdr (abfd) = core;
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  core_stacksec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_stacksec (abfd) == NULL) {
+loser:
+    bfd_error = no_memory;
+    free ((void *)rawptr);
+    return 0;
+  }
+  core_datasec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_datasec (abfd) == NULL) {
+loser1:
+    free ((void *)core_stacksec (abfd));
+    goto loser;
+  }
+  core_regsec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_regsec (abfd) == NULL) {
+loser2:
+    free ((void *)core_datasec (abfd));
+    goto loser1;
+  }
+  core_reg2sec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_reg2sec (abfd) == NULL) {
+    free ((void *)core_regsec (abfd));
+    goto loser2;
+  }
+
+  core_stacksec (abfd)->name = ".stack";
+  core_datasec (abfd)->name = ".data";
+  core_regsec (abfd)->name = ".reg";
+  core_reg2sec (abfd)->name = ".reg2";
+
+  core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_regsec (abfd)->flags = SEC_ALLOC;
+  core_reg2sec (abfd)->flags = SEC_ALLOC;
+
+  core_stacksec (abfd)->size = core->c_ssize;
+  core_datasec (abfd)->size = core->c_dsize;
+  core_regsec (abfd)->size = (sizeof core->c_regs);
+  /* Float regs take up end of struct, except c_ucode.  */
+  core_reg2sec (abfd)->size = core_size - (sizeof core->c_ucode) -
+                             (file_ptr)(((struct core *)0)->fp_stuff);
+
+  core_stacksec (abfd)->vma = (USRSTACK - core->c_ssize);
+  core_datasec (abfd)->vma = N_DATADDR(core->c_aouthdr);
+  core_regsec (abfd)->vma = -1;
+  core_reg2sec (abfd)->vma = -1;
+
+  core_stacksec (abfd)->filepos = core->c_len + core->c_dsize;
+  core_datasec (abfd)->filepos = core->c_len;
+                        /* In file header: */
+  core_regsec (abfd)->filepos = (file_ptr)(&((struct core *)0)->c_regs);
+  core_reg2sec (abfd)->filepos = (file_ptr)(((struct core *)0)->fp_stuff);
+
+  /* Align to word at least */
+  core_stacksec (abfd)->alignment_power = 2;
+  core_datasec (abfd)->alignment_power = 2;
+  core_regsec (abfd)->alignment_power = 2;
+  core_reg2sec (abfd)->alignment_power = 2;
+
+  abfd->sections = core_stacksec (abfd);
+  core_stacksec (abfd)->next = core_datasec (abfd);
+  core_datasec (abfd)->next = core_regsec (abfd);
+  core_regsec (abfd)->next = core_reg2sec (abfd);
+
+  abfd->section_count = 4;
+
+  return abfd->xvec;
+}
+
+char *
+sunos4_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_cmdname;
+}
+
+int
+sunos4_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_signo;
+}
+
+boolean
+sunos4_core_file_matches_executable_p  (core_bfd, exec_bfd)
+     bfd *core_bfd, *exec_bfd;
+{
+  if (core_bfd->xvec != exec_bfd->xvec) {
+    bfd_error = system_call_error;
+    return false;
+  }
+
+  return (bcmp ((char *)&core_hdr (core_bfd), (char*) &exec_hdr (exec_bfd),
+                sizeof (struct exec)) == 0) ? true : false;
+}
+
+/* byte-swap core structure */
+/* FIXME, this needs more work to swap IN a core struct from raw bytes */
+static void
+swapcore (abfd, core)
+     bfd *abfd;
+     struct core *core;
+{
+  unsigned char exec_bytes[EXEC_BYTES_SIZE];
+
+  core->c_magic = bfd_h_getlong (abfd, (unsigned char *)&core->c_magic);
+  core->c_len   = bfd_h_getlong (abfd, (unsigned char *)&core->c_len  );
+  /* Leave integer registers in target byte order.  */
+  bcopy ((char *)&(core->c_aouthdr), (char *)exec_bytes, EXEC_BYTES_SIZE);
+  bfd_aout_swap_exec_header_in (abfd, exec_bytes, &core->c_aouthdr);
+  core->c_signo = bfd_h_getlong (abfd, (unsigned char *)&core->c_signo);
+  core->c_tsize = bfd_h_getlong (abfd, (unsigned char *)&core->c_tsize);
+  core->c_dsize = bfd_h_getlong (abfd, (unsigned char *)&core->c_dsize);
+  core->c_ssize = bfd_h_getlong (abfd, (unsigned char *)&core->c_ssize);
+  /* Leave FP registers in target byte order.  */
+  /* Leave "c_ucode" unswapped for now, since we can't find it easily.  */
+}
+\f
+/** exec and core file sections */
+
+boolean
+sunos4_new_section_hook (abfd, newsect)
+     bfd *abfd;
+     asection *newsect;
+{
+  /* align to double at least */
+  newsect->alignment_power = 3;
+
+  if (bfd_get_format (abfd) == bfd_object) {
+    if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
+      obj_textsec(abfd)= newsect;
+      return true;
+    }
+
+    if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
+      obj_datasec(abfd) = newsect;
+      return true;
+    }
+
+    if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
+      obj_bsssec(abfd) = newsect;
+      return true;
+    }
+  }
+
+  /* We allow more than three sections internally */
+  return true;
+}
+
+boolean
+sunos4_set_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     unsigned char *location;
+     file_ptr offset;
+      int count;
+{
+  if (abfd->output_has_begun == false)
+    {                          /* set by bfd.c handler */
+      if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)
+         
+         /*||
+           (obj_textsec (abfd)->size == 0) || (obj_datasec (abfd)->size=
+           0)*/
+         ) 
+       {
+         bfd_error = invalid_operation;
+         return false;
+       }
+
+
+#if 0
+      if (abfd->flags & D_PAGED)
+       {
+         obj_textsec (abfd)->filepos = sizeof(struct exec);
+         obj_datasec(abfd)->filepos =  obj_textsec (abfd)->size;
+       }
+      else 
+#endif
+       {
+         obj_textsec (abfd)->filepos = sizeof(struct exec);
+         obj_datasec(abfd)->filepos = obj_textsec(abfd)->filepos  + obj_textsec (abfd)->size;
+
+       }
+    }
+  /* regardless, once we know what we're doing, we might as well get going */
+
+  bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+  if (count) {
+    return (bfd_write ((void *)location, 1, count, abfd) == count) ?
+      true : false;
+  }
+  return false;
+}
+boolean
+sunos4_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     void  *location;
+     file_ptr offset;
+     int count;
+{
+  if (count) {
+    if (offset >= section->size) return false;
+
+    bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+    return (bfd_read (location, 1, count, abfd) == count) ? true:false;
+  }
+  else return true;
+}
+
+\f
+/* Classify stabs symbols */
+
+
+#define sym_in_text_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
+
+#define sym_in_data_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
+
+#define sym_in_bss_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
+
+/* Symbol is undefined if type is N_UNDF|N_EXT and if it has
+   zero in the "value" field.  Nonzeroes there are fortrancommon
+   symbols.  */
+#define sym_is_undefined(sym) \
+        ((sym)->n_type == (N_UNDF | N_EXT) && (sym)->n_value == 0)
+
+/* Symbol is a global definition if N_EXT is on and if it has
+   a nonzero type field.  */
+#define sym_is_global_defn(sym) \
+        (((sym)->n_type & N_EXT) && (sym)->n_type & N_TYPE)
+
+/* Symbol is debugger info if any bits outside N_TYPE or N_EXT
+   are on.  */
+#define sym_is_debugger_info(sym) \
+        ((sym)->n_type & ~(N_EXT | N_TYPE))
+
+#define sym_is_fortrancommon(sym)       \
+        (((sym)->n_type == (N_EXT)) && (sym)->n_value != 0)
+
+/* Symbol is absolute if it has N_ABS set */
+#define sym_is_absolute(sym) \
+              (((sym)->n_type  & N_TYPE)== N_ABS)
+
+
+#define sym_is_indirect(sym) \
+              (((sym)->n_type  & N_ABS)== N_ABS)
+
+/* Only in their own functions for ease of debugging; when sym flags have
+   stabilised these should be inlined into their (single) caller */
+
+static void
+translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
+     struct nlist *sym_pointer;
+     aout_symbol_type *cache_ptr;
+     bfd *abfd;
+{
+  switch (cache_ptr->type & N_TYPE) {
+  case N_SETA:
+  case N_SETT:
+  case N_SETD:
+  case N_SETB:
+    {
+      asection *section = bfd_make_section(abfd,
+                                          cache_ptr->symbol.name);
+      arelent_chain *reloc = (arelent_chain *)malloc(sizeof(arelent_chain));
+
+      switch ( (cache_ptr->type  & N_TYPE) ) {
+      case N_SETA:
+       reloc->relent.section =  (asection *)NULL;
+       cache_ptr->symbol.section = (asection *)NULL;
+       break;
+      case N_SETT:
+       reloc->relent.section = (asection *)obj_textsec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETD:
+       reloc->relent.section = (asection *)obj_datasec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETB:
+       reloc->relent.section = (asection *)obj_bsssec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      }
+      cache_ptr->symbol.section = reloc->relent.section;
+      reloc->relent.addend = cache_ptr->symbol.value ;
+      /* 
+        We modify the symbol to belong to a section depending upon the
+        name of the symbol - probably __CTOR__ or __DTOR__ but we don't
+        really care, and add to the size of the section to contain a
+        pointer to the symbol. Build a reloc entry to relocate to this
+        symbol attached to this section.
+        */
+
+
+      section->flags = SEC_CONSTRUCTOR;
+      section->reloc_count++;
+      section->alignment_power = 2;
+      reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
+      reloc->next = section->constructor_chain;
+      section->constructor_chain = reloc;
+      reloc->relent.address = section->size;
+      section->size += sizeof(int *);
+
+      reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
+      cache_ptr->symbol.flags |=  BSF_DEBUGGING ;
+      }
+    break;
+  default:
+
+    if (sym_is_debugger_info (sym_pointer)) {
+      cache_ptr->symbol.flags = BSF_DEBUGGING ;
+      /* Work out the section correct for this symbol */
+      switch (sym_pointer->n_type & N_TYPE) 
+       {
+       case N_TEXT:
+       case N_FN:
+         cache_ptr->symbol.section = obj_textsec (abfd);
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         break;
+       case N_DATA:
+         cache_ptr->symbol.value  -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+         break;
+       case N_BSS :
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+         break;
+       case N_ABS:
+       default:
+         cache_ptr->symbol.section = 0;
+         break;
+       }
+    }
+    else {
+      if (sym_is_fortrancommon (sym_pointer))
+       {
+         cache_ptr->symbol.flags = BSF_FORT_COMM;
+         cache_ptr->symbol.section = (asection *)NULL;
+       }
+      else {
+       if (sym_is_undefined (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_UNDEFINED;
+       }
+       else if (sym_is_global_defn (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+       }
+
+       else if (sym_is_absolute (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_ABSOLUTE;
+       }
+       else {
+         cache_ptr->symbol.flags = BSF_LOCAL;
+       }
+
+       /* In a.out, the value of a symbol is always relative to the 
+        * start of the file, if this is a data symbol we'll subtract
+        * the size of the text section to get the section relative
+        * value. If this is a bss symbol (which would be strange)
+        * we'll subtract the size of the previous two sections
+        * to find the section relative address.
+        */
+
+       if (sym_in_text_section (sym_pointer))   {
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         cache_ptr->symbol.section = obj_textsec (abfd);
+       }
+       else if (sym_in_data_section (sym_pointer)){
+         cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+       }
+       else if (sym_in_bss_section(sym_pointer)) {
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+       }
+       else {
+         cache_ptr->symbol.section = (asection *)NULL;
+         cache_ptr->symbol.flags |= BSF_ABSOLUTE;
+       }
+      }
+    }
+  }
+}
+
+void
+translate_to_native_sym_flags (sym_pointer, cache_ptr_g, abfd)
+     struct nlist *sym_pointer;
+     generic_symbol_type *cache_ptr_g;
+     bfd *abfd;
+{
+  asymbol *cache_ptr = (asymbol *)cache_ptr_g;
+
+  /* FIXME check for wrigin bss */
+  if (bfd_get_section(cache_ptr)) {
+    if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
+      sym_pointer->n_type |= N_BSS;
+    }
+    else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
+      sym_pointer->n_type |= N_DATA;
+    }
+    else  if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
+      sym_pointer->n_type |= N_TEXT;
+    }
+    else {
+      bfd_error_trap(bfd_error_nonrepresentable_section,
+                bfd_get_output_section(cache_ptr)->name);
+
+    }
+    /* Turn the symbol from section relative to absolute again */
+    sym_pointer->n_value +=
+      cache_ptr->section->output_section->vma 
+       + cache_ptr->section->output_offset ;
+  }
+  else {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
+    sym_pointer->n_type = (N_UNDF | N_EXT);
+    return;
+  }
+
+  if (cache_ptr->flags & BSF_ABSOLUTE) {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
+    sym_pointer->n_type |= N_EXT;
+  }
+  if (cache_ptr->flags & BSF_DEBUGGING) {
+    sym_pointer->n_type = ((aout_symbol_type *)cache_ptr)->type;
+  }
+  
+}
+\f
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+   function exits.  We read the strings into a buffer large enough to
+   hold them all plus all the cached symbol entries. */
+
+asymbol *
+sunos4_make_empty_symbol (abfd)
+bfd *abfd;
+{
+  aout_symbol_type  *new =
+    (aout_symbol_type *)zalloc (sizeof (aout_symbol_type));
+  new->symbol.the_bfd = abfd;
+
+  return &new->symbol;
+}
+
+boolean
+sunos4_slurp_symbol_table (abfd)
+     bfd *abfd;
+{
+  unsigned int symbol_count;
+  size_t symbol_size;
+  size_t string_size;
+  struct nlist *syms;
+  char *strings;
+  aout_symbol_type *cached;
+
+  /* If there's no work to be done, don't do any */
+  if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
+  symbol_size = exec_hdr(abfd)->a_syms;
+  if (symbol_size == 0) {
+    bfd_error = no_symbols;
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)&string_size, 4, 1, abfd) != 4)
+    return false;
+  string_size = bfd_h_getlong (abfd, (unsigned char *)&string_size);
+
+  symbol_count = symbol_size / sizeof (struct nlist);
+
+  /* Malloc (should alloca) space for native symbols, and
+     malloc space for string table and symbol cache. */
+
+  syms = (struct nlist *) zalloc (symbol_size);
+  if (syms == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  cached = (aout_symbol_type *) zalloc ((size_t)(string_size + 1 +
+                               (symbol_count * sizeof (aout_symbol_type))));
+  if (cached == NULL) {
+    bfd_error = no_memory;
+    free ((void *)syms);
+    return false;
+  }
+
+  strings = ((char *) cached) + (symbol_count * sizeof (aout_symbol_type));
+
+  bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)syms, 1, symbol_size, abfd) != symbol_size) {
+  bailout:
+    free ((void *)cached);
+    free ((void*)syms);
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)strings, 1, string_size, abfd) != string_size) {
+    goto bailout;
+  }
+
+  /* OK, now walk the new symtable, cacheing symbol properties */
+  {
+    register struct nlist *sym_pointer;
+    register struct nlist *sym_end = syms + symbol_count;
+    register aout_symbol_type *cache_ptr = cached;
+
+    if (bfd_header_twiddle_required (abfd) == true) {
+      /* run through the table and byte swap if needed */
+      for (sym_pointer = syms; sym_pointer < sym_end;  sym_pointer++) {
+        sym_pointer->n_un.n_strx =
+         bfd_h_get_x (abfd, &sym_pointer->n_un.n_strx);
+        sym_pointer->n_desc =
+         bfd_h_get_x (abfd, &sym_pointer->n_desc);
+        sym_pointer->n_value =
+         bfd_h_get_x (abfd, &sym_pointer->n_value);
+       sym_pointer->n_other = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_other);
+       sym_pointer->n_type = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_type);
+
+      }
+    }
+    /* Run through table and copy values */
+    for (sym_pointer = syms, cache_ptr = cached;
+        sym_pointer < sym_end; sym_pointer++, cache_ptr++) 
+      {
+       cache_ptr->symbol.the_bfd = abfd;
+       if (sym_pointer->n_un.n_strx)
+         cache_ptr->symbol.name = sym_pointer->n_un.n_strx + strings;
+       else
+         cache_ptr->symbol.name = (char *)NULL;
+       cache_ptr->symbol.value = sym_pointer->n_value;
+       cache_ptr->desc = sym_pointer->n_desc;
+       cache_ptr->other = sym_pointer->n_other;
+       cache_ptr->type = sym_pointer->n_type;
+       cache_ptr->symbol.udata = 0;
+       translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
+
+      }
+  }
+
+  obj_aout_symbols (abfd) =  cached;
+  bfd_get_symcount (abfd) = symbol_count;
+  free ((void *)syms);
+
+  return true;
+}
+
+\f
+void
+sunos4_write_syms (abfd)
+     bfd *abfd;
+{
+  unsigned int count ;
+  asymbol **generic = bfd_get_outsymbols (abfd);
+
+  unsigned int stindex = sizeof(stindex); /* initial string length */
+
+  for (count = 0; count < bfd_get_symcount (abfd); count++) {
+    asymbol *g = generic[count];
+    struct nlist nsp;
+
+    if (g->name) {
+      unsigned int length = strlen(g->name) +1;
+      bfd_h_putlong  (abfd, stindex, (unsigned char *)&nsp.n_un.n_strx);
+      stindex += length;
+    }
+    else {
+      bfd_h_putlong  (abfd, 0, (unsigned char *)&nsp.n_un.n_strx);
+    }
+
+    if (g->the_bfd->xvec->flavour == abfd->xvec->flavour) 
+      {
+       nsp.n_desc = aout_symbol( g)->desc;
+       nsp.n_other = aout_symbol(g)->other;
+       nsp.n_type = aout_symbol(g)->type;
+      }
+    else
+      {
+       nsp.n_desc = 0;
+       nsp.n_other = 0;
+       nsp.n_type = 0;
+      }
+
+
+    nsp.n_value = g->value;
+    translate_to_native_sym_flags (&nsp, (generic_symbol_type *)g, abfd);
+
+
+    bfd_h_putshort (abfd, nsp.n_desc, (unsigned char *)&nsp.n_desc);
+    bfd_h_putlong  (abfd, nsp.n_value, (unsigned char *)&nsp.n_value);
+    bfd_write((void *)&nsp,1, sizeof(nsp), abfd);
+  }
+
+
+  /* Now output the strings.  Be sure to put string length into correct
+   * byte ordering before writing it.
+   */
+  bfd_h_putlong  (abfd, stindex, (unsigned char *)&stindex);
+
+  bfd_write((void *)&stindex, 1, sizeof(stindex), abfd);
+  
+  generic = bfd_get_outsymbols(abfd);
+  for (count = 0; count < bfd_get_symcount(abfd); count++) 
+    {
+      asymbol *g = *(generic++);
+
+      if (g->name != (char *)NULL) 
+       {
+         size_t length = strlen(g->name)+1;
+         bfd_write((void *)g->name, 1, length, abfd);
+       }
+      if ((g->flags & BSF_FAKE)==0) {
+       g->name = itos(count);  /* smash the generic symbol */
+      }
+    }
+}
+
+\f
+void
+sunos4_reclaim_symbol_table (abfd)
+     bfd *abfd;
+{
+  asection *section;
+
+  if (!bfd_get_symcount (abfd)) return;
+
+  for (section = abfd->sections;
+       section != (asection *) NULL;
+       section = section->next)
+    if (section->relocation) {
+      free ((void *)section->relocation);
+      section->relocation = NULL;
+      section->reloc_count = 0;
+    }
+
+  bfd_get_symcount (abfd) = 0;
+  free ((void *)obj_aout_symbols (abfd));
+  obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+}
+\f
+unsigned int
+sunos4_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
+}
+
+unsigned int
+sunos4_get_symtab (abfd, location)
+     bfd *abfd;
+     asymbol **location;
+{
+  unsigned int counter = 0;
+  aout_symbol_type *symbase;
+
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
+    *(location++) = (asymbol *)( symbase++);
+  *location++ =0;
+  return bfd_get_symcount(abfd);
+}
+
+\f
+/* Obsolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+   BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+sunos4_get_symcount_upper_bound (abfd)
+     bfd *abfd;
+{
+  /* In case we're doing an output file or something...?  */
+  if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+  return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+}
+
+symindex
+sunos4_get_first_symbol (ignore_abfd)
+     bfd * ignore_abfd;
+{
+  return 0;
+}
+
+symindex
+sunos4_get_next_symbol (abfd, oidx)
+     bfd *abfd;
+     symindex oidx;
+{
+  if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+  return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
+}
+
+char *
+sunos4_symbol_name (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.name;
+}
+
+long
+sunos4_symbol_value (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.value;
+}
+
+symclass
+sunos4_classify_symbol (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+  if ((sym->symbol.flags & BSF_FORT_COMM) != 0)   return bfd_symclass_fcommon;
+  if ((sym->symbol.flags & BSF_GLOBAL) != 0)    return bfd_symclass_global;
+  if ((sym->symbol.flags & BSF_DEBUGGING) != 0)  return bfd_symclass_debugger;
+  if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+
+  return bfd_symclass_unknown;
+}
+
+boolean
+sunos4_symbol_hasclass (abfd, idx, class)
+     bfd *abfd;
+     symindex idx;
+     symclass class;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+  switch (class) {
+  case bfd_symclass_fcommon:
+    return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+  case bfd_symclass_global:
+    return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+  case bfd_symclass_debugger:
+    return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+  case bfd_symclass_undefined:
+    return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+  default: return false;
+  }
+}
+\f
+/* Standard reloc stuff */
+/* Output standard relocation information to a file in target byte order. */
+
+void
+swap_std_reloc_out (abfd, p, natptr, count)
+     bfd *abfd;
+     arelent **p;              /* Generic relocation struct */
+     struct reloc_std_bytes *natptr;
+     unsigned int count;
+{
+  int r_index;
+  int r_extern;
+  unsigned int r_length;
+  int r_pcrel;
+  int r_baserel, r_jmptable, r_relative;
+  unsigned int r_addend;
+  unsigned int idx;
+  for (idx = 0; idx < count; idx++, p++, natptr++) 
+    {
+      arelent *g = *p;
+      bfd_h_putlong (abfd, g->address, natptr->r_address);
+
+      r_length = g->howto->size; /* Size as a power of two */
+      r_pcrel  = g->howto->pc_relative;        /* Relative to PC? */
+      /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
+      r_baserel = 0;
+      r_jmptable = 0;
+      r_relative = 0;
+
+      r_addend = g->addend;    /* Start here, see how it goes */
+
+      /* name was clobbered by sunos4_write_syms to be symbol index */
+
+      if (g->sym_ptr_ptr != NULL) 
+       {
+         if ((*(g->sym_ptr_ptr))->section) {
+           /* put the section offset into the addend for output */
+           r_addend += (*(g->sym_ptr_ptr))->section->vma;
+         }
+
+         r_index = stoi((*(g->sym_ptr_ptr))->name);
+         r_extern = 1;
+       }
+      else {
+       r_extern = 0;
+       if (g->section == NULL) {
+         BFD_ASSERT(0);
+         r_index = N_ABS | N_EXT;
+       }
+       else  if(g->section->output_section == obj_textsec(abfd)) {
+         r_index = N_TEXT | N_EXT;
+         r_addend += g->section->output_section->vma;
+       }
+       else if (g->section->output_section == obj_datasec(abfd)) {
+         r_index = N_DATA | N_EXT;
+         r_addend += g->section->output_section->vma;
+       }
+       else if (g->section->output_section == obj_bsssec(abfd)) {
+         r_index = N_BSS | N_EXT ;
+         r_addend += g->section->output_section->vma;
+       }
+       else {
+         BFD_ASSERT(0);
+       }
+      }
+
+      /* now the fun stuff */
+      if (abfd->xvec->header_byteorder_big_p != false) {
+       natptr->r_index[0] = r_index >> 16;
+       natptr->r_index[1] = r_index >> 8;
+       natptr->r_index[2] = r_index;
+       natptr->r_bits[0] =
+         (r_extern?    RELOC_STD_BITS_EXTERN_BIG: 0)
+           | (r_pcrel?     RELOC_STD_BITS_PCREL_BIG: 0)
+             | (r_baserel?   RELOC_STD_BITS_BASEREL_BIG: 0)
+               | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_BIG: 0)
+                 | (r_relative?  RELOC_STD_BITS_RELATIVE_BIG: 0)
+                   | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG);
+      } else {
+       natptr->r_index[2] = r_index >> 16;
+       natptr->r_index[1] = r_index >> 8;
+       natptr->r_index[0] = r_index;
+       natptr->r_bits[0] =
+         (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
+           | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
+             | (r_baserel?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
+               | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
+                 | (r_relative?  RELOC_STD_BITS_RELATIVE_LITTLE: 0)
+                   | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE);
+      }
+
+
+    }
+}
+
+
+/* Extended stuff */
+/* Output extended relocation information to a file in target byte order. */
+
+void
+swap_ext_reloc_out (abfd, p, natptr, count)
+     bfd *abfd;
+     arelent **p;              /* Generic relocation struct */
+     register struct reloc_ext_bytes *natptr;
+     unsigned int count;
+{
+
+  int r_index;
+  int r_extern;
+  unsigned int r_type;
+  unsigned int r_addend;
+  unsigned int idx;
+  for (idx = 0; idx < count; idx++, p++, natptr++) {
+    arelent *g = *p;
+
+    bfd_h_putlong (abfd, g->address, natptr->r_address);
+
+    /* Find a type in the output format which matches the input howto - 
+       at the moment we assume input format == output format FIXME!! */
+    r_type = (enum reloc_type) g->howto->type;
+
+    r_addend = g->addend;      /* Start here, see how it goes */
+
+    /* name was clobbered by sunos4_write_syms to be symbol index*/
+
+    if (g->sym_ptr_ptr != NULL) 
+      {
+       if ((*(g->sym_ptr_ptr))->section) {
+         /* put the section offset into the addend for output */
+         r_addend += (*(g->sym_ptr_ptr))->section->vma;
+       }
+
+       r_index = stoi((*(g->sym_ptr_ptr))->name);
+       r_extern = 1;
+      }
+    else {
+      r_extern = 0;
+      if (g->section == NULL) {
+       BFD_ASSERT(0);
+       r_index = N_ABS | N_EXT;
+      }
+      else  if(g->section->output_section == obj_textsec(abfd)) {
+       r_index = N_TEXT | N_EXT;
+       r_addend += g->section->output_section->vma;
+      }
+      else if (g->section->output_section == obj_datasec(abfd)) {
+       r_index = N_DATA | N_EXT;
+       r_addend += g->section->output_section->vma;
+      }
+      else if (g->section->output_section == obj_bsssec(abfd)) {
+       r_index = N_BSS | N_EXT ;
+       r_addend += g->section->output_section->vma;
+      }
+      else {
+       BFD_ASSERT(0);
+      }
+    }
+
+    /* now the fun stuff */
+    if (abfd->xvec->header_byteorder_big_p != false) {
+      natptr->r_index[0] = r_index >> 16;
+      natptr->r_index[1] = r_index >> 8;
+      natptr->r_index[2] = r_index;
+      natptr->r_bits[0] =
+       (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
+         || (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
+    } else {
+      natptr->r_index[2] = r_index >> 16;
+      natptr->r_index[1] = r_index >> 8;
+      natptr->r_index[0] = r_index;
+      natptr->r_bits[0] =
+       (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
+         || (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
+    }
+
+    bfd_h_putlong (abfd, r_addend, natptr->r_addend);
+  }
+}
+#define MOVE_ADDRESS(ad)                                                       \
+  if (r_extern) {                                                      \
+    cache_ptr->sym_ptr_ptr = symbols + r_index;                                \
+    cache_ptr->section = (asection *)NULL;                             \
+      cache_ptr->addend = ad;                                          \
+  } else {                                                             \
+    cache_ptr->sym_ptr_ptr = (asymbol **)NULL;                         \
+    switch (r_index) {                                                 \
+    case N_TEXT:                                                       \
+    case N_TEXT | N_EXT:                                               \
+      cache_ptr->section = obj_textsec(abfd);                          \
+      cache_ptr->addend = ad  - su->textsec->vma;                      \
+      break;                                                           \
+    case N_DATA:                                                       \
+    case N_DATA | N_EXT:                                               \
+      cache_ptr->section = obj_datasec(abfd);                          \
+      cache_ptr->addend = ad - su->datasec->vma;                       \
+      break;                                                           \
+    case N_BSS:                                                                \
+    case N_BSS | N_EXT:                                                        \
+      cache_ptr->section = obj_bsssec(abfd);                           \
+      cache_ptr->addend = ad - su->bsssec->vma;                                \
+      break;                                                           \
+    case N_ABS:                                                                \
+    case N_ABS | N_EXT:                                                        \
+      BFD_ASSERT(1);                                                   \
+      break;                                                           \
+    default:                                                           \
+      BFD_ASSERT(1);                                                   \
+      break;                                                           \
+    }                                                                  \
+  }                                                                    \
+
+void
+swap_ext_reloc_in (abfd, bytes, cache_ptr, symbols)
+     bfd *abfd;
+     struct reloc_ext_bytes *bytes;
+     arelent *cache_ptr;
+     asymbol **symbols;
+{
+  int r_index;
+  int r_extern;
+  unsigned int r_type;
+  struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
+
+  cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
+
+  /* now the fun stuff */
+  if (abfd->xvec->header_byteorder_big_p != false) {
+    r_index =  (bytes->r_index[0] << 16)
+            | (bytes->r_index[1] << 8)
+            |  bytes->r_index[2];
+    r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_BIG));
+    r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_BIG)
+                                     >> RELOC_EXT_BITS_TYPE_SH_BIG;
+  } else {
+    r_index =  (bytes->r_index[2] << 16)
+            | (bytes->r_index[1] << 8)
+            |  bytes->r_index[0];
+    r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
+    r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_LITTLE)
+                                     >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
+  }
+
+  cache_ptr->howto =  howto_table_ext + r_type;
+  MOVE_ADDRESS(bfd_h_getlong(abfd,bytes->r_addend));
+                                                                        
+}
+
+void
+swap_std_reloc_in (abfd, bytes, cache_ptr, symbols)
+     bfd *abfd;
+ struct reloc_std_bytes *bytes;
+     arelent *cache_ptr;
+     asymbol **symbols;
+{
+  int r_index;
+  int r_extern;
+  unsigned int r_length;
+  int r_pcrel;
+  int r_baserel, r_jmptable, r_relative;
+  struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
+  cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
+
+  /* now the fun stuff */
+  if (abfd->xvec->header_byteorder_big_p != false) {
+    r_index =  (bytes->r_index[0] << 16)
+      | (bytes->r_index[1] << 8)
+       |  bytes->r_index[2];
+    r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_BIG));
+    r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_BIG));
+    r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_BIG));
+    r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+    r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_BIG));
+    r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_BIG) 
+      >> RELOC_STD_BITS_LENGTH_SH_BIG;
+  } else {
+    r_index =  (bytes->r_index[2] << 16)
+      | (bytes->r_index[1] << 8)
+       |  bytes->r_index[0];
+    r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_LITTLE));
+    r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_LITTLE));
+    r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_LITTLE));
+    r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
+    r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
+    r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_LITTLE) 
+      >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
+  }
+
+  cache_ptr->howto =  howto_table_std + r_length + 4 * r_pcrel;
+  /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
+
+  MOVE_ADDRESS(0);
+}
+
+/* Reloc hackery */
+
+boolean
+sunos4_slurp_reloc_table (abfd, asect, symbols)
+     bfd *abfd;
+     sec_ptr asect;
+     asymbol **symbols;
+{
+  unsigned int count;
+  size_t reloc_size;
+  void *relocs;
+  arelent *reloc_cache;
+  size_t each_size;
+
+  if (asect->relocation) return true;
+
+  if (asect->flags & SEC_CONSTRUCTOR) return true;
+
+  if (asect == obj_datasec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_drsize;
+    goto doit;
+  }
+
+  if (asect == obj_textsec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_trsize;
+    goto doit;
+  }
+
+  bfd_error = invalid_operation;
+  return false;
+
+ doit:
+  bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
+  each_size = reloc_size_func(abfd);
+
+  count = reloc_size / each_size;
+
+  relocs =  malloc (reloc_size);
+  if (!relocs) {
+    bfd_error = no_memory;
+    return false;
+  }
+  reloc_cache = (arelent *) zalloc ((size_t)(count * sizeof (arelent)));
+  if (reloc_cache == (arelent *)NULL) {
+    free (relocs);
+    bfd_error = no_memory;
+    return false;
+  }
+
+  if (bfd_read ( relocs, 1, reloc_size, abfd) != reloc_size) {
+    bfd_error = system_call_error;
+    free (reloc_cache);
+    free (relocs);
+    return false;
+  }
+
+  if (each_size == RELOC_EXT_SIZE)
+    {
+      register struct reloc_ext_bytes *rptr = relocs;
+      unsigned int counter = 0;
+      arelent *cache_ptr = reloc_cache;
+
+      for (; counter < count; counter++, rptr++, cache_ptr++) {
+       swap_ext_reloc_in(abfd, rptr, cache_ptr, symbols);
+      }
+    }
+  else {
+    register struct reloc_std_bytes *rptr = relocs;
+    unsigned int counter = 0;
+    arelent *cache_ptr = reloc_cache;
+
+    for (; counter < count; counter++, rptr++, cache_ptr++) {
+       swap_std_reloc_in(abfd, rptr, cache_ptr, symbols);
+    }
+
+  }
+  free (relocs);
+  asect->relocation = reloc_cache;
+  asect->reloc_count = count;
+  return true;
+}
+
+
+
+/* Write out a relocation section into an object file.  */
+
+static boolean
+sunos4_squirt_out_relocs (abfd, section)
+     bfd *abfd;
+     asection *section;
+{
+  arelent **generic;
+  unsigned char *native;
+  size_t each_size;
+
+  unsigned int count = section->reloc_count;
+  size_t natsize;
+
+  if (count == 0) return true;
+
+  each_size = reloc_size_func(abfd);
+  natsize = each_size * count;
+  native = (unsigned char *) zalloc (natsize);
+  if (!native) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  generic = section->orelocation;
+
+  if (each_size == RELOC_EXT_SIZE) 
+    {
+      swap_ext_reloc_out (abfd,
+                         generic,
+                         (struct reloc_ext_bytes *)native,
+                         count);
+    }
+  else 
+    {
+      swap_std_reloc_out(abfd, generic, native, count);
+    }
+
+  if ( bfd_write ((void *) native, 1, natsize, abfd) != natsize) {
+    free(native);
+    return false;
+  }
+  free (native);
+
+  return true;
+}
+
+/* This is stupid.  This function should be a boolean predicate */
+unsigned int
+sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  arelent *tblptr = section->relocation;
+  unsigned int count;
+
+  if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
+    return 0;
+
+  if (section->flags & SEC_CONSTRUCTOR) {
+    arelent_chain *chain = section->constructor_chain;
+    for (count = 0; count < section->reloc_count; count ++) {
+      *relptr ++ = &chain->relent;
+      chain = chain->next;
+    }
+  }
+  else {
+    tblptr = section->relocation;
+    if (!tblptr) return 0;
+
+    for (count = 0; count++ < section->reloc_count;) 
+      {
+       *relptr++ = tblptr++;
+      }
+  }
+  *relptr = 0;
+
+  return section->reloc_count;
+}
+
+unsigned int
+sunos4_get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  if (bfd_get_format (abfd) != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+  if (asect->flags & SEC_CONSTRUCTOR) {
+    return (sizeof (arelent *) * (asect->reloc_count+1));
+  }
+
+
+  if (asect == obj_datasec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_drsize / reloc_size_func(abfd))
+             +1));
+
+  if (asect == obj_textsec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_trsize / reloc_size_func(abfd))
+             +1));
+
+  bfd_error = invalid_operation;
+  return 0;
+}
+
+void
+sunos4_reclaim_reloc (ignore_abfd, section)
+     bfd *ignore_abfd;
+     sec_ptr section;
+{
+  if (section->relocation) {
+    free (section->relocation);
+    section->relocation = NULL;
+    section->reloc_count = 0;
+    }
+}
+\f
+
+alent *
+sunos4_get_lineno(ignore_abfd, ignore_symbol)
+bfd *ignore_abfd;
+generic_symbol_type *ignore_symbol;
+{
+return (alent *)NULL;
+}
+
+void 
+sunos4_print_symbol(ignore_abfd, file,  symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+  switch (how) {
+  case bfd_print_symbol_name_enum:
+    fprintf(file,"%s", symbol->name);
+    break;
+  case bfd_print_symbol_type_enum:
+    fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
+           (unsigned)(   aout_symbol(symbol)->other  & 0xff),
+           (unsigned)(aout_symbol(symbol)->type));
+    break;
+  case bfd_print_symbol_all_enum:
+    {
+      char *section_name = symbol->section == (asection *)NULL ?
+       "*abs" : symbol->section->name;
+
+      bfd_print_symbol_vandf((void *)file,symbol);
+
+      fprintf(file," %-5s %04x %02x %02x %s",
+             section_name,
+             (unsigned)(aout_symbol(symbol)->desc & 0xffff),
+             (unsigned)(aout_symbol(symbol)->other  & 0xff),
+             (unsigned)(aout_symbol(symbol)->type  & 0xff),
+             symbol->name);
+    }
+    break;
+  }
+}
+/* Once we know all the stuff that could be consed, we know how to clean
+   it up.  So why don't we? */
+
+boolean
+sunos4_close_and_cleanup (abfd)
+     bfd *abfd;
+{
+  if (!bfd_read_p (abfd))
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) return false; break;
+    case bfd_object:
+      if (!sunos4_write_object_contents (abfd))  return false; break;
+    default: bfd_error = invalid_operation; return false;
+    }
+
+#define cleaner(ptr) if (abfd->ptr) free (abfd->ptr)
+  cleaner (tdata);
+
+  if (abfd->my_archive)
+    cleaner (filename);
+
+#undef cleaner
+  return true;
+}
+
+/* 
+ provided a bfd, a section and an offset into the section, calculate
+ and return the name of the source file and the line nearest to the
+ wanted location.
+*/
+boolean
+sunos4_find_nearest_line(abfd,
+                        section,
+                        symbols,
+                        offset,
+                        filename_ptr,
+                        functionname_ptr,
+                        line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+  /* Run down the file looking for the filename, function and linenumber */
+  asymbol **p;
+  static  char buffer[100];
+  bfd_vma high_line_vma = ~0;
+  bfd_vma low_func_vma = 0;
+  asymbol *func = 0;
+  *filename_ptr = abfd->filename;
+  *functionname_ptr = 0;
+  *line_ptr = 0;
+  if (symbols != (asymbol **)NULL) {
+    for (p = symbols; *p; p++) {
+      aout_symbol_type  *q = (aout_symbol_type *)(*p);
+      switch (q->type){
+      case N_SO:
+       *filename_ptr = q->symbol.name;
+       if (obj_textsec(abfd) != section) {
+         return true;
+       }
+       break;
+      case N_SLINE:
+
+      case N_DSLINE:
+      case N_BSLINE:
+       /* We'll keep this if it resolves nearer than the one we have already */
+       if (q->symbol.value >= offset &&
+           q->symbol.value < high_line_vma) {
+         *line_ptr = q->desc;
+         high_line_vma = q->symbol.value;
+       }
+       break;
+      case N_FUN:
+       {
+         /* We'll keep this if it is nearer than the one we have already */
+         if (q->symbol.value >= low_func_vma &&
+             q->symbol.value <= offset) {
+           low_func_vma = q->symbol.value;
+           func = (asymbol *)q;
+         }
+         if (*line_ptr && func) {
+           char *function = func->name;
+           char *p;
+           strncpy(buffer, function, sizeof(buffer)-1);
+           buffer[sizeof(buffer)-1] = 0;
+           /* Have to remove : stuff */
+           p = strchr(buffer,':');
+           if (p != NULL) {*p = NULL; }
+           *functionname_ptr = buffer;
+           return true;
+
+         }
+       }
+       break;
+      }
+    }
+  }
+  
+  return true;
+
+}
+
+bfd_target aoutvec =
+{
+  "a.out-generic-big",         /* name */
+  bfd_target_aout_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  sunos4_close_and_cleanup,    /* _close_and_cleanup */
+  sunos4_set_section_contents, /* bfd_set_section_contents */
+  sunos4_get_section_contents, /* bfd_get_section_contents */
+  sunos4_new_section_hook,     /* new_section_hook */
+  sunos4_core_file_failing_command, /* _core_file_failing_command */
+  sunos4_core_file_failing_signal, /* _core_file_failing_signal */
+  sunos4_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_bsd_armap,         /* bfd_slurp_armap */
+  bfd_true,                    /* bfd_slurp_extended_name_table */
+  bfd_bsd_truncate_arname,     /* bfd_truncate_arname */
+
+  sunos4_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  sunos4_get_symtab,           /* canonicalize_symtab */
+  sunos4_reclaim_symbol_table, /* bfd_reclaim_symbol_table */
+  sunos4_get_reloc_upper_bound,        /* get_reloc_upper_bound */
+  sunos4_canonicalize_reloc,   /* bfd_canonicalize_reloc */
+  sunos4_reclaim_reloc,                /* bfd_reclaim_reloc */
+  sunos4_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  sunos4_get_first_symbol,     /* bfd_get_first_symbol */
+  sunos4_get_next_symbol,      /* bfd_get_next_symbol */
+  sunos4_classify_symbol,      /* bfd_classify_symbol */
+  sunos4_symbol_hasclass,      /* bfd_symbol_hasclass */
+  sunos4_symbol_name,          /* bfd_symbol_name */
+  sunos4_symbol_value,         /* bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target, sunos4_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, sunos4_core_file_p},
+  {bfd_false, sunos4_mkobject, /* bfd_zxset_format */
+     _bfd_generic_mkarchive, bfd_false},
+  sunos4_make_empty_symbol,
+  sunos4_print_symbol,
+  sunos4_get_lineno,
+  sunos4_set_arch_mach,
+  bsd_write_armap,
+  bfd_generic_openr_next_archived_file,
+  sunos4_find_nearest_line,    /* bfd_find_nearest_line */
+  bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+  };
+
diff --git a/bfd/targets.c b/bfd/targets.c
new file mode 100644 (file)
index 0000000..252cbe7
--- /dev/null
@@ -0,0 +1,56 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+
+/* This -*- C -*- source file will someday be machine-generated */
+
+/*** Defines the target vector through which operations dispatch */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+extern bfd_target aoutvec;
+extern bfd_target srec_vec;
+extern bfd_target b_out_vec_little_host;
+extern bfd_target b_out_vec_big_host;
+extern bfd_target icoff_little_vec;
+extern bfd_target icoff_big_vec;
+extern bfd_target ieee_vec;
+extern bfd_target oasys_vec;
+extern bfd_target m88k_bcs_vec;
+
+
+bfd_target *target_vector[] = 
+  {
+#ifndef INTEL960VERSION
+
+
+#endif /* INTEL960VERSION */
+    &ieee_vec,
+    &oasys_vec,
+    &icoff_big_vec,
+    &aoutvec,
+    &icoff_little_vec,
+    &m88k_bcs_vec,
+    &b_out_vec_big_host,
+    &b_out_vec_little_host,
+    &srec_vec,
+    NULL
+    };
diff --git a/binutils/TODO b/binutils/TODO
new file mode 100644 (file)
index 0000000..026f86c
--- /dev/null
@@ -0,0 +1,11 @@
+o - merge:
+       copy and strip
+       ar and ranlib
+       nm, size, and objdump
+
+o - make the long options more consistent.
+
+o - make ATT and BSD versions -- perhaps the options should be
+    controlled by an environment variable.
+
+o - Calling +help or +version should exit with a successful status (ie 0)
diff --git a/binutils/alloca.c b/binutils/alloca.c
new file mode 100644 (file)
index 0000000..9639def
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+       alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+       last edit:      86/05/30        rms
+          include config.h, since on VMS it renames some symbols.
+          Use xmalloc instead of malloc.
+
+       This implementation of the PWB library alloca() function,
+       which is used to allocate space off the run-time stack so
+       that it is automatically reclaimed upon procedure exit, 
+       was inspired by discussions with J. Q. Johnson of Cornell.
+
+       It should work under any C implementation that uses an
+       actual procedure stack (as opposed to a linked list of
+       frames).  There are some preprocessor constants that can
+       be defined when compiling for your specific system, for
+       improved efficiency; however, the defaults should be okay.
+
+       The general concept of this implementation is to keep
+       track of all alloca()-allocated blocks, and reclaim any
+       that are found to be deeper in the stack than the current
+       invocation.  This heuristic does not reclaim storage as
+       soon as it becomes invalid, but it will do so eventually.
+
+       As a special case, alloca(0) reclaims storage without
+       allocating any.  It is a good idea to use alloca(0) in
+       your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char    SCCSid[] = "@(#)alloca.c        1.1";   /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+#ifdef X3J11
+typedef void   *pointer;               /* generic pointer type */
+#else
+typedef char   *pointer;               /* generic pointer type */
+#endif
+
+#define        NULL    0                       /* null pointer constant */
+
+extern void    free();
+extern pointer xmalloc();
+
+/*
+       Define STACK_DIRECTION 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
+*/
+
+#ifndef STACK_DIRECTION
+#define        STACK_DIRECTION 0               /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define        STACK_DIR       STACK_DIRECTION /* known at compile-time */
+
+#else  /* STACK_DIRECTION == 0; need run-time code */
+
+static int     stack_dir;              /* 1 or -1 once known */
+#define        STACK_DIR       stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+  static char  *addr = NULL;   /* address of first
+                                  `dummy', once known */
+  auto char    dummy;          /* to get stack address */
+
+  if (addr == NULL)
+    {                          /* initial entry */
+      addr = &dummy;
+
+      find_stack_direction (); /* recurse once */
+    }
+  else                         /* second entry */
+    if (&dummy > addr)
+      stack_dir = 1;           /* stack grew upward */
+    else
+      stack_dir = -1;          /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+       An "alloca header" is used to:
+       (a) chain together all alloca()ed blocks;
+       (b) keep track of stack depth.
+
+       It is very important that sizeof(header) agree with malloc()
+       alignment chunk size.  The following default should work okay.
+*/
+
+#ifndef        ALIGN_SIZE
+#define        ALIGN_SIZE      sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];      /* to force sizeof(header) */
+  struct
+    {
+      union hdr *next;         /* for chaining headers */
+      char *deep;              /* for stack depth measure */
+    } h;
+} header;
+
+/*
+       alloca( size ) returns a pointer to at least `size' bytes of
+       storage which will be automatically reclaimed upon exit from
+       the procedure that called alloca().  Originally, this space
+       was supposed to be taken from the current stack frame of the
+       caller, but that method cannot be made to work for some
+       implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size)                  /* returns pointer to storage */
+     unsigned  size;           /* # bytes to allocate */
+{
+  auto char    probe;          /* probes stack depth: */
+  register char        *depth = &probe;
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)          /* unknown growth direction */
+    find_stack_direction ();
+#endif
+
+                               /* Reclaim garbage, defined as all alloca()ed storage that
+                                  was allocated from deeper in the stack than currently. */
+
+  {
+    register header    *hp;    /* traverses linked list */
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if (STACK_DIR > 0 && hp->h.deep > depth
+         || STACK_DIR < 0 && hp->h.deep < depth)
+       {
+         register header       *np = hp->h.next;
+
+         free ((pointer) hp);  /* collect garbage */
+
+         hp = np;              /* -> next header */
+       }
+      else
+       break;                  /* rest are not deeper */
+
+    last_alloca_header = hp;   /* -> last valid storage */
+  }
+
+  if (size == 0)
+    return NULL;               /* no allocation required */
+
+  /* Allocate combined header + user data storage. */
+
+  {
+    register pointer   new = xmalloc (sizeof (header) + size);
+    /* address of header */
+
+    ((header *)new)->h.next = last_alloca_header;
+    ((header *)new)->h.deep = depth;
+
+    last_alloca_header = (header *)new;
+
+    /* User storage begins just after header. */
+
+    return (pointer)((char *)new + sizeof(header));
+  }
+}
+
diff --git a/binutils/ar.c b/binutils/ar.c
new file mode 100644 (file)
index 0000000..9a8a528
--- /dev/null
@@ -0,0 +1,850 @@
+
+
+
+/* ar.c - Archive modify and extract. */
+/*
+   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 "sysdep.h"
+#include "bfd.h"
+#include "ar.h"
+#include <stdio.h>
+#include <sys/time.h>
+#include <errno.h>
+#define BUFSIZE 8192
+/* Not great to have these here.  Should they be exported or not? */
+PROTO(size_t, bfd_read, (void *ptr, size_t size, size_t nitems, bfd * abfd));
+PROTO(size_t, bfd_write, (void *ptr, size_t size, size_t nitems, bfd * abfd));
+/* PROTO (void, open_inarch, (char *archive_filename)); */
+#ifdef __STDC__
+static void     open_inarch(char *archive_filename);
+#else
+static void     open_inarch();
+#endif                         /* __STDC__ */
+
+PROTO(void, map_over_members, (void (*function) (), char **files, int count));
+PROTO(void, print_contents, (bfd * member));
+PROTO(void, extract_file, (bfd * abfd));
+PROTO(void, delete_members, (char **files_to_delete));
+PROTO(void, do_quick_append, (char *archive_filename, char **files_to_append));
+PROTO(void, move_members, (char **files_to_move));
+PROTO(void, replace_members, (char **files_to_replace));
+PROTO(void, print_descr, (bfd * abfd));
+PROTO(void, ranlib_only, (char *archname));
+
+/** Globals and flags */
+
+char           *program_name = NULL;
+bfd             bogus_archive;
+bfd            *inarch;                /* The input arch we're manipulating */
+
+/* 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;
+/* write a __.SYMDEF member into the modified archive.  */
+boolean         write_armap = false;
+/*
+   Nonzero means don't update __.SYMDEF unless command line explicitly
+   requested it
+*/
+int             ignore_symdef = 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;
+
+/*
+   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;
+    char           *temp;
+    program_name = argv[0];
+
+
+    temp = strrchr(program_name, '/');
+    if (temp == (char *) NULL)
+       temp = program_name;    /* shouldn't happen, but... */
+    else
+       ++temp;
+    if (!strcmp(temp, "ranlib")) {
+       if (argc < 2)
+           fatal("Too few command arguments.");
+       ranlib_only(argv[1]);
+    }
+
+
+    if (argc < 3)
+       fatal("Too few command arguments.");
+
+    arg_ptr = argv[1];
+
+    if (*arg_ptr == '-')
+       ++arg_ptr;              /* compatibility */
+
+    while (c = *arg_ptr++) {
+       switch (c) {
+       case 'd':
+       case 'm':
+       case 'p':
+       case 'q':
+       case 'r':
+       case 't':
+       case 'x':
+           if (operation != none)
+               fatal("two different operation switches specified");
+           switch (c) {
+           case 'd':
+               operation = delete;
+               break;
+           case 'm':
+               operation = move;
+               break;
+           case 'p':
+               operation = print_files;
+               break;
+           case 'q':
+               operation = quick_append;
+               break;
+           case 'r':
+               operation = replace;
+               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 's':
+           write_armap = true;
+           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;
+       default:
+           fatal("invalid option %c", c);
+       }
+    }
+
+    if (operation == none && write_armap)
+       ranlib_only(argv[2]);
+
+    if (operation == none)
+       fatal("no operation specified");
+
+    if (newer_only && operation != replace)
+       fatal("'u' only meaningful with 'r' option.");
+
+    arg_index = 2;
+
+    if (postype != pos_default)
+       posname = argv[arg_index++];
+
+    inarch_filename = argv[arg_index++];
+
+    if (arg_index < argc) {
+       files = argv + arg_index;
+       while (arg_index < argc)
+           if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
+               ignore_symdef = 1;
+               break;
+           }
+    }
+    else
+       files = NULL;
+
+    if (operation == quick_append) {
+       if (files != NULL)
+           do_quick_append(inarch_filename, files);
+       exit(0);
+    }
+
+
+    open_inarch(inarch_filename);
+    /*
+       If we have no archive, and we've been asked to replace then create one
+    */
+
+    if (operation == replace &&
+       inarch == &bogus_archive) {
+       silent_create = 1;
+       do_quick_append(inarch_filename, 0);
+       open_inarch(inarch_filename);
+    }
+
+    switch (operation) {
+
+    case print_table:
+       map_over_members(print_descr, files, argc - 3);
+       break;
+
+    case print_files:
+       map_over_members(print_contents, files, argc - 3);
+       break;
+
+    case extract:
+       map_over_members(extract_file, files, argc - 3);
+       break;
+
+    case delete:
+       if (files != NULL)
+           delete_members(files);
+       break;
+
+    case move:
+       if (files != NULL)
+           move_members(files);
+       break;
+
+    case replace:
+       if (files != NULL || write_armap)
+           replace_members(files);
+       break;
+
+       /* Shouldn't happen! */
+    default:
+       fprintf(stderr, "Sorry; this option not implemented.\n");
+    }
+
+    return (0);
+}                              /* main() */
+
+static
+char *normalize(file)
+char *file;
+{
+    char *    filename = strrchr(file, '/');
+    if (filename != (char *)NULL) {
+       filename ++;
+    }
+    else {
+       filename = file;
+    }
+    return filename;
+}
+
+static void
+open_inarch(archive_filename)
+    char           *archive_filename;
+{
+    bfd           **last_one;
+    bfd            *next_one;
+    struct stat     sbuf;
+    bfd_error = no_error;
+    if (stat(archive_filename, &sbuf) != 0) {
+       if (errno != ENOENT)
+           bfd_fatal(archive_filename);
+       if (!silent_create)
+           fprintf(stderr,
+                   "%s: creating %s\n", program_name, archive_filename);
+
+       inarch = &bogus_archive;
+       inarch->filename = archive_filename;
+       inarch->has_armap = true;
+
+    }
+    else {
+       inarch = bfd_openr(archive_filename, NULL);
+       if (inarch == NULL) {
+    bloser:
+           bfd_perror(archive_filename);
+           exit(1);
+       }
+
+       if (bfd_check_format(inarch, bfd_archive) != true)
+           fatal("File %s is not an archive.", archive_filename);
+       last_one = &(inarch->next);
+       /* Read all the contents right away, regardless. */
+       for (next_one = bfd_openr_next_archived_file(inarch, NULL);
+            next_one;
+            next_one = bfd_openr_next_archived_file(inarch, next_one)) {
+           *last_one = next_one;
+           last_one = &next_one->next;
+       }
+       *last_one = (bfd *) NULL;
+       if (bfd_error != no_more_archived_files)
+           goto bloser;
+    }
+}
+
+
+
+/*
+   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
+*/
+void
+map_over_members(function, files, count)
+    void            (*function) ();
+    char          **files;
+    int             count;
+{
+    bfd            *head;
+
+
+
+
+    if (count == 0) {
+       for (head = inarch->next; head; head = head->next)
+           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 = inarch->next; head; head = head->next)
+           if ((head->filename != NULL) &&
+               (!strcmp(*files, head->filename))) {
+               found = true;
+               function(head);
+           }
+       if (!found)
+           fprintf(stderr, "No entry %s in archive.\n", *files);
+    }
+}
+
+
+/* Things which are interesting to map over all or some of the files: */
+
+void
+print_descr(abfd)
+    bfd            *abfd;
+{
+    print_arelt_descr(abfd, verbose);
+}
+
+void
+print_contents(abfd)
+    bfd            *abfd;
+{
+    int             ncopied = 0;
+    struct stat     buf;
+    long            size;
+    if (bfd_stat_arch_elt(abfd, &buf) != 0)
+       fatal("Internal stat error on %s", abfd->filename);
+
+    if (verbose)
+       printf("\n<member %s>\n\n", abfd->filename);
+
+    bfd_seek(abfd, 0, SEEK_SET);
+
+    size = buf.st_size;
+    while (ncopied < size) {
+       char            cbuf[BUFSIZE];
+       int             nread;
+       int             tocopy = size - ncopied;
+       if (tocopy > BUFSIZE)
+           tocopy = BUFSIZE;
+
+       nread = bfd_read(cbuf, 1, tocopy, abfd);        /* oops -- broke
+                                                          abstraction!  */
+
+       if (nread != tocopy)
+           fatal("file %s not a valid archive", abfd->my_archive->filename);
+       fwrite(cbuf, 1, nread, stdout);
+       ncopied += tocopy;
+    }
+}
+
+
+/*
+   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[BUFSIZE];
+    int             nread,
+                    tocopy;
+    int             ncopied = 0;
+    long            size;
+    struct stat     buf;
+    if (bfd_stat_arch_elt(abfd, &buf) != 0)
+       fatal("Internal stat error on %s", abfd->filename);
+    size = buf.st_size;
+
+    if (verbose)
+       printf("x - %s\n", abfd->filename);
+
+    bfd_seek(abfd, 0, SEEK_SET);
+
+    ostream = 0;
+    while (ncopied < size) {
+       tocopy = size - ncopied;
+       if (tocopy > BUFSIZE)
+           tocopy = BUFSIZE;
+
+       nread = bfd_read(cbuf, 1, tocopy, abfd);
+       if (nread != tocopy)
+           fatal("file %s not a valid archive", abfd->my_archive->filename);
+
+       /* See comment above; this saves disk arm motion */
+       if (!ostream) {
+           /* Seems like an abstraction violation, eh?  Well it's OK! */
+           ostream = fopen(abfd->filename, "w");
+           if (!ostream) {
+               perror(abfd->filename);
+               exit(1);
+           }
+       }
+       /* no need to byte-swap; the two formats are presumably compatible(!) */
+       fwrite(cbuf, 1, nread, ostream);
+       ncopied += tocopy;
+    }
+
+    fclose(ostream);
+    chmod(abfd->filename, buf.st_mode);
+
+    if (preserve_dates) {
+#ifdef USG
+       long            tb[2];
+       tb[0] = buf.st_mtime;
+       tb[1] = buf.st_mtime;
+       utime(abfd->filename, tb);      /* FIXME check result */
+#else
+       struct timeval  tv[2];
+       tv[0].tv_sec = buf.st_mtime;
+       tv[0].tv_usec = 0;
+       tv[1].tv_sec = buf.st_mtime;
+       tv[1].tv_usec = 0;
+       utimes(abfd->filename, tv);     /* FIXME check result */
+#endif
+    }
+}
+
+
+/* Just do it quickly; don't worry about dups, armap, or anything like that */
+
+/* This is ugly! XXX */
+
+PROTO(struct ar_hdr *, bfd_special_undocumented_glue, (char *filename));
+
+void
+do_quick_append(archive_filename, files_to_append)
+    char           *archive_filename;
+    char          **files_to_append;
+
+{
+    FILE           *ofile,
+                   *ifile;
+    char            buf[BUFSIZE];
+    long            tocopy,
+                    thistime;
+    bfd            *temp;
+    struct stat     sbuf;
+    boolean         newfile = false;
+    bfd_error = no_error;
+
+    if (stat(archive_filename, &sbuf) != 0) {
+       if (errno != ENOENT)
+           bfd_fatal(archive_filename);
+       newfile = true;
+    }
+
+
+    ofile = fopen(archive_filename, "a+");
+    if (ofile == NULL) {
+       perror(program_name);
+       exit(1);
+    }
+
+    /* bletch */
+    temp = bfd_openr(archive_filename, NULL);
+    if (temp == NULL) {
+       bfd_perror(archive_filename);
+       exit(1);
+    }
+    if (newfile == false) {
+       if (bfd_check_format(temp, bfd_archive) != true)
+           fatal("File %s is not an archive.", archive_filename);
+    }
+    else {
+       fwrite(ARMAG, 1, SARMAG, ofile);
+       if (!silent_create)
+           fprintf(stderr, "%s: creating %s\n", program_name, archive_filename);
+    }
+
+    /* 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(*files_to_append);
+       if (hdr == NULL) {
+           bfd_perror(*files_to_append);
+           exit(1);
+       }
+
+       BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
+
+       ifile = fopen(*files_to_append, "r");
+       if (ifile == NULL)
+           bfd_perror(program_name);
+
+       if (stat(*files_to_append, &sbuf) != 0)
+           bfd_perror(*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('\n', ofile);
+    }
+    fclose(ofile);
+    bfd_close(temp);
+}
+
+
+void
+write_archive()
+{
+    bfd            *obfd;
+    char           *xmalloc();
+    int             namelen = strlen(inarch->filename);
+    char           *new_name = xmalloc(namelen + 6);
+    bfd            *contents_head = inarch->next;
+    if (inarch == &bogus_archive) {
+       /* How can this be ? */
+       return;
+    }
+    else {
+
+       strcpy(new_name, inarch->filename);
+       strcpy(new_name + namelen, ".art");
+       obfd = bfd_openw(new_name, bfd_get_target(inarch));
+
+       if (obfd == NULL)
+           bfd_fatal(inarch->filename);
+
+       bfd_set_format(obfd, bfd_archive);
+       obfd->has_armap = write_armap;
+
+       if (bfd_set_archive_head(obfd, contents_head) != true)
+           bfd_fatal(inarch->filename);
+
+       if (!bfd_close(obfd))
+           bfd_fatal(inarch->filename);
+       if (rename(new_name, inarch->filename) != 0)
+           bfd_fatal(inarch->filename);
+    }
+}
+
+
+
+/*
+   returns 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.
+*/
+
+bfd **
+get_pos_bfd(contents, default_pos)
+    bfd           **contents;
+    enum pos        default_pos;
+{
+    bfd           **after_bfd;
+
+    enum pos        realpos = (postype == pos_default ? default_pos : postype);
+    switch (realpos) {
+
+    case pos_end:
+       after_bfd = contents;
+       while (*after_bfd) {
+           after_bfd = &((*after_bfd)->next);
+       }
+
+       break;
+#if 0
+    case pos_after:
+       for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
+           if (!strcpy(after_bfd->filename, posname))
+               break;
+       break;
+    case pos_before:
+       for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
+           if (after_bfd->next && (!strcpy(after_bfd->next->filename, posname)))
+               break;
+#endif
+    }
+
+    return after_bfd;
+}
+
+
+void
+delete_members(files_to_delete)
+    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. The name is NULL in COFF archives, so using this as a
+          key is as good as anything I suppose
+       */
+       if (!strcmp(*files_to_delete, "__.SYMDEF")) {
+           inarch->has_armap = false;
+           write_armap = false;
+           continue;
+       }
+
+       found = false;
+       current_ptr_ptr = &(inarch->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) {
+           printf("No member named `%s'\n", *files_to_delete);
+       }
+next_file:;
+
+    }
+
+    if (something_changed == true) {
+       write_archive();
+    }
+}
+
+
+/* Reposition existing members within an archive */
+
+void
+move_members(files_to_move)
+    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 = &(inarch->next);
+       while (*current_ptr_ptr) {
+           bfd            *current_ptr = *current_ptr_ptr;
+           if (strcmp(normalize(*files_to_move), current_ptr->filename) == 0) {
+               /*
+                  Move this file to the end of the list - first cut from
+                  where it is.
+               */
+               *current_ptr_ptr = current_ptr->next;
+
+               /* Now glue to end */
+               after_bfd = get_pos_bfd(&inarch->next, pos_end);
+               *after_bfd = current_ptr;
+               current_ptr->next = (bfd *) NULL;
+
+               if (verbose)
+                   printf("m - %s\n", *files_to_move);
+
+               goto next_file;
+           }
+           current_ptr_ptr = &((*current_ptr_ptr)->next);
+       }
+       fprintf(stderr, "No entry %s in archive %s!\n",
+               *files_to_move, inarch->filename);
+       exit(1);
+next_file:;
+    }
+
+    write_archive();
+}
+
+
+/* Ought to default to replacing in place, but this is existing practice! */
+
+void
+replace_members(files_to_move)
+    char          **files_to_move;
+{
+    bfd           **after_bfd; /* New entries go after this one */
+    bfd            *current;
+    bfd           **current_ptr;
+    bfd            *temp;
+    /*
+       If the first item in the archive is an __.SYMDEF then remove it
+    */
+    if (inarch->next &&
+       strcmp(inarch->next->filename, "__.SYMDEF") == 0) {
+       inarch->next = inarch->next->next;
+    }
+
+
+
+    while (files_to_move && *files_to_move) {
+       current_ptr = &inarch->next;
+       while (*current_ptr) {
+           current = *current_ptr;
+           
+           if (!strcmp(normalize(*files_to_move), current->filename)) {
+               /* snip out this entry from the chain */
+               *current_ptr = current->next;
+               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)
+                       fatal("Internal stat error on %s", current->filename);
+
+                   if (fsbuf.st_mtime <= asbuf.st_mtime)
+                       goto next_file;
+               }
+
+
+               after_bfd = get_pos_bfd(&inarch->next, pos_end);
+               temp = *after_bfd;
+               *after_bfd = bfd_openr(*files_to_move, NULL);
+               if (*after_bfd == (bfd *) NULL) {
+                   fprintf(stderr, "Can't open file %s\n", *files_to_move);
+                   exit(1);
+               }
+               (*after_bfd)->next = temp;
+
+               if (verbose) {
+                   printf("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
+                          *files_to_move);
+               }
+               goto next_file;
+           }
+           current_ptr = &(current->next);
+       }
+
+       /* It isn't in there, so add to end */
+
+       after_bfd = get_pos_bfd(&inarch->next, pos_end);
+       temp = *after_bfd;
+       *after_bfd = bfd_openr(*files_to_move, NULL);
+       if (*after_bfd == (bfd *) NULL) {
+           fprintf(stderr, "Can't open file %s\n", *files_to_move);
+           exit(1);
+       }
+       if (verbose) {
+           printf("c - %s\n", *files_to_move);
+       }
+
+       (*after_bfd)->next = temp;
+
+next_file:;
+
+       files_to_move++;
+    }
+
+
+    write_archive();
+}
+
+void
+ranlib_only(archname)
+    char           *archname;
+{
+    write_armap = true;
+    open_inarch(archname);
+    write_archive();
+    exit(0);
+}
diff --git a/binutils/bucomm.c b/binutils/bucomm.c
new file mode 100644 (file)
index 0000000..00f379f
--- /dev/null
@@ -0,0 +1,151 @@
+/*** bucomm.c -- Bin Utils COMmon code.
+
+     We might put this in a library someday so it could be dynamically
+     loaded, but for now it's not necessary */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include <varargs.h>
+
+char *target = NULL;           /* default as late as possible */
+
+/* Yes, this is what atexit is for, but that isn't guaranteed yet.
+   And yes, I know this isn't as good, but it does what is needed just fine */
+void (*exit_handler) ();
+\f
+/** Memory hackery */
+
+PROTO (char *, malloc, (unsigned size));
+PROTO (char *, realloc, (char *ptr, unsigned size));
+
+\f
+/* Error reporting */
+
+char *program_name;
+
+void
+bfd_fatal (string)
+     char *string;
+{
+  char *errmsg =  bfd_errmsg (bfd_error);
+  
+  if (string)
+    fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
+  else
+    fprintf (stderr, "%s: %s\n", program_name, errmsg);
+
+  if (NULL != exit_handler) (*exit_handler) ();
+  exit (1);
+}
+
+#ifndef NO_STDARG
+void
+fatal (Format)
+     const char *Format;
+{
+  va_list args;
+       
+  va_start (args, Format);
+  vfprintf (stderr, Format, args);
+  va_end (args);
+  (void) putc ('\n', stderr);
+  if (NULL != exit_handler) (*exit_handler) ();
+  exit (1);
+}
+#else
+#ifndef NO_VARARGS
+void fatal (va_alist)
+     va_dcl
+{
+       char *Format;
+       va_list args;
+       
+       va_start (args);
+       Format = va_arg(args, char *);
+       vfprintf (stderr, Format, args);
+       va_end (args);
+       (void) putc ('\n', stderr);
+       if (NULL != exit_handler) (*exit_handler) ();
+       exit (1);
+} /* fatal() */
+#else
+/*VARARGS1 */
+fatal (Format, args)
+     char *Format;
+{
+  as_where ();
+  _doprnt (Format, &args, stderr); /* not terribly portable, but... */
+  (void) putc ('\n', stderr);
+  if (NULL != exit_handler) (*exit_handler) ();
+  exit (1);
+}
+#endif /* not NO_VARARGS */
+#endif /* not NO_STDARG */
+
+\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 (abfd, verbose)
+     bfd *abfd;
+     boolean verbose;
+{
+  struct stat buf;
+  char modebuf[11];
+  char timebuf[40];
+  long when;
+  long current_time = time ((long *) 0);
+
+  if (verbose) {
+
+    if (bfd_stat_arch_elt (abfd, &buf) == 0) { /* if not, huh? */
+
+      mode_string (buf.st_mode, modebuf);
+      modebuf[10] = '\0';
+      fputs (modebuf, stdout);
+
+      when = buf.st_mtime;
+      strcpy (timebuf, ctime (&when));
+
+      /* This code comes from gnu ls.  */
+      if ((current_time - when > 6 * 30 * 24 * 60 * 60)
+         || (current_time - when < 0)) {
+       /* The file is fairly old or in the future.
+          POSIX says the cutoff is 6 months old;
+          approximate this by 6*30 days.
+          Show the year instead of the time of day.  */
+       strcpy (timebuf + 11, timebuf + 19);
+      }
+      timebuf[16] = 0;
+
+      printf (" %d\t%d\t%ld\t%s ", buf.st_uid, buf.st_gid, buf.st_size, timebuf);
+    }
+  }
+
+  puts (abfd->filename);
+}
+
+/* Like malloc but get fatal error if memory is exhausted.  */
+char *
+xmalloc (size)
+     unsigned size;
+{
+  register char *result = malloc (size);
+  if (result == NULL && size != NULL) fatal ("virtual memory exhausted");
+
+  return result;
+}
+
+/* Like realloc but get fatal error if memory is exhausted.  */
+char *
+xrealloc (ptr, size)
+     char *ptr;
+     unsigned size;
+{
+  register char *result = realloc (ptr, size);
+  if (result == 0 && size != 0) fatal ("virtual memory exhausted");
+
+  return result;
+}
diff --git a/binutils/copy.c b/binutils/copy.c
new file mode 100644 (file)
index 0000000..91b5f26
--- /dev/null
@@ -0,0 +1,414 @@
+/*** copy.c -- copy object file from input to output, optionally massaging it */
+#include "sysdep.h"
+#include "bfd.h"
+
+asymbol       **sympp;
+char           *input_target = NULL;
+char           *output_target = NULL;
+char           *input_filename = NULL;
+char           *output_filename = NULL;
+
+
+static void     setup_sections();
+static void     copy_sections();
+static boolean  strip;
+static boolean verbose;
+
+/* IMPORTS */
+extern char    *program_name;
+extern char *xmalloc();
+
+static
+void            
+usage()
+{
+    fprintf(stderr,
+    "Usage %s [-S][-s srcfmt] [-d dtfmt] [-b bothfmts] infile [outfile]\n",
+           program_name);
+    exit(1);
+}
+
+
+/* Create a temp file in the same directory as supplied */
+static
+char *
+make_tempname(filename)
+char *filename;
+{
+    static char template[] = "stXXXXXX";
+    char *tmpname;
+    char *      slash = strrchr( filename, '/' );
+    if (slash != (char *)NULL){
+       *slash = 0;
+       tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
+       strcpy(tmpname, filename);
+       strcat(tmpname, "/" );
+       strcat(tmpname, template);
+       mktemp(tmpname );
+       *slash = '/';
+    } else {
+       tmpname = xmalloc(sizeof(template));
+       strcpy(tmpname, template);
+       mktemp(tmpname);
+    }
+    return tmpname;
+}
+
+/*
+   All the symbols have been read in and point to their owning input section.
+   They have been relocated to that they are all relative to the base of
+   their owning section. On the way out, all the symbols will be relocated to
+   their new location in the output file, through some complex sums.
+
+*/
+static void
+mangle_sections(ibfd, obfd)
+    bfd            *ibfd;
+    bfd            *obfd;
+{
+    asection       *current = ibfd->sections;
+    for (; current != NULL; current = current->next) {
+       current->output_section = bfd_get_section_by_name(obfd, current->name);
+       current->output_offset = 0;
+    }
+}
+
+static 
+void
+copy_object(ibfd, obfd)
+bfd *ibfd;
+bfd *obfd;
+{
+
+    unsigned int symcount;
+
+
+    if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
+       bfd_fatal(output_filename);
+
+
+    if (verbose)
+       printf("copy from %s(%s) to %s(%s)\n",
+              ibfd->filename, ibfd->xvec->name,
+              obfd->filename, obfd->xvec->name);
+
+    if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false) ||
+       (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
+                                  ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS | D_PAGED |
+                                    HAS_LOCALS))) == false) ||
+       bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
+       bfd_fatal(bfd_get_filename(ibfd));
+
+    /* Copy architecture of input file to output file */
+    if (!bfd_set_arch_mach(obfd, bfd_get_architecture(ibfd),
+                          bfd_get_machine(ibfd))) {
+       fprintf(stderr, "Output file cannot represent architecture %s\n",
+               bfd_printable_arch_mach(bfd_get_architecture(ibfd),
+                                       bfd_get_machine(ibfd)));
+    }
+    if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
+       {
+           bfd_fatal(ibfd->filename);
+       }
+
+    sympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
+    symcount = bfd_canonicalize_symtab(ibfd, sympp);
+
+    bfd_set_symtab(obfd, sympp, strip == true ? 0 : symcount);
+    
+    /*
+      bfd mandates that all output sections be created and sizes set before
+      any output is done.  Thus, we traverse all sections twice.
+      */
+    bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
+    bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
+    mangle_sections(ibfd, obfd);
+}
+static
+char *
+cat(a,b,c)
+char *a;
+char *b;
+char *c;
+{
+    int size = strlen(a) + strlen(b) + strlen(c);
+    char *r = xmalloc(size+1);
+    strcpy(r,a);
+    strcat(r,b);
+    strcat(r,c);
+    return r;
+}
+
+static void 
+copy_archive(ibfd, obfd)
+bfd *ibfd;
+bfd *obfd;
+{
+    bfd **ptr =&( obfd->archive_head);
+    bfd *this_element;
+    /* Read each archive element in turn from the input, copy the
+       contents to a temp file, and keep the temp file handle */
+    char *dir = cat("./",make_tempname(""),"copy-dir");
+
+    /* Make a temp directory to hold the contents */
+    mkdir(dir,0777);
+    obfd->has_armap = ibfd->has_armap;
+    this_element = bfd_openr_next_archived_file(ibfd, NULL);
+    while (this_element != (bfd *)NULL) {
+
+       /* Create an output file for this member */
+       char *output_name = cat(dir, "/",this_element->filename);
+       bfd *output_bfd = bfd_openw(output_name, output_target);
+       
+       if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
+           bfd_fatal(output_filename);
+
+       if (output_bfd == (bfd *)NULL) {
+           bfd_fatal(output_name);
+       }
+       if (bfd_check_format(this_element, bfd_object) == true) {
+           copy_object(this_element, output_bfd);
+       }
+
+       bfd_close(output_bfd);
+       /* Now open the newly output file and attatch to our list */
+       output_bfd = bfd_openr(output_name, output_target);
+       /* Mark it for deletion */
+
+       *ptr = output_bfd;
+
+       ptr =&( output_bfd->next);
+       this_element = bfd_openr_next_archived_file(ibfd, this_element);
+
+    }
+    *ptr = (bfd *)NULL;
+
+    if (!bfd_close(obfd))
+       bfd_fatal(output_filename);
+
+    /* Now delete all the files that we opened 
+      We can't use the names in the obfd list since they may have been
+      trampled by the archive output code
+      */
+    for (this_element = ibfd->archive_head;
+        this_element != (bfd *)NULL;
+        this_element = this_element->next) 
+       {
+       unlink(cat(dir,"/",this_element->filename));
+    }
+    unlink(dir);
+    if (!bfd_close(ibfd))
+       bfd_fatal(input_filename);
+
+}
+
+static
+void
+copy_file(input_filename, output_filename)
+    char           *input_filename;
+    char           *output_filename;
+{
+  bfd            *ibfd;
+
+  ibfd = bfd_openr(input_filename, input_target);
+  if (ibfd == NULL)
+    bfd_fatal(input_filename);
+
+  if (bfd_check_format(ibfd, bfd_object)) {
+    bfd * obfd = bfd_openw(output_filename, output_target);
+    if (obfd == NULL)
+      bfd_fatal(output_filename);
+
+    copy_object(ibfd, obfd);
+
+    if (!bfd_close(obfd))
+      bfd_fatal(output_filename);
+
+    if (!bfd_close(ibfd))
+      bfd_fatal(input_filename);
+  }
+  else if (bfd_check_format(ibfd, bfd_archive)) {
+    bfd * obfd = bfd_openw(output_filename, output_target);
+    if (obfd == NULL)
+      bfd_fatal(output_filename);
+    copy_archive(ibfd, obfd);
+  }
+}
+
+
+
+/** Actually do the work */
+static void
+setup_sections(ibfd, isection, obfd)
+    bfd            *ibfd;
+    sec_ptr         isection;
+    bfd            *obfd;
+{
+    sec_ptr         osection;
+    char           *err;
+    osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
+    if (osection == NULL) {
+       err = "making";
+       goto loser;
+    }
+
+    if (!bfd_set_section_size(obfd,
+                             osection,
+                             bfd_section_size(ibfd, isection))) {
+       err = "size";
+       goto loser;
+    }
+
+    if (bfd_set_section_vma(obfd,
+                           osection,
+                           bfd_section_vma(ibfd, isection))
+       == false) {
+       err = "vma";
+       goto loser;
+    }                          /* on error */
+
+    if (bfd_set_section_alignment(obfd,
+                                 osection,
+                                 bfd_section_alignment(ibfd, isection))
+       == false) {
+       err = "alignment";
+       goto loser;
+    }                          /* on error */
+
+    if (!bfd_set_section_flags(obfd, osection,
+                              bfd_get_section_flags(ibfd, isection))) {
+       err = "flags";
+       goto loser;
+    }
+
+    /* All went well */
+    return;
+
+loser:
+    fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
+           program_name,
+           bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
+           err, bfd_errmsg(bfd_error));
+    exit(1);
+}                              /* setup_sections() */
+
+/*
+Copy all the section related data from an input section
+to an output section
+
+If stripping then don't copy any relocation info
+*/
+static void
+copy_sections(ibfd, isection, obfd)
+    bfd            *ibfd;
+    sec_ptr         isection;
+    bfd            *obfd;
+{
+
+  arelent       **relpp;
+  int             relcount;
+  sec_ptr         osection;
+  unsigned long   size;
+  osection = bfd_get_section_by_name(obfd,
+                                    bfd_section_name(ibfd, isection));
+
+  size = bfd_section_size(ibfd, isection);
+
+  if (size == 0)
+    return;
+
+  if (strip == true || get_reloc_upper_bound(ibfd, isection) == 0) 
+    {
+      bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
+    } 
+  else 
+    {
+      relpp = (arelent **) xmalloc(get_reloc_upper_bound(ibfd, isection));
+      relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
+      bfd_set_reloc(obfd, osection, relpp, relcount);
+    }
+
+
+  if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS) 
+    {
+      unsigned char *memhunk = (unsigned char *) xmalloc(size);
+
+      if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size))
+       bfd_fatal(bfd_get_filename(ibfd));
+
+      if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size))
+       bfd_fatal(bfd_get_filename(obfd));
+      free(memhunk);
+    }
+
+
+}
+int
+main(argc, argv)
+    int             argc;
+    char           *argv[];
+{
+  int             i;
+
+  program_name = argv[0];
+
+  if (strcmp(program_name,"strip") == 0) {
+    strip = true;
+  }
+
+  for (i = 1; i < argc; i++) 
+    {
+      if (argv[i][0] == '-') {
+       switch (argv[i][1]) {
+       case 'v':
+         verbose = true;
+         break;
+       case 'b':
+         i++;
+         input_target = output_target = argv[i];
+         break;
+       case 'S':
+         strip = true;
+         break;
+       case 's':
+         i++;
+         input_target = argv[i];
+         break;
+       case 'd':
+         i++;
+         output_target = argv[i];
+         break;
+       default:
+         usage();
+       }
+      }
+      else {
+       if (input_filename) {
+         output_filename = argv[i];
+       }
+       else {
+         input_filename = argv[i];
+       }
+      }
+    }
+
+  if (input_filename == (char *) NULL)
+    usage();
+
+  if (output_target == (char *) NULL)
+    output_target = input_target;
+
+  /* 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);
+    output_filename = input_filename;
+    rename(tmpname, input_filename);
+  }
+  else {
+    copy_file(input_filename, output_filename);
+  }
+    return 1;
+}
diff --git a/binutils/cplus-dem.c b/binutils/cplus-dem.c
new file mode 100644 (file)
index 0000000..4cc6496
--- /dev/null
@@ -0,0 +1,933 @@
+/* Demangler for GNU C++ 
+   Copyright (C) 1989 Free Software Foundation, Inc.
+   written by James Clark (jjc@jclark.uucp)
+   
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is for g++ 1.36.1 (November 6 version). It will probably
+   require changes for any other version.
+
+   Modified for g++ 1.36.2 (November 18 version).  */
+
+/* This file exports one function
+
+   char *cplus_demangle (const char *name)
+   
+   If `name' is a mangled function name produced by g++, then
+   a pointer to a malloced string giving a C++ representation
+   of the name will be returned; otherwise NULL will be returned.
+   It is the caller's responsibility to free the string which
+   is returned.
+
+   For example,
+   
+   cplus_demangle ("_foo__1Ai")
+   
+   returns
+
+   "A::foo(int)"
+
+   This file imports xmalloc and xrealloc, which are like malloc and
+   realloc except that they generate a fatal error if there is no
+   available memory. */
+
+#if 0                          /* Should really be part of BFD */
+#define nounderscore 1         /* define this is names don't start with _ */
+#endif
+#include "sysdep.h"
+
+#include <ctype.h>
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifdef __STDC__
+extern char *cplus_demangle (const char *type);
+#else
+extern char *cplus_demangle ();
+#endif
+
+static char **typevec = 0;
+static int ntypes = 0;
+static int typevec_size = 0;
+
+static struct {
+  const char *in;
+  const char *out;
+} optable[] = {
+  "new", " new",
+  "delete", " delete",
+  "ne", "!=",
+  "eq", "==",
+  "ge", ">=",
+  "gt", ">",
+  "le", "<=",
+  "lt", "<",
+  "plus", "+",
+  "minus", "-",
+  "mult", "*",
+  "convert", "+",      /* unary + */
+  "negate", "-",       /* unary - */
+  "trunc_mod", "%",
+  "trunc_div", "/",
+  "truth_andif", "&&",
+  "truth_orif", "||",
+  "truth_not", "!",
+  "postincrement", "++",
+  "postdecrement", "--",
+  "bit_ior", "|",
+  "bit_xor", "^",
+  "bit_and", "&",
+  "bit_not", "~",
+  "call", "()",
+  "cond", "?:",
+  "alshift", "<<",
+  "arshift", ">>",
+  "component", "->",
+  "indirect", "*",
+  "method_call", "->()",
+  "addr", "&",         /* unary & */
+  "array", "[]",
+  "nop", "",                   /* for operator= */
+};
+
+/* Beware: these aren't '\0' terminated. */
+
+typedef struct {
+  char *b;                     /* pointer to start of string */
+  char *p;                     /* pointer after last character */
+  char *e;                     /* pointer after end of allocated space */
+} string;
+
+#ifdef __STDC__
+static void string_need (string *s, int n);
+static void string_delete (string *s);
+static void string_init (string *s);
+static void string_clear (string *s);
+static int string_empty (string *s);
+static void string_append (string *p, const char *s);
+static void string_appends (string *p, string *s);
+static void string_appendn (string *p, const char *s, int n);
+static void string_prepend (string *p, const char *s);
+#if 0
+static void string_prepends (string *p, string *s);
+#endif
+static void string_prependn (string *p, const char *s, int n);
+static int get_count (const char **type, int *count);
+static int do_args (const char **type, string *decl);
+static int do_type (const char **type, string *result);
+static int do_arg (const char **type, string *result);
+static int do_args (const char **type, string *decl);
+static void munge_function_name (string *name);
+#else
+static void string_need ();
+static void string_delete ();
+static void string_init ();
+static void string_clear ();
+static int string_empty ();
+static void string_append ();
+static void string_appends ();
+static void string_appendn ();
+static void string_prepend ();
+static void string_prepends ();
+static void string_prependn ();
+static int get_count ();
+static int do_args ();
+static int do_type ();
+static int do_arg ();
+static int do_args ();
+static void munge_function_name ();
+#endif
+
+char *
+cplus_demangle (type)
+     const char *type;
+{
+  string decl;
+  int n;
+  int success = 0;
+  int constructor = 0;
+  int const_flag = 0;
+  int i;
+  const char *p, *premangle;
+
+  if (type == NULL || *type == '\0')
+    return NULL;
+#ifndef nounderscore
+  if (*type++ != '_')
+    return NULL;
+#endif
+  p = type;
+  while (*p != '\0' && !(*p == '_' && p[1] == '_'))
+    p++;
+  if (*p == '\0')
+    {
+      /* destructor */
+      if (type[0] == '_' && type[1] == '$' && type[2] == '_')
+       {
+         unsigned int l = (strlen (type) - 3)*2 + 3 + 2 + 1;
+         char *tem = (char *) xmalloc (l);
+         strcpy (tem, type + 3);
+         strcat (tem, "::~");
+         strcat (tem, type + 3);
+         strcat (tem, "()");
+         return tem;
+       }
+      /* static data member */
+      if (*type != '_' && (p = (char *) strchr (type, '$')) != NULL)
+       {
+         int n = strlen (type) + 2;
+         char *tem = (char *) xmalloc (n);
+         memcpy (tem, type, p - type);
+         strcpy (tem + (p - type), "::");
+         strcpy (tem + (p - type) + 2, p + 1);
+         return tem;
+       }
+      /* virtual table */
+      if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
+       {
+         int n = strlen (type + 4) + 14 + 1;
+         char *tem = (char *) xmalloc (n);
+         strcpy (tem, type + 4);
+         strcat (tem, " virtual table");
+         return tem;
+       }
+      return NULL;
+    }
+
+  string_init (&decl);
+
+  if (p == type)
+    {
+      if (!isdigit (p[2]))
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      constructor = 1;
+    }
+  else
+    {
+      string_appendn (&decl, type, p - type);
+      munge_function_name (&decl);
+    }
+  p += 2;
+
+  premangle = p;
+  switch (*p)
+    {
+    case 'C':
+      /* a const member function */
+      if (!isdigit (p[1]))
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      p += 1;
+      const_flag = 1;
+      /* fall through */
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      n = 0;
+      do
+       {
+         n *= 10;
+         n += *p - '0';
+         p += 1;
+       }
+      while (isdigit (*p));
+      if (strlen (p) < n)
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      if (constructor)
+       {
+         string_appendn (&decl, p, n);
+         string_append (&decl, "::");
+         string_appendn (&decl, p, n);
+       }
+      else
+       {
+         string_prepend (&decl, "::");
+         string_prependn (&decl, p, n);
+       }
+#ifndef LONGERNAMES
+      p = premangle;
+#else
+      p += n;
+#endif
+      success = do_args (&p, &decl);
+      if (const_flag)
+       string_append (&decl, " const");
+      break;
+    case 'F':
+      p += 1;
+      success = do_args (&p, &decl);
+      break;
+    }
+
+  for (i = 0; i < ntypes; i++)
+    if (typevec[i] != NULL)
+      free (typevec[i]);
+  ntypes = 0;
+  if (typevec != NULL)
+    {
+      free ((char *)typevec);
+      typevec = NULL;
+      typevec_size = 0;
+    }
+
+  if (success)
+    {
+      string_appendn (&decl, "", 1);
+      return decl.b;
+    }
+  else
+    {
+      string_delete (&decl);
+      return NULL;
+    }
+}
+
+static int
+get_count (type, count)
+     const char **type;
+     int *count;
+{
+  if (!isdigit (**type))
+    return 0;
+  *count = **type - '0';
+  *type += 1;
+  /* see flush_repeats in cplus-method.c */
+  if (isdigit (**type))
+    {
+      const char *p = *type;
+      int n = *count;
+      do 
+       {
+         n *= 10;
+         n += *p - '0';
+         p += 1;
+       } 
+      while (isdigit (*p));
+      if (*p == '_')
+       {
+         *type = p + 1;
+         *count = n;
+       }
+    }
+  return 1;
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (type, result)
+     const char **type;
+     string *result;
+{
+  int n;
+  int done;
+  int non_empty = 0;
+  int success;
+  string decl;
+  const char *remembered_type;
+
+  string_init (&decl);
+  string_init (result);
+
+  done = 0;
+  success = 1;
+  while (success && !done)
+    {
+      int member;
+      switch (**type)
+       {
+       case 'P':
+         *type += 1;
+         string_prepend (&decl, "*");
+         break;
+
+       case 'R':
+         *type += 1;
+         string_prepend (&decl, "&");
+         break;
+
+       case 'T':
+         *type += 1;
+         if (!get_count (type, &n) || n >= ntypes)
+           success = 0;
+         else
+           {
+             remembered_type = typevec[n];
+             type = &remembered_type;
+           }
+         break;
+
+       case 'F':
+         *type += 1;
+         if (!string_empty (&decl) && decl.b[0] == '*')
+           {
+             string_prepend (&decl, "(");
+             string_append (&decl, ")");
+           }
+         if (!do_args (type, &decl) || **type != '_')
+           success = 0;
+         else
+           *type += 1;
+         break;
+
+       case 'M':
+       case 'O':
+         {
+           int constp = 0;
+           int volatilep = 0;
+
+           member = **type == 'M';
+           *type += 1;
+           if (!isdigit (**type))
+             {
+               success = 0;
+               break;
+             }
+           n = 0;
+           do
+             {
+               n *= 10;
+               n += **type - '0';
+               *type += 1;
+             } 
+           while (isdigit (**type));
+           if (strlen (*type) < n)
+             {
+               success = 0;
+               break;
+             }
+           string_append (&decl, ")");
+           string_prepend (&decl, "::");
+           string_prependn (&decl, *type, n);
+           string_prepend (&decl, "(");
+           *type += n;
+           if (member)
+             {
+               if (**type == 'C')
+                 {
+                   *type += 1;
+                   constp = 1;
+                 }
+               if (**type == 'V')
+                 {
+                   *type += 1;
+                   volatilep = 1;
+                 }
+               if (*(*type)++ != 'F')
+                 {
+                   success = 0;
+                   break;
+                 }
+             }
+           if ((member && !do_args (type, &decl)) || **type != '_')
+             {
+               success = 0;
+               break;
+             }
+           *type += 1;
+           if (constp)
+             {
+               if (non_empty)
+                 string_append (&decl, " ");
+               else
+                 non_empty = 1;
+               string_append (&decl, "const");
+             }
+           if (volatilep)
+             {
+               if (non_empty)
+                 string_append (&decl, " ");
+               else
+                 non_empty = 1;
+               string_append (&decl, "volatilep");
+             }
+           break;
+         }
+
+       case 'C':
+         if ((*type)[1] == 'P')
+           {
+             *type += 1;
+             if (!string_empty (&decl))
+               string_prepend (&decl, " ");
+             string_prepend (&decl, "const");
+             break;
+           }
+
+         /* fall through */
+       default:
+         done = 1;
+         break;
+       }
+    }
+
+  done = 0;
+  non_empty = 0;
+  while (success && !done)
+    {
+      switch (**type)
+       {
+       case 'C':
+         *type += 1;
+         if (non_empty)
+           string_append (result, " ");
+         else
+           non_empty = 1;
+         string_append (result, "const");
+         break;
+       case 'U':
+         *type += 1;
+         if (non_empty)
+           string_append (result, " ");
+         else
+           non_empty = 1;
+         string_append (result, "unsigned");
+         break;
+       case 'V':
+         *type += 1;
+         if (non_empty)
+           string_append (result, " ");
+         else
+           non_empty = 1;
+         string_append (result, "volatile");
+         break;
+       default:
+         done = 1;
+         break;
+       }
+    }
+
+  if (success)
+    switch (**type)
+      {
+      case '\0':
+      case '_':
+       break;
+      case 'v':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "void");
+       break;
+      case 'l':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "long");
+       break;
+      case 'i':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "int");
+       break;
+      case 's':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "short");
+       break;
+      case 'c':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "char");
+       break;
+      case 'r':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "long double");
+       break;
+      case 'd':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "double");
+       break;
+      case 'f':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "float");
+       break;
+      case 'G':
+       *type += 1;
+       if (!isdigit (**type))
+         {
+           success = 0;
+           break;
+         }
+       /* fall through */
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+       n = 0;
+       do
+         {
+           n *= 10;
+           n += **type - '0';
+           *type += 1;
+         }
+       while (isdigit (**type));
+       if (strlen (*type) < n)
+         {
+           success = 0;
+           break;
+         }
+       if (non_empty)
+         string_append (result, " ");
+       string_appendn (result, *type, n);
+       *type += n;
+       break;
+      default:
+       success = 0;
+       break;
+      }
+
+  if (success)
+    {
+      if (!string_empty (&decl))
+       {
+         string_append (result, " ");
+         string_appends (result, &decl);
+       }
+      string_delete (&decl);
+      return 1;
+    }
+  else
+    {
+      string_delete (&decl);
+      string_delete (result);
+      return 0;
+    }
+}
+
+/* `result' will be initialised in do_type; it will be freed on failure */
+
+static int
+do_arg (type, result)
+     const char **type;
+     string *result;
+{
+  char *tem;
+  int len;
+  const char *start;
+  const char *end;
+
+  start = *type;
+  if (!do_type (type, result))
+    return 0;
+  end = *type;
+  if (ntypes >= typevec_size)
+    {
+      if (typevec_size == 0)
+       {
+         typevec_size = 3;
+         typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
+       }
+      else
+       {
+         typevec_size *= 2;
+         typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
+       }
+    }
+  len = end - start;
+  tem = (char *) xmalloc (len + 1);
+  memcpy (tem, start, len);
+  tem[len] = '\0';
+  typevec[ntypes++] = tem;
+  return 1;
+}
+
+/* `decl' must be already initialised, usually non-empty;
+   it won't be freed on failure */
+
+static int
+do_args (type, decl)
+     const char **type;
+     string *decl;
+{
+  string arg;
+  int need_comma = 0;
+  int dont_want_first;
+
+#ifndef LONGERNAMES
+  dont_want_first = 1;
+#else
+  dont_want_first = 0;
+#endif
+
+  string_append (decl, "(");
+
+  while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
+    {
+      if (**type == 'N')
+       {
+         int r;
+         int t;
+         *type += 1;
+         if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
+           return 0;
+         while (--r >= 0)
+           {
+             const char *tem = typevec[t];
+             if (need_comma)
+               string_append (decl, ", ");
+             if (!do_arg (&tem, &arg))
+               return 0;
+             string_appends (decl, &arg);
+             string_delete (&arg);
+             need_comma = 1;
+           }
+       }
+      else
+       {
+         if (need_comma)
+           string_append (decl, ", ");
+         if (!do_arg (type, &arg))
+           return 0;
+         if (dont_want_first)
+           dont_want_first = 0;
+         else
+           {
+             string_appends (decl, &arg);
+             need_comma = 1;
+           }
+         string_delete (&arg);
+       }
+    }
+
+  if (**type == 'v')
+    *type += 1;
+  else if (**type == 'e')
+    {
+      *type += 1;
+      if (need_comma)
+       string_append (decl, ",");
+      string_append (decl, "...");
+    }
+
+  string_append (decl, ")");
+  return 1;
+}
+
+static void
+munge_function_name (name)
+     string *name;
+{
+  if (!string_empty (name) && name->p - name->b >= 3 
+      && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
+    {
+           unsigned int i;
+      /* see if it's an assignment expression */
+      if (name->p - name->b >= 10 /* op$assign_ */
+         && memcmp (name->b + 3, "assign_", 7) == 0)
+       {
+         for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+           {
+             int len = name->p - name->b - 10;
+             if (strlen (optable[i].in) == len
+                 && memcmp (optable[i].in, name->b + 10, len) == 0)
+               {
+                 string_clear (name);
+                 string_append (name, "operator");
+                 string_append (name, optable[i].out);
+                 string_append (name, "=");
+                 return;
+               }
+           }
+       }
+      else
+       {
+         for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+           {
+             int len = name->p - name->b - 3;
+             if (strlen (optable[i].in) == len 
+                 && memcmp (optable[i].in, name->b + 3, len) == 0)
+               {
+                 string_clear (name);
+                 string_append (name, "operator");
+                 string_append (name, optable[i].out);
+                 return;
+               }
+           }
+       }
+      return;
+    }
+  else if (!string_empty (name) && name->p - name->b >= 5
+          && memcmp (name->b, "type$", 5) == 0)
+    {
+      /* type conversion operator */
+      string type;
+      const char *tem = name->b + 5;
+      if (do_type (&tem, &type))
+       {
+         string_clear (name);
+         string_append (name, "operator ");
+         string_appends (name, &type);
+         string_delete (&type);
+         return;
+       }
+    }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+     string *s;
+     int n;
+{
+  if (s->b == NULL)
+    {
+      if (n < 32)
+       n = 32;
+      s->p = s->b = (char *) xmalloc (n);
+      s->e = s->b + n;
+    }
+  else if (s->e - s->p < n)
+    {
+      int tem = s->p - s->b;
+      n += tem;
+      n *= 2;
+      s->b = (char *) xrealloc (s->b, n);
+      s->p = s->b + tem;
+      s->e = s->b + n;
+    }
+}
+
+static void
+string_delete (s)
+     string *s;
+{
+  if (s->b != NULL)
+    {
+      free (s->b);
+      s->b = s->e = s->p = NULL;
+    }
+}
+
+static void
+string_init (s)
+     string *s;
+{
+  s->b = s->p = s->e = NULL;
+}
+
+static void 
+string_clear (s)
+     string *s;
+{
+  s->p = s->b;
+}
+
+static int
+string_empty (s)
+     string *s;
+{
+  return s->b == s->p;
+}
+
+static void
+string_append (p, s)
+     string *p;
+     const char *s;
+{
+  int n;
+  if (s == NULL || *s == '\0')
+    return;
+  n = strlen (s);
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_appends (p, s)
+     string *p, *s;
+{
+  int n;
+  if (s->b == s->p)
+    return;
+  n = s->p - s->b;
+  string_need (p, n);
+  memcpy (p->p, s->b, n);
+  p->p += n;
+}
+
+static void
+string_appendn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  if (n == 0)
+    return;
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_prepend (p, s)
+     string *p;
+     const char *s;
+{
+  if (s == NULL || *s == '\0')
+    return;
+  string_prependn (p, s, strlen (s));
+}
+
+static void
+string_prependn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  char *q;
+
+  if (n == 0)
+    return;
+  string_need (p, n);
+  for (q = p->p - 1; q >= p->b; q--)
+    q[n] = q[0];
+  memcpy (p->b, s, n);
+  p->p += n;
+}
diff --git a/binutils/filemode.c b/binutils/filemode.c
new file mode 100644 (file)
index 0000000..1bb5e64
--- /dev/null
@@ -0,0 +1,193 @@
+/* filemode.c -- make a string describing file modes
+   Copyright (C) 1985, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+#include <sys/types.h>
+#include <sys/stat.h>
+
+void mode_string ();
+static char ftypelet ();
+static void rwx ();
+static void setst ();
+
+/* 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. */
+
+void
+filemodestring (statp, str)
+     struct stat *statp;
+     char *str;
+{
+  mode_string (statp->st_mode, str);
+}
+
+/* Like filemodestring, but only the relevant part of the `struct stat'
+   is given as an argument. */
+
+void
+mode_string (mode, str)
+     unsigned short mode;
+     char *str;
+{
+  str[0] = ftypelet (mode);
+  rwx ((mode & 0700) << 0, &str[1]);
+  rwx ((mode & 0070) << 3, &str[4]);
+  rwx ((mode & 0007) << 6, &str[7]);
+  setst (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. */
+
+static char
+ftypelet (bits)
+     unsigned short bits;
+{
+  switch (bits & S_IFMT)
+    {
+    default:
+      return '-';
+    case S_IFDIR:
+      return 'd';
+#ifdef S_IFLNK
+    case S_IFLNK:
+      return 'l';
+#endif
+#ifdef S_IFCHR
+    case S_IFCHR:
+      return 'c';
+#endif
+#ifdef S_IFBLK
+    case S_IFBLK:
+      return 'b';
+#endif
+#ifdef S_IFMPC
+    case S_IFMPC:
+    case S_IFMPB:
+      return 'm';
+#endif
+#ifdef S_IFSOCK
+    case S_IFSOCK:
+      return 's';
+#endif
+#ifdef S_IFIFO
+#if S_IFIFO != S_IFSOCK
+    case S_IFIFO:
+      return 'p';
+#endif
+#endif
+#ifdef S_IFNWK                 /* HP-UX */
+    case S_IFNWK:
+      return 'n';
+#endif
+    }
+}
+
+/* Look at read, write, and execute bits in BITS and set
+   flags in CHARS accordingly. */
+
+static void
+rwx (bits, chars)
+     unsigned short bits;
+     char *chars;
+{
+  chars[0] = (bits & S_IREAD) ? 'r' : '-';
+  chars[1] = (bits & S_IWRITE) ? 'w' : '-';
+  chars[2] = (bits & S_IEXEC) ? 'x' : '-';
+}
+
+/* Set the 's' and 't' flags in file attributes string CHARS,
+   according to the file mode BITS. */
+
+static void
+setst (bits, chars)
+     unsigned short bits;
+     char *chars;
+{
+#ifdef S_ISUID
+  if (bits & S_ISUID)
+    {
+      if (chars[3] != 'x')
+       /* Set-uid, but not executable by owner. */
+       chars[3] = 'S';
+      else
+       chars[3] = 's';
+    }
+#endif
+#ifdef S_ISGID
+  if (bits & S_ISGID)
+    {
+      if (chars[6] != 'x')
+       /* Set-gid, but not executable by group. */
+       chars[6] = 'S';
+      else
+       chars[6] = 's';
+    }
+#endif
+#ifdef S_ISVTX
+  if (bits & S_ISVTX)
+    {
+      if (chars[9] != 'x')
+       /* Sticky, but not executable by others. */
+       chars[9] = 'T';
+      else
+       chars[9] = 't';
+    }
+#endif
+}
+
+
diff --git a/binutils/gmalloc.c b/binutils/gmalloc.c
new file mode 100644 (file)
index 0000000..0468551
--- /dev/null
@@ -0,0 +1,1116 @@
+
+/* gmalloc.c - THIS FILE IS AUTOMAGICALLY GENERATED SO DON'T EDIT IT. */
+
+/* Single-file skeleton for GNU malloc.
+   Copyright 1989 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#define __ONEFILE
+
+/* DO NOT DELETE THIS LINE -- ansidecl.h INSERTED HERE. */
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library 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 1, or (at your option)
+any later version.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+       Macros
+               PTR             - Generic pointer type
+               LONG_DOUBLE     - `long double' type
+               CONST           - `const' keyword
+               VOLATILE        - `volatile' keyword
+               SIGNED          - `signed' keyword
+               PTRCONST        - Generic const pointer (void *const)
+
+       EXFUN(name, prototype)          - declare external function NAME
+                                         with prototype PROTOTYPE
+       DEFUN(name, arglist, args)      - define function NAME with
+                                         args ARGLIST of types in ARGS
+       DEFUN_VOID(name)                - define function NAME with no args
+       AND                             - argument separator for ARGS
+       NOARGS                          - null arglist
+       DOTS                            - `...' in args
+
+    For example:
+       extern int EXFUN(printf, (CONST char *format DOTS));
+       int DEFUN(fprintf, (stream, format),
+                 FILE *stream AND CONST char *format DOTS) { ... }
+       void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef        _ANSIDECL_H
+
+#define        _ANSIDECL_H     1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#ifdef __STDC__
+
+#define        PTR             void *
+#define        PTRCONST        void *CONST
+#define        LONG_DOUBLE     long double
+
+#define        AND             ,
+#define        NOARGS          void
+#define        CONST           const
+#define        VOLATILE        volatile
+#define        SIGNED          signed
+#define        DOTS            , ...
+
+#define        EXFUN(name, proto)              name proto
+#define        DEFUN(name, arglist, args)      name(args)
+#define        DEFUN_VOID(name)                name(NOARGS)
+
+#else  /* Not ANSI C.  */
+
+#define        PTR             char *
+#define        PTRCONST        PTR
+#define        LONG_DOUBLE     double
+
+#define        AND             ;
+#define        NOARGS
+#define        CONST
+#define        VOLATILE
+#define        SIGNED
+#define        DOTS
+
+#define        EXFUN(name, proto)              name()
+#define        DEFUN(name, arglist, args)      name arglist args;
+#define        DEFUN_VOID(name)                name()
+
+#endif /* ANSI C.  */
+
+
+#endif /* ansidecl.h   */
+
+#ifdef __STDC__
+#include <limits.h>
+#else
+/* DO NOT DELETE THIS LINE -- limits.h INSERTED HERE. */
+/* Number of bits in a `char'.  */
+#define CHAR_BIT 8
+
+/* No multibyte characters supported yet.  */
+#define MB_LEN_MAX 1
+
+/* Minimum and maximum values a `signed char' can hold.  */
+#define SCHAR_MIN -128
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold.  (Minimum is 0).  */
+#define UCHAR_MAX 255U
+
+/* Minimum and maximum values a `char' can hold.  */
+#ifdef __CHAR_UNSIGNED__
+#define CHAR_MIN 0
+#define CHAR_MAX 255U
+#else
+#define CHAR_MIN -128
+#define CHAR_MAX 127
+#endif
+
+/* Minimum and maximum values a `signed short int' can hold.  */
+#define SHRT_MIN -32768
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short int' can hold.  (Minimum is 0).  */
+#define USHRT_MAX 65535U
+
+/* Minimum and maximum values a `signed int' can hold.  */
+#define INT_MIN -2147483648
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold.  (Minimum is 0).  */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long int' can hold.
+   (Same as `int').  */
+#define LONG_MIN (-LONG_MAX-1)
+#define LONG_MAX 2147483647
+
+/* Maximum value an `unsigned long int' can hold.  (Minimum is 0).  */
+#define ULONG_MAX 4294967295U
+#endif
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+/* DO NOT DELETE THIS LINE -- stddef.h INSERTED HERE. */
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+/* Signed type of difference of two pointers.  */
+
+typedef long ptrdiff_t;
+
+/* Unsigned type of `sizeof' something.  */
+
+#ifndef _SIZE_T        /* in case <sys/types.h> has defined it. */
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif /* _SIZE_T */
+
+/* A null pointer constant.  */
+
+#undef NULL            /* in case <stdio.h> has defined it. */
+#define NULL 0
+
+/* Offset of member MEMBER in a struct of type TYPE.  */
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* _STDDEF_H */
+#endif
+
+/* DO NOT DELETE THIS LINE -- stdlib.h INSERTED HERE. */
+/* Fake stdlib.h supplying the stuff needed by malloc. */
+
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern void EXFUN(abort, (void));
+extern void EXFUN(free, (PTR));
+extern PTR EXFUN(malloc, (size_t));
+extern PTR EXFUN(realloc, (PTR, size_t));
+
+/* DO NOT DELETE THIS LINE -- string.h INSERTED HERE. */
+/* Fake string.h supplying stuff used by malloc. */
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern PTR EXFUN(memcpy, (PTR, PTR, size_t));
+extern PTR EXFUN(memset, (PTR, int, size_t));
+#define memmove memcpy
+
+#define _MALLOC_INTERNAL
+/* DO NOT DELETE THIS LINE -- malloc.h INSERTED HERE. */
+/* Declarations for `malloc' and friends.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H      1
+
+#ifndef __ONEFILE
+#define        __need_NULL
+#define        __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+#endif
+
+#ifdef _MALLOC_INTERNAL
+
+#ifndef __ONEFILE
+#include <limits.h>
+#endif
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.  */
+#define INT_BIT                (CHAR_BIT * sizeof(int))
+#define BLOCKLOG       (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE      (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit).  */
+#define HEAP           (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system.  */
+#define FINAL_FREE_BLOCKS      8
+
+/* Where to start searching the free list when looking for new memory.
+   The two possible values are 0 and _heapindex.  Starting at 0 seems
+   to reduce total memory usage, while starting at _heapindex seems to
+   run faster.  */
+#define MALLOC_SEARCH_START    _heapindex
+
+/* Data structure giving per-block information.  */
+typedef union
+  {
+    /* Heap information for a busy block.  */
+    struct
+      {
+       /* Zero for a large block, or positive giving the
+          logarithm to the base two of the fragment size.  */
+       int type;
+       union
+         {
+           struct
+             {
+               size_t nfree;   /* Free fragments in a fragmented block.  */
+               size_t first;   /* First free fragment of the block.  */
+             } frag;
+           /* Size (in blocks) of a large cluster.  */
+           size_t size;
+         } info;
+      } busy;
+    /* Heap information for a free block (that may be the first of
+       a free cluster).  */
+    struct
+      {
+       size_t size;            /* Size (in blocks) of a free cluster.  */
+       size_t next;            /* Index of next free cluster.  */
+       size_t prev;            /* Index of previous free cluster.  */
+      } free;
+  } malloc_info;
+
+/* Pointer to first block of the heap.  */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information.  */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa.  */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table.  */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments.  */
+struct list
+  {
+    struct list *next;
+    struct list *prev;
+  };
+
+/* Free list headers for each fragment size.  */
+extern struct list _fraghead[];
+
+/* Instrumentation.  */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of free() used in morecore(). */
+extern void EXFUN(__free, (PTR __ptr));
+
+#endif  /* _MALLOC_INTERNAL.  */
+
+/* Underlying allocation function; successive calls should
+   return contiguous pieces of memory.  */
+extern PTR EXFUN((*__morecore), (ptrdiff_t __size));
+
+/* Default value of previous.  */
+extern PTR EXFUN(__default_morecore, (ptrdiff_t __size));
+
+/* Flag whether malloc has been called.  */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions.  */
+extern void EXFUN((*__free_hook), (PTR __ptr));
+extern PTR EXFUN((*__malloc_hook), (size_t __size));
+extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks.  */
+extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
+
+/* Statistics available to the user.  */
+struct mstats
+  {
+    size_t bytes_total;                /* Total size of the heap. */
+    size_t chunks_used;                /* Chunks allocated by the user. */
+    size_t bytes_used;         /* Byte total of user-allocated chunks. */
+    size_t chunks_free;                /* Chunks in the free list. */
+    size_t bytes_free;         /* Byte total of chunks in the free list. */
+  };
+
+/* Pick up the current statistics. */
+extern struct mstats EXFUN(mstats, (NOARGS));
+
+#endif /* malloc.h  */
+
+/* DO NOT DELETE THIS LINE -- free.c INSERTED HERE. */
+/* Free a block of memory allocated by `malloc'.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* Debugging hook for free.  */
+void EXFUN((*__free_hook), (PTR __ptr));
+
+/* Return memory to the heap.  Like free() but don't call a __free_hook
+   if there is one.  */
+void
+DEFUN(__free, (ptr), PTR ptr)
+{
+  int type;
+  size_t block, blocks;
+  register size_t i;
+  struct list *prev, *next;
+
+  block = BLOCK(ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Get as many statistics as early as we can.  */
+      --_chunks_used;
+      _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+      _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+      /* Find the free cluster previous to this one in the free list.
+        Start searching at the last block referenced; this may benefit
+        programs with locality of allocation.  */
+      i = _heapindex;
+      if (i > block)
+       while (i > block)
+         i = _heapinfo[i].free.prev;
+      else
+       {
+         do
+           i = _heapinfo[i].free.next;
+         while (i > 0 && i < block);
+         i = _heapinfo[i].free.prev;
+       }
+
+      /* Determine how to link this block into the free list.  */
+      if (block == i + _heapinfo[i].free.size)
+       {
+         /* Coalesce this block with its predecessor.  */
+         _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+         block = i;
+       }
+      else
+       {
+         /* Really link this block back into the free list.  */
+         _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+         _heapinfo[block].free.next = _heapinfo[i].free.next;
+         _heapinfo[block].free.prev = i;
+         _heapinfo[i].free.next = block;
+         _heapinfo[_heapinfo[block].free.next].free.prev = block;
+         ++_chunks_free;
+       }
+
+      /* Now that the block is linked in, see if we can coalesce it
+        with its successor (by deleting its successor from the list
+        and adding in its size).  */
+      if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+       {
+         _heapinfo[block].free.size
+           += _heapinfo[_heapinfo[block].free.next].free.size;
+         _heapinfo[block].free.next
+           = _heapinfo[_heapinfo[block].free.next].free.next;
+         _heapinfo[_heapinfo[block].free.next].free.prev = block;
+         --_chunks_free;
+       }
+
+      /* Now see if we can return stuff to the system.  */
+      blocks = _heapinfo[block].free.size;
+      if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+         && (*__morecore)(0) == ADDRESS(block + blocks))
+       {
+         register size_t bytes = blocks * BLOCKSIZE;
+         _heaplimit -= blocks;
+         (*__morecore)(- bytes);
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapinfo[block].free.next;
+         _heapinfo[_heapinfo[block].free.next].free.prev
+           = _heapinfo[block].free.prev;
+         block = _heapinfo[block].free.prev;
+         --_chunks_free;
+         _bytes_free -= bytes;
+       }
+
+      /* Set the next search to begin at this block.  */
+      _heapindex = block;
+      break;
+
+    default:
+      /* Do some of the statistics.  */
+      --_chunks_used;
+      _bytes_used -= 1 << type;
+      ++_chunks_free;
+      _bytes_free += 1 << type;
+
+      /* Get the address of the first free fragment in this block.  */
+      prev = (struct list *) ((char *) ADDRESS(block) +
+                             (_heapinfo[block].busy.info.frag.first << type));
+
+      if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+       {
+         /* If all fragments of this block are free, remove them
+            from the fragment list and free the whole block.  */
+         next = prev;
+         for (i = 1; i < BLOCKSIZE >> type; ++i)
+           next = next->next;
+         prev->prev->next = next;
+         if (next != NULL)
+           next->prev = prev->prev;
+         _heapinfo[block].busy.type = 0;
+         _heapinfo[block].busy.info.size = 1;
+
+         /* Keep the statistics accurate.  */
+         ++_chunks_used;
+         _bytes_used += BLOCKSIZE;
+         _chunks_free -= BLOCKSIZE >> type;
+         _bytes_free -= BLOCKSIZE;
+
+         free(ADDRESS(block));
+       }
+      else if (_heapinfo[block].busy.info.frag.nfree != 0)
+       {
+         /* If some fragments of this block are free, link this
+            fragment into the fragment list after the first free
+            fragment of this block. */
+         next = (struct list *) ptr;
+         next->next = prev->next;
+         next->prev = prev;
+         prev->next = next;
+         if (next->next != NULL)
+           next->next->prev = next;
+         ++_heapinfo[block].busy.info.frag.nfree;
+       }
+      else
+       {
+         /* No fragments of this block are free, so link this
+            fragment into the fragment list and announce that
+            it is the first free fragment of this block. */
+         prev = (struct list *) ptr;
+         _heapinfo[block].busy.info.frag.nfree = 1;
+         _heapinfo[block].busy.info.frag.first = (unsigned int)
+           (((char *) ptr - (char *) NULL) % BLOCKSIZE >> type);
+         prev->next = _fraghead[type].next;
+         prev->prev = &_fraghead[type];
+         prev->prev->next = prev;
+         if (prev->next != NULL)
+           prev->next->prev = prev;
+       }
+      break;
+    }
+}
+
+/* Return memory to the heap.  */
+void
+DEFUN(free, (ptr), PTR ptr)
+{
+  if (ptr == NULL)
+    return;
+
+  if (__free_hook != NULL)
+    (*__free_hook)(ptr);
+  else
+    __free (ptr);
+}
+
+/* DO NOT DELETE THIS LINE -- malloc.c INSERTED HERE. */
+/* Memory allocator `malloc'.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* How to really get more memory.  */
+PTR EXFUN((*__morecore), (ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'.  */
+PTR EXFUN((*__malloc_hook), (size_t __size));
+
+/* Pointer to the base of the first block.  */
+char *_heapbase;
+
+/* Block information table.  Allocated with align/__free (not malloc/free).  */
+malloc_info *_heapinfo;
+
+/* Number of info entries.  */
+static size_t heapsize;
+
+/* Search index in the info table.  */
+size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+size_t _heaplimit;
+
+/* Free lists for each fragment size.  */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation.  */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced?  */
+int __malloc_initialized;
+
+/* Aligned allocation.  */
+static PTR
+DEFUN(align, (size), size_t size)
+{
+  PTR result;
+  unsigned int adj;
+
+  result = (*__morecore)(size);
+  adj = (unsigned int) ((char *) result - (char *) NULL) % BLOCKSIZE;
+  if (adj != 0)
+    {
+      adj = BLOCKSIZE - adj;
+      (void) (*__morecore)(adj);
+      result = (char *) result + adj;
+    }
+  return result;
+}
+
+/* Set everything up and remember that we have.  */
+static int
+DEFUN_VOID(initialize)
+{
+  heapsize = HEAP / BLOCKSIZE;
+  _heapinfo = (malloc_info *) align(heapsize * sizeof(malloc_info));
+  if (_heapinfo == NULL)
+    return 0;
+  memset(_heapinfo, 0, heapsize * sizeof(malloc_info));
+  _heapinfo[0].free.size = 0;
+  _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+  _heapindex = 0;
+  _heapbase = (char *) _heapinfo;
+  __malloc_initialized = 1;
+  return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+   growing the heap info table as necessary. */
+static PTR
+DEFUN(morecore, (size), size_t size)
+{
+  PTR result;
+  malloc_info *newinfo, *oldinfo;
+  size_t newsize;
+
+  result = align(size);
+  if (result == NULL)
+    return NULL;
+
+  /* Check if we need to grow the info table.  */
+  if (BLOCK((char *) result + size) > heapsize)
+    {
+      newsize = heapsize;
+      while (BLOCK((char *) result + size) > newsize)
+       newsize *= 2;
+      newinfo = (malloc_info *) align(newsize * sizeof(malloc_info));
+      if (newinfo == NULL)
+       {
+         (*__morecore)(- size);
+         return NULL;
+       }
+      memset(newinfo, 0, newsize * sizeof(malloc_info));
+      memcpy(newinfo, _heapinfo, heapsize * sizeof(malloc_info));
+      oldinfo = _heapinfo;
+      newinfo[BLOCK(oldinfo)].busy.type = 0;
+      newinfo[BLOCK(oldinfo)].busy.info.size
+       = BLOCKIFY(heapsize * sizeof(malloc_info));
+      _heapinfo = newinfo;
+      __free(oldinfo);
+      heapsize = newsize;
+    }
+
+  _heaplimit = BLOCK((char *) result + size);
+  return result;
+}
+
+/* Allocate memory from the heap.  */
+PTR
+DEFUN(malloc, (size), size_t size)
+{
+  PTR result;
+  size_t block, blocks, lastblocks, start;
+  register size_t i;
+  struct list *next;
+
+  if (size == 0)
+    return NULL;
+
+  if (__malloc_hook != NULL)
+    return (*__malloc_hook)(size);
+
+  if (!__malloc_initialized)
+    if (!initialize())
+      return NULL;
+
+  if (size < sizeof(struct list))
+    size = sizeof(struct list);
+
+  /* Determine the allocation policy based on the request size.  */
+  if (size <= BLOCKSIZE / 2)
+    {
+      /* Small allocation to receive a fragment of a block.
+        Determine the logarithm to base two of the fragment size. */
+      register size_t log = 1;
+      --size;
+      while ((size /= 2) != 0)
+       ++log;
+
+      /* Look in the fragment lists for a
+        free fragment of the desired size. */
+      next = _fraghead[log].next;
+      if (next != NULL)
+       {
+         /* There are free fragments of this size.
+            Pop a fragment out of the fragment list and return it.
+            Update the block's nfree and first counters. */
+         result = (PTR) next;
+         next->prev->next = next->next;
+         if (next->next != NULL)
+           next->next->prev = next->prev;
+         block = BLOCK(result);
+         if (--_heapinfo[block].busy.info.frag.nfree != 0)
+           _heapinfo[block].busy.info.frag.first = (unsigned int)
+             (((char *) next->next - (char *) NULL) % BLOCKSIZE) >> log;
+
+         /* Update the statistics.  */
+         ++_chunks_used;
+         _bytes_used += 1 << log;
+         --_chunks_free;
+         _bytes_free -= 1 << log;
+       }
+      else
+       {
+         /* No free fragments of the desired size, so get a new block
+            and break it into fragments, returning the first.  */
+         result = malloc(BLOCKSIZE);
+         if (result == NULL)
+           return NULL;
+
+         /* Link all fragments but the first into the free list.  */
+         for (i = 1; i < BLOCKSIZE >> log; ++i)
+           {
+             next = (struct list *) ((char *) result + (i << log));
+             next->next = _fraghead[log].next;
+             next->prev = &_fraghead[log];
+             next->prev->next = next;
+             if (next->next != NULL)
+               next->next->prev = next;
+           }
+
+         /* Initialize the nfree and first counters for this block.  */
+         block = BLOCK(result);
+         _heapinfo[block].busy.type = log;
+         _heapinfo[block].busy.info.frag.nfree = i - 1;
+         _heapinfo[block].busy.info.frag.first = i - 1;
+
+         _chunks_free += (BLOCKSIZE >> log) - 1;
+         _bytes_free += BLOCKSIZE - (1 << log);
+       }
+    }
+  else
+    {
+      /* Large allocation to receive one or more blocks.
+        Search the free list in a circle starting at the last place visited.
+        If we loop completely around without finding a large enough
+        space we will have to get more memory from the system.  */
+      blocks = BLOCKIFY(size);
+      start = block = MALLOC_SEARCH_START;
+      while (_heapinfo[block].free.size < blocks)
+       {
+         block = _heapinfo[block].free.next;
+         if (block == start)
+           {
+             /* Need to get more from the system.  Check to see if
+                the new core will be contiguous with the final free
+                block; if so we don't need to get as much.  */
+             block = _heapinfo[0].free.prev;
+             lastblocks = _heapinfo[block].free.size;
+             if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+                 (*__morecore)(0) == ADDRESS(block + lastblocks) &&
+                 (morecore((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+               {
+                 _heapinfo[block].free.size = blocks;
+                 _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+                 continue;
+               }
+             result = morecore(blocks * BLOCKSIZE);
+             if (result == NULL)
+               return NULL;
+             block = BLOCK(result);
+             _heapinfo[block].busy.type = 0;
+             _heapinfo[block].busy.info.size = blocks;
+             ++_chunks_used;
+             _bytes_used += blocks * BLOCKSIZE;
+             return result;
+           }
+       }
+
+      /* At this point we have found a suitable free list entry.
+        Figure out how to remove what we need from the list. */
+      result = ADDRESS(block);
+      if (_heapinfo[block].free.size > blocks)
+       {
+         /* The block we found has a bit left over,
+            so relink the tail end back into the free list. */
+         _heapinfo[block + blocks].free.size
+           = _heapinfo[block].free.size - blocks;
+         _heapinfo[block + blocks].free.next
+           = _heapinfo[block].free.next;
+         _heapinfo[block + blocks].free.prev
+           = _heapinfo[block].free.prev;
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapinfo[_heapinfo[block].free.next].free.prev
+             = _heapindex = block + blocks;
+       }
+      else
+       {
+         /* The block exactly matches our requirements,
+            so just remove it from the list. */
+         _heapinfo[_heapinfo[block].free.next].free.prev
+           = _heapinfo[block].free.prev;
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapindex = _heapinfo[block].free.next;
+         --_chunks_free;
+       }
+
+      _heapinfo[block].busy.type = 0;
+      _heapinfo[block].busy.info.size = blocks;
+      ++_chunks_used;
+      _bytes_used += blocks * BLOCKSIZE;
+      _bytes_free -= blocks * BLOCKSIZE;
+    }
+
+  return result;
+}
+
+/* DO NOT DELETE THIS LINE -- realloc.c INSERTED HERE. */
+/* Change the size of a block allocated by `malloc'.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc.  */
+PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+   to the (possibly moved) region.  This is optimized for speed;
+   some benchmarks seem to indicate that greater compactness is
+   achieved by unconditionally allocating and copying to a
+   new region.  This module has incestuous knowledge of the
+   internals of both free and malloc. */
+PTR
+DEFUN(realloc, (ptr, size), PTR ptr AND size_t size)
+{
+  PTR result;
+  int type;
+  size_t block, blocks, oldlimit;
+
+  if (size == 0)
+    {
+      free(ptr);
+      return NULL;
+    }
+  else if (ptr == NULL)
+    return malloc(size);
+
+  if (__realloc_hook != NULL)
+    return (*__realloc_hook)(ptr, size);
+
+  block = BLOCK(ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Maybe reallocate a large block to a small fragment.  */
+      if (size <= BLOCKSIZE / 2)
+       {
+         result = malloc(size);
+         if (result != NULL)
+           {
+             memcpy(result, ptr, size);
+             free(ptr);
+             return result;
+           }
+       }
+
+      /* The new size is a large allocation as well;
+        see if we can hold it in place. */
+      blocks = BLOCKIFY(size);
+      if (blocks < _heapinfo[block].busy.info.size)
+       {
+         /* The new size is smaller; return
+            excess memory to the free list. */
+         _heapinfo[block + blocks].busy.type = 0;
+         _heapinfo[block + blocks].busy.info.size
+           = _heapinfo[block].busy.info.size - blocks;
+         _heapinfo[block].busy.info.size = blocks;
+         free(ADDRESS(block + blocks));
+         result = ptr;
+       }
+      else if (blocks == _heapinfo[block].busy.info.size)
+       /* No size change necessary.  */
+       result = ptr;
+      else
+       {
+         /* Won't fit, so allocate a new region that will.
+            Free the old region first in case there is sufficient
+            adjacent free space to grow without moving. */
+         blocks = _heapinfo[block].busy.info.size;
+         /* Prevent free from actually returning memory to the system.  */
+         oldlimit = _heaplimit;
+         _heaplimit = 0;
+         free(ptr);
+         _heaplimit = oldlimit;
+         result = malloc(size);
+         if (result == NULL)
+           {
+             (void) malloc(blocks * BLOCKSIZE);
+             return NULL;
+           }
+         if (ptr != result)
+           memmove(result, ptr, blocks * BLOCKSIZE);
+       }
+      break;
+
+    default:
+      /* Old size is a fragment; type is logarithm
+        to base two of the fragment size.  */
+      if (size > 1 << (type - 1) && size <= 1 << type)
+       /* The new size is the same kind of fragment.  */
+       result = ptr;
+      else
+       {
+         /* The new size is different; allocate a new space,
+            and copy the lesser of the new size and the old. */
+         result = malloc(size);
+         if (result == NULL)
+           return NULL;
+         memcpy(result, ptr, MIN(size, 1 << type));
+         free(ptr);
+       }
+      break;
+    }
+
+  return result;
+}
+
+/* DO NOT DELETE THIS LINE -- unix.c INSERTED HERE. */
+/* unix.c - get more memory with a UNIX system call.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+extern PTR EXFUN(sbrk, (ptrdiff_t size));
+
+PTR
+DEFUN(__default_morecore, (size), ptrdiff_t size)
+{
+  PTR result;
+
+  result = sbrk(size);
+  if (result == (PTR) -1)
+    return NULL;
+  return result;
+}
+
+#define __getpagesize getpagesize
+/* DO NOT DELETE THIS LINE -- valloc.c INSERTED HERE. */
+/* Allocate memory on a page boundary.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#endif /* __ONEFILE */
+
+extern size_t EXFUN(__getpagesize, (NOARGS));
+
+static size_t pagesize;
+
+PTR
+DEFUN(valloc, (size), size_t size)
+{
+  PTR result;
+  unsigned int adj;
+
+  if (pagesize == 0)
+    pagesize = __getpagesize();
+
+  result = malloc(size + pagesize);
+  if (result == NULL)
+    return NULL;
+  adj = (unsigned int) ((char *) result - (char *) NULL) % pagesize;
+  if (adj != 0)
+    result = (char *) result + pagesize - adj;
+  return result;
+}
diff --git a/binutils/i960-pinsn.c b/binutils/i960-pinsn.c
new file mode 100644 (file)
index 0000000..1c7b719
--- /dev/null
@@ -0,0 +1,820 @@
+/* Disassemble i80960 instructions.
+ */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ 
+   $Log
+*/
+#include <stdio.h>
+#include "sysdep.h"
+#include "bfd.h"
+
+extern char *xmalloc();
+extern int fputs();
+
+static char *reg_names[] = {
+/*  0 */       "pfp", "sp",  "rip", "r3",  "r4",  "r5",  "r6",  "r7", 
+/*  8 */       "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
+/* 16 */       "g0",  "g1",  "g2",  "g3",  "g4",  "g5",  "g6",  "g7", 
+/* 24 */       "g8",  "g9",  "g10", "g11", "g12", "g13", "g14", "fp", 
+/* 32 */       "pc",  "ac",  "ip",  "tc",  "fp0", "fp1", "fp2", "fp3" 
+};
+
+
+static FILE *stream;           /* Output goes here */
+static void print_addr();
+static void ctrl();
+static void cobr();
+static void reg();
+static int mem();
+static void ea();
+static void dstop();
+static void regop();
+static void invalid();
+static int pinsn();
+static void put_abs();
+
+
+/* Print the i960 instruction at address 'memaddr' in debugged memory,
+ * on stream 's'.  Returns length of the instruction, in bytes.
+ */
+int
+print_insn_i960( memaddr, buffer, s )
+    bfd_vma memaddr;
+uint8e_type *buffer;
+    FILE *s;
+{
+    unsigned int word1, word2;
+
+    stream = s;
+    word1 =buffer [0] |( buffer[1]<< 8) | (buffer[2] << 16) | ( buffer[3] <<24);
+    word2 =buffer [4] |( buffer[5]<< 8) | (buffer[6] << 16) | ( buffer[7] <<24);
+    return pinsn( memaddr, word1, word2 );
+}
+\f
+#define IN_GDB
+
+/*****************************************************************************
+ *     All code below this point should be identical with that of
+ *     the disassembler in gdmp960.
+ *****************************************************************************/
+
+struct tabent {
+       char    *name;
+       char    numops;
+};
+
+static int
+pinsn( memaddr, word1, word2 )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+{
+       int instr_len;
+
+       instr_len = 4;
+       put_abs( word1, word2 );
+
+       /* Divide instruction set into classes based on high 4 bits of opcode*/
+       switch ( (word1 >> 28) & 0xf ){
+       case 0x0:
+       case 0x1:
+               ctrl( memaddr, word1, word2 );
+               break;
+       case 0x2:
+       case 0x3:
+               cobr( memaddr, word1, word2 );
+               break;
+       case 0x5:
+       case 0x6:
+       case 0x7:
+               reg( word1 );
+               break;
+       case 0x8:
+       case 0x9:
+       case 0xa:
+       case 0xb:
+       case 0xc:
+               instr_len = mem( memaddr, word1, word2, 0 );
+               break;
+       default:
+               /* invalid instruction, print as data word */ 
+               invalid( word1 );
+               break;
+       }
+       return instr_len;
+}
+
+/****************************************/
+/* CTRL format                         */
+/****************************************/
+static void
+ctrl( memaddr, word1, word2 )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+{
+       int i;
+       static struct tabent ctrl_tab[] = {
+               NULL,           0,      /* 0x00 */
+               NULL,           0,      /* 0x01 */
+               NULL,           0,      /* 0x02 */
+               NULL,           0,      /* 0x03 */
+               NULL,           0,      /* 0x04 */
+               NULL,           0,      /* 0x05 */
+               NULL,           0,      /* 0x06 */
+               NULL,           0,      /* 0x07 */
+               "b",            1,      /* 0x08 */
+               "call",         1,      /* 0x09 */
+               "ret",          0,      /* 0x0a */
+               "bal",          1,      /* 0x0b */
+               NULL,           0,      /* 0x0c */
+               NULL,           0,      /* 0x0d */
+               NULL,           0,      /* 0x0e */
+               NULL,           0,      /* 0x0f */
+               "bno",          1,      /* 0x10 */
+               "bg",           1,      /* 0x11 */
+               "be",           1,      /* 0x12 */
+               "bge",          1,      /* 0x13 */
+               "bl",           1,      /* 0x14 */
+               "bne",          1,      /* 0x15 */
+               "ble",          1,      /* 0x16 */
+               "bo",           1,      /* 0x17 */
+               "faultno",      0,      /* 0x18 */
+               "faultg",       0,      /* 0x19 */
+               "faulte",       0,      /* 0x1a */
+               "faultge",      0,      /* 0x1b */
+               "faultl",       0,      /* 0x1c */
+               "faultne",      0,      /* 0x1d */
+               "faultle",      0,      /* 0x1e */
+               "faulto",       0,      /* 0x1f */
+       };
+
+       i = (word1 >> 24) & 0xff;
+       if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){
+               invalid( word1 );
+               return;
+       }
+
+       fputs( ctrl_tab[i].name, stream );
+       if ( word1 & 2 ){               /* Predicts branch not taken */
+               fputs( ".f", stream );
+       }
+
+       if ( ctrl_tab[i].numops == 1 ){
+               /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */
+               word1 &= 0x00ffffff;
+               if ( word1 & 0x00800000 ){              /* Sign bit is set */
+                       word1 |= (-1 & ~0xffffff);      /* Sign extend */
+               }
+               putc( '\t', stream );
+               print_addr( word1 + memaddr );
+       }
+}
+
+/****************************************/
+/* COBR format                         */
+/****************************************/
+static void
+cobr( memaddr, word1, word2 )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+{
+       int src1;
+       int src2;
+       int i;
+
+       static struct tabent cobr_tab[] = {
+               "testno",       1,      /* 0x20 */
+               "testg",        1,      /* 0x21 */
+               "teste",        1,      /* 0x22 */
+               "testge",       1,      /* 0x23 */
+               "testl",        1,      /* 0x24 */
+               "testne",       1,      /* 0x25 */
+               "testle",       1,      /* 0x26 */
+               "testo",        1,      /* 0x27 */
+               NULL,           0,      /* 0x28 */
+               NULL,           0,      /* 0x29 */
+               NULL,           0,      /* 0x2a */
+               NULL,           0,      /* 0x2b */
+               NULL,           0,      /* 0x2c */
+               NULL,           0,      /* 0x2d */
+               NULL,           0,      /* 0x2e */
+               NULL,           0,      /* 0x2f */
+               "bbc",          3,      /* 0x30 */
+               "cmpobg",       3,      /* 0x31 */
+               "cmpobe",       3,      /* 0x32 */
+               "cmpobge",      3,      /* 0x33 */
+               "cmpobl",       3,      /* 0x34 */
+               "cmpobne",      3,      /* 0x35 */
+               "cmpoble",      3,      /* 0x36 */
+               "bbs",          3,      /* 0x37 */
+               "cmpibno",      3,      /* 0x38 */
+               "cmpibg",       3,      /* 0x39 */
+               "cmpibe",       3,      /* 0x3a */
+               "cmpibge",      3,      /* 0x3b */
+               "cmpibl",       3,      /* 0x3c */
+               "cmpibne",      3,      /* 0x3d */
+               "cmpible",      3,      /* 0x3e */
+               "cmpibo",       3,      /* 0x3f */
+       };
+
+       i = ((word1 >> 24) & 0xff) - 0x20;
+       if ( cobr_tab[i].name == NULL ){
+               invalid( word1 );
+               return;
+       }
+
+       fputs( cobr_tab[i].name, stream );
+       if ( word1 & 2 ){               /* Predicts branch not taken */
+               fputs( ".f", stream );
+       }
+       putc( '\t', stream );
+
+       src1 = (word1 >> 19) & 0x1f;
+       src2 = (word1 >> 14) & 0x1f;
+
+       if ( word1 & 0x02000 ){         /* M1 is 1 */
+               fprintf( stream, "%d", src1 );
+       } else {                        /* M1 is 0 */
+               fputs( reg_names[src1], stream );
+       }
+
+       if ( cobr_tab[i].numops > 1 ){
+               if ( word1 & 1 ){               /* S2 is 1 */
+                       fprintf( stream, ",sf%d,", src2 );
+               } else {                        /* S1 is 0 */
+                       fprintf( stream, ",%s,", reg_names[src2] );
+               }
+
+               /* Extract displacement and convert to address
+                */
+               word1 &= 0x00001ffc;
+               if ( word1 & 0x00001000 ){      /* Negative displacement */
+                       word1 |= (-1 & ~0x1fff);        /* Sign extend */
+               }
+               print_addr( memaddr + word1 );
+       }
+}
+
+/****************************************/
+/* MEM format                          */
+/****************************************/
+static int                             /* returns instruction length: 4 or 8 */
+mem( memaddr, word1, word2, noprint )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+    int noprint;               /* If TRUE, return instruction length, but
+                                * don't output any text.
+                                */
+{
+       int i, j;
+       int len;
+       int mode;
+       int offset;
+       char *reg1, *reg2, *reg3;
+
+       /* This lookup table is too sparse to make it worth typing in, but not
+        * so large as to make a sparse array necessary.  We allocate the
+        * table at runtime, initialize all entries to empty, and copy the
+        * real ones in from an initialization table.
+        *
+        * NOTE: In this table, the meaning of 'numops' is:
+        *       1: single operand
+        *       2: 2 operands, load instruction
+        *      -2: 2 operands, store instruction
+        */
+       static struct tabent *mem_tab = NULL;
+       static struct { int opcode; char *name; char numops; } mem_init[] = {
+#define MEM_MIN        0x80
+               0x80,   "ldob",  2,
+               0x82,   "stob", -2,
+               0x84,   "bx",    1,
+               0x85,   "balx",  2,
+               0x86,   "callx", 1,
+               0x88,   "ldos",  2,
+               0x8a,   "stos", -2,
+               0x8c,   "lda",   2,
+               0x90,   "ld",    2,
+               0x92,   "st",   -2,
+               0x98,   "ldl",   2,
+               0x9a,   "stl",  -2,
+               0xa0,   "ldt",   2,
+               0xa2,   "stt",  -2,
+               0xb0,   "ldq",   2,
+               0xb2,   "stq",  -2,
+               0xc0,   "ldib",  2,
+               0xc2,   "stib", -2,
+               0xc8,   "ldis",  2,
+               0xca,   "stis", -2,
+#define MEM_MAX        0xca
+#define MEM_SIZ        ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
+               0,      NULL,   0
+       };
+
+       if ( mem_tab == NULL ){
+               mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
+               bzero( (void *) mem_tab, MEM_SIZ );
+               for ( i = 0; mem_init[i].opcode != 0; i++ ){
+                       j = mem_init[i].opcode - MEM_MIN;
+                       mem_tab[j].name = mem_init[i].name;
+                       mem_tab[j].numops = mem_init[i].numops;
+               }
+       }
+
+       i = ((word1 >> 24) & 0xff) - MEM_MIN;
+       mode = (word1 >> 10) & 0xf;
+
+       if ( (mem_tab[i].name != NULL)          /* Valid instruction */
+       &&   ((mode == 5) || (mode >=12)) ){    /* With 32-bit displacement */
+               len = 8;
+       } else {
+               len = 4;
+       }
+
+       if ( noprint ){
+               return len;
+       }
+
+       if ( (mem_tab[i].name == NULL) || (mode == 6) ){
+               invalid( word1 );
+               return len;
+       }
+
+       fprintf( stream, "%s\t", mem_tab[i].name );
+
+       reg1 = reg_names[ (word1 >> 19) & 0x1f ];       /* MEMB only */
+       reg2 = reg_names[ (word1 >> 14) & 0x1f ];
+       reg3 = reg_names[ word1 & 0x1f ];               /* MEMB only */
+       offset = word1 & 0xfff;                         /* MEMA only  */
+
+       switch ( mem_tab[i].numops ){
+
+       case 2: /* LOAD INSTRUCTION */
+               if ( mode & 4 ){                        /* MEMB FORMAT */
+                       ea( memaddr, mode, reg2, reg3, word1, word2 );
+                       fprintf( stream, ",%s", reg1 );
+               } else {                                /* MEMA FORMAT */
+                       fprintf( stream, "0x%x", (unsigned) offset );
+                       if (mode & 8) {
+                               fprintf( stream, "(%s)", reg2 );
+                       }
+                       fprintf( stream, ",%s", reg1 );
+               }
+               break;
+
+       case -2: /* STORE INSTRUCTION */
+               if ( mode & 4 ){                        /* MEMB FORMAT */
+                       fprintf( stream, "%s,", reg1 );
+                       ea( memaddr, mode, reg2, reg3, word1, word2 );
+               } else {                                /* MEMA FORMAT */
+                       fprintf( stream, "%s,0x%x", reg1, (unsigned) offset );
+                       if (mode & 8) {
+                               fprintf( stream, "(%s)", reg2 );
+                       }
+               }
+               break;
+
+       case 1: /* BX/CALLX INSTRUCTION */
+               if ( mode & 4 ){                        /* MEMB FORMAT */
+                       ea( memaddr, mode, reg2, reg3, word1, word2 );
+               } else {                                /* MEMA FORMAT */
+                       fprintf( stream, "0x%x", (unsigned) offset );
+                       if (mode & 8) {
+                               fprintf( stream, "(%s)", reg2 );
+                       }
+               }
+               break;
+       }
+
+       return len;
+}
+
+/****************************************/
+/* REG format                          */
+/****************************************/
+static void
+reg( word1 )
+    unsigned long word1;
+{
+       int i, j;
+       int opcode;
+       int fp;
+       int m1, m2, m3;
+       int s1, s2;
+       int src, src2, dst;
+       char *mnemp;
+
+       /* This lookup table is too sparse to make it worth typing in, but not
+        * so large as to make a sparse array necessary.  We allocate the
+        * table at runtime, initialize all entries to empty, and copy the
+        * real ones in from an initialization table.
+        *
+        * NOTE: In this table, the meaning of 'numops' is:
+        *       1: single operand, which is NOT a destination.
+        *      -1: single operand, which IS a destination.
+        *       2: 2 operands, the 2nd of which is NOT a destination.
+        *      -2: 2 operands, the 2nd of which IS a destination.
+        *       3: 3 operands
+        *
+        *      If an opcode mnemonic begins with "F", it is a floating-point
+        *      opcode (the "F" is not printed).
+        */
+
+       static struct tabent *reg_tab = NULL;
+       static struct { int opcode; char *name; char numops; } reg_init[] = {
+#define REG_MIN        0x580
+               0x580,  "notbit",       3,
+               0x581,  "and",          3,
+               0x582,  "andnot",       3,
+               0x583,  "setbit",       3,
+               0x584,  "notand",       3,
+               0x586,  "xor",          3,
+               0x587,  "or",           3,
+               0x588,  "nor",          3,
+               0x589,  "xnor",         3,
+               0x58a,  "not",          -2,
+               0x58b,  "ornot",        3,
+               0x58c,  "clrbit",       3,
+               0x58d,  "notor",        3,
+               0x58e,  "nand",         3,
+               0x58f,  "alterbit",     3,
+               0x590,  "addo",         3,
+               0x591,  "addi",         3,
+               0x592,  "subo",         3,
+               0x593,  "subi",         3,
+               0x598,  "shro",         3,
+               0x59a,  "shrdi",        3,
+               0x59b,  "shri",         3,
+               0x59c,  "shlo",         3,
+               0x59d,  "rotate",       3,
+               0x59e,  "shli",         3,
+               0x5a0,  "cmpo",         2,
+               0x5a1,  "cmpi",         2,
+               0x5a2,  "concmpo",      2,
+               0x5a3,  "concmpi",      2,
+               0x5a4,  "cmpinco",      3,
+               0x5a5,  "cmpinci",      3,
+               0x5a6,  "cmpdeco",      3,
+               0x5a7,  "cmpdeci",      3,
+               0x5ac,  "scanbyte",     2,
+               0x5ae,  "chkbit",       2,
+               0x5b0,  "addc",         3,
+               0x5b2,  "subc",         3,
+               0x5cc,  "mov",          -2,
+               0x5d8,  "eshro",        3,
+               0x5dc,  "movl",         -2,
+               0x5ec,  "movt",         -2,
+               0x5fc,  "movq",         -2,
+               0x600,  "synmov",       2,
+               0x601,  "synmovl",      2,
+               0x602,  "synmovq",      2,
+               0x603,  "cmpstr",       3,
+               0x604,  "movqstr",      3,
+               0x605,  "movstr",       3,
+               0x610,  "atmod",        3,
+               0x612,  "atadd",        3,
+               0x613,  "inspacc",      -2,
+               0x614,  "ldphy",        -2,
+               0x615,  "synld",        -2,
+               0x617,  "fill",         3,
+               0x630,  "sdma",         3,
+               0x631,  "udma",         0,
+               0x640,  "spanbit",      -2,
+               0x641,  "scanbit",      -2,
+               0x642,  "daddc",        3,
+               0x643,  "dsubc",        3,
+               0x644,  "dmovt",        -2,
+               0x645,  "modac",        3,
+               0x646,  "condrec",      -2,
+               0x650,  "modify",       3,
+               0x651,  "extract",      3,
+               0x654,  "modtc",        3,
+               0x655,  "modpc",        3,
+               0x656,  "receive",      -2,
+               0x659,  "sysctl",       3,
+               0x660,  "calls",        1,
+               0x662,  "send",         3,
+               0x663,  "sendserv",     1,
+               0x664,  "resumprcs",    1,
+               0x665,  "schedprcs",    1,
+               0x666,  "saveprcs",     0,
+               0x668,  "condwait",     1,
+               0x669,  "wait",         1,
+               0x66a,  "signal",       1,
+               0x66b,  "mark",         0,
+               0x66c,  "fmark",        0,
+               0x66d,  "flushreg",     0,
+               0x66f,  "syncf",        0,
+               0x670,  "emul",         3,
+               0x671,  "ediv",         3,
+               0x673,  "ldtime",       -1,
+               0x674,  "Fcvtir",       -2,
+               0x675,  "Fcvtilr",      -2,
+               0x676,  "Fscalerl",     3,
+               0x677,  "Fscaler",      3,
+               0x680,  "Fatanr",       3,
+               0x681,  "Flogepr",      3,
+               0x682,  "Flogr",        3,
+               0x683,  "Fremr",        3,
+               0x684,  "Fcmpor",       2,
+               0x685,  "Fcmpr",        2,
+               0x688,  "Fsqrtr",       -2,
+               0x689,  "Fexpr",        -2,
+               0x68a,  "Flogbnr",      -2,
+               0x68b,  "Froundr",      -2,
+               0x68c,  "Fsinr",        -2,
+               0x68d,  "Fcosr",        -2,
+               0x68e,  "Ftanr",        -2,
+               0x68f,  "Fclassr",      1,
+               0x690,  "Fatanrl",      3,
+               0x691,  "Flogeprl",     3,
+               0x692,  "Flogrl",       3,
+               0x693,  "Fremrl",       3,
+               0x694,  "Fcmporl",      2,
+               0x695,  "Fcmprl",       2,
+               0x698,  "Fsqrtrl",      -2,
+               0x699,  "Fexprl",       -2,
+               0x69a,  "Flogbnrl",     -2,
+               0x69b,  "Froundrl",     -2,
+               0x69c,  "Fsinrl",       -2,
+               0x69d,  "Fcosrl",       -2,
+               0x69e,  "Ftanrl",       -2,
+               0x69f,  "Fclassrl",     1,
+               0x6c0,  "Fcvtri",       -2,
+               0x6c1,  "Fcvtril",      -2,
+               0x6c2,  "Fcvtzri",      -2,
+               0x6c3,  "Fcvtzril",     -2,
+               0x6c9,  "Fmovr",        -2,
+               0x6d9,  "Fmovrl",       -2,
+               0x6e1,  "Fmovre",       -2,
+               0x6e2,  "Fcpysre",      3,
+               0x6e3,  "Fcpyrsre",     3,
+               0x701,  "mulo",         3,
+               0x708,  "remo",         3,
+               0x70b,  "divo",         3,
+               0x741,  "muli",         3,
+               0x748,  "remi",         3,
+               0x749,  "modi",         3,
+               0x74b,  "divi",         3,
+               0x78b,  "Fdivr",        3,
+               0x78c,  "Fmulr",        3,
+               0x78d,  "Fsubr",        3,
+               0x78f,  "Faddr",        3,
+               0x79b,  "Fdivrl",       3,
+               0x79c,  "Fmulrl",       3,
+               0x79d,  "Fsubrl",       3,
+               0x79f,  "Faddrl",       3,
+#define REG_MAX        0x79f
+#define REG_SIZ        ((REG_MAX-REG_MIN+1) * sizeof(struct tabent))
+               0,      NULL,   0
+       };
+
+       if ( reg_tab == NULL ){
+               reg_tab = (struct tabent *) xmalloc( REG_SIZ );
+               bzero( (void *) reg_tab, REG_SIZ );
+               for ( i = 0; reg_init[i].opcode != 0; i++ ){
+                       j = reg_init[i].opcode - REG_MIN;
+                       reg_tab[j].name = reg_init[i].name;
+                       reg_tab[j].numops = reg_init[i].numops;
+               }
+       }
+
+       opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf);
+       i = opcode - REG_MIN;
+
+       if ( (opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL) ){
+               invalid( word1 );
+               return;
+       }
+
+       mnemp = reg_tab[i].name;
+       if ( *mnemp == 'F' ){
+               fp = 1;
+               mnemp++;
+       } else {
+               fp = 0;
+       }
+
+       fputs( mnemp, stream );
+
+       s1   = (word1 >> 5)  & 1;
+       s2   = (word1 >> 6)  & 1;
+       m1   = (word1 >> 11) & 1;
+       m2   = (word1 >> 12) & 1;
+       m3   = (word1 >> 13) & 1;
+       src  =  word1        & 0x1f;
+       src2 = (word1 >> 14) & 0x1f;
+       dst  = (word1 >> 19) & 0x1f;
+
+       if  ( reg_tab[i].numops != 0 ){
+               putc( '\t', stream );
+
+               switch ( reg_tab[i].numops ){
+               case 1:
+                       regop( m1, s1, src, fp );
+                       break;
+               case -1:
+                       dstop( m3, dst, fp );
+                       break;
+               case 2:
+                       regop( m1, s1, src, fp );
+                       putc( ',', stream );
+                       regop( m2, s2, src2, fp );
+                       break;
+               case -2:
+                       regop( m1, s1, src, fp );
+                       putc( ',', stream );
+                       dstop( m3, dst, fp );
+                       break;
+               case 3:
+                       regop( m1, s1, src, fp );
+                       putc( ',', stream );
+                       regop( m2, s2, src2, fp );
+                       putc( ',', stream );
+                       dstop( m3, dst, fp );
+                       break;
+               }
+       }
+}
+
+
+/*
+ * Print out effective address for memb instructions.
+ */
+static void
+ea( memaddr, mode, reg2, reg3, word1, word2 )
+    unsigned long memaddr;
+    int mode;
+    char *reg2, *reg3;
+int word1;
+    unsigned int word2;
+{
+       int scale;
+       static int scale_tab[] = { 1, 2, 4, 8, 16 };
+
+       scale = (word1 >> 7) & 0x07;
+       if ( (scale > 4) || ((word1 >> 5) & 0x03 != 0) ){
+               invalid( word1 );
+               return;
+       }
+       scale = scale_tab[scale];
+
+       switch (mode) {
+       case 4:                                         /* (reg) */
+               fprintf( stream, "(%s)", reg2 );
+               break;
+       case 5:                                         /* displ+8(ip) */
+               print_addr( word2+8+memaddr );
+               break;
+       case 7:                                         /* (reg)[index*scale] */
+               if (scale == 1) {
+                       fprintf( stream, "(%s)[%s]", reg2, reg3 );
+               } else {
+                       fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale);
+               }
+               break;
+       case 12:                                        /* displacement */
+               print_addr( word2 );
+               break;
+       case 13:                                        /* displ(reg) */
+               print_addr( word2 );
+               fprintf( stream, "(%s)", reg2 );
+               break;
+       case 14:                                        /* displ[index*scale] */
+               print_addr( word2 );
+               if (scale == 1) {
+                       fprintf( stream, "[%s]", reg3 );
+               } else {
+                       fprintf( stream, "[%s*%d]", reg3, scale );
+               }
+               break;
+       case 15:                                /* displ(reg)[index*scale] */
+               print_addr( word2 );
+               if (scale == 1) {
+                       fprintf( stream, "(%s)[%s]", reg2, reg3 );
+               } else {
+                       fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale );
+               }
+               break;
+       default:
+               invalid( word1 );
+               return;
+       }
+}
+
+
+/************************************************/
+/* Register Instruction Operand                */
+/************************************************/
+static void
+regop( mode, spec, reg, fp )
+    int mode, spec, reg, fp;
+{
+       if ( fp ){                              /* FLOATING POINT INSTRUCTION */
+               if ( mode == 1 ){                       /* FP operand */
+                       switch ( reg ){
+                       case 0:  fputs( "fp0", stream );        break;
+                       case 1:  fputs( "fp1", stream );        break;
+                       case 2:  fputs( "fp2", stream );        break;
+                       case 3:  fputs( "fp3", stream );        break;
+                       case 16: fputs( "0f0.0", stream );      break;
+                       case 22: fputs( "0f1.0", stream );      break;
+                       default: putc( '?', stream );           break;
+                       }
+               } else {                                /* Non-FP register */
+                       fputs( reg_names[reg], stream );
+               }
+       } else {                                /* NOT FLOATING POINT */
+               if ( mode == 1 ){                       /* Literal */
+                       fprintf( stream, "%d", reg );
+               } else {                                /* Register */
+                       if ( spec == 0 ){
+                               fputs( reg_names[reg], stream );
+                       } else {
+                               fprintf( stream, "sf%d", reg );
+                       }
+               }
+       }
+}
+
+/************************************************/
+/* Register Instruction Destination Operand    */
+/************************************************/
+static void
+dstop( mode, reg, fp )
+    int mode, reg, fp;
+{
+       /* 'dst' operand can't be a literal. On non-FP instructions,  register
+        * mode is assumed and "m3" acts as if were "s3";  on FP-instructions,
+        * sf registers are not allowed so m3 acts normally.
+        */
+        if ( fp ){
+               regop( mode, 0, reg, fp );
+        } else {
+               regop( 0, mode, reg, fp );
+        }
+}
+
+
+static void
+invalid( word1 )
+    int word1;
+{
+       fprintf( stream, ".word\t0x%08x", (unsigned) word1 );
+}      
+
+static void
+print_addr(a)
+int a;
+{
+       fprintf( stream, "0x%x", (unsigned) a );
+}
+
+static void
+put_abs( word1, word2 )
+    unsigned long word1, word2;
+{
+#ifdef IN_GDB
+       return;
+#else
+       int len;
+
+       switch ( (word1 >> 28) & 0xf ){
+       case 0x8:
+       case 0x9:
+       case 0xa:
+       case 0xb:
+       case 0xc:
+               /* MEM format instruction */
+               len = mem( 0, word1, word2, 1 );
+               break;
+       default:
+               len = 4;
+               break;
+       }
+
+       if ( len == 8 ){
+               fprintf( stream, "%08x %08x\t", word1, word2 );
+       } else {
+               fprintf( stream, "%08x         \t", word1 );
+       }
+;
+
+#endif
+}
diff --git a/binutils/m68k-pinsn.c b/binutils/m68k-pinsn.c
new file mode 100644 (file)
index 0000000..b84a869
--- /dev/null
@@ -0,0 +1,809 @@
+/* Print m68k instructions for objdump
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+
+This file is part of the binutils.
+
+The binutils are 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 1, or (at your option)
+any later version.
+
+The binutils are distributed in the hope that they 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 the binutils; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$
+   $Log$
+   Revision 1.1.1.1  1991/03/21 21:26:46  gumby
+   Back from Intel with Steve
+
+ * Revision 1.1  1991/03/21  21:26:45  gumby
+ * Initial revision
+ *
+ * Revision 1.1  1991/03/13  00:34:06  chrisb
+ * Initial revision
+ *
+ * Revision 1.4  1991/03/09  04:36:34  rich
+ *  Modified Files:
+ *     sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
+ *     binutils.h
+ *
+ * Pulled sysdep.h out of bfd.h.
+ *
+ * Revision 1.3  1991/03/08  21:54:45  rich
+ *  Modified Files:
+ *     Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
+ *     i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
+ *     sparc-pinsn.c strip.c
+ *
+ * Verifying Portland tree with steve's last changes.  Also, some partial
+ * porting.
+ *
+ * Revision 1.2  1991/03/08  07:46:24  sac
+ * Added -l option to disassembly - prints line numbers too.
+ *
+ * Revision 1.1  1991/02/22  16:48:02  sac
+ * Initial revision
+ *
+*/
+
+#include <stdio.h>
+#include "sysdep.h"
+#include "bfd.h"
+#include "m68k-opcode.h"
+
+extern int fputs();
+extern void print_address();
+
+/* 68k instructions are never longer than this many bytes.  */
+#define MAXLEN 22
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
+
+extern char *reg_names[];
+char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
+                    "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
+
+char *reg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", "ps", "pc"};
+static unsigned char *print_insn_arg ();
+static unsigned char *print_indexed ();
+static void print_base ();
+static int fetch_arg ();
+
+#define NEXTBYTE(p)  (p += 2, ((char *)p)[-1])
+
+#define NEXTWORD(p)  \
+  (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
+
+#define NEXTLONG(p)  \
+  (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+#define NEXTSINGLE(p) \
+  (p += 4, *((float *)(p - 4)))
+
+#define NEXTDOUBLE(p) \
+  (p += 8, *((double *)(p - 8)))
+
+#define NEXTEXTEND(p) \
+  (p += 12, 0.0)       /* Need a function to convert from extended to double
+                          precision... */
+
+#define NEXTPACKED(p) \
+  (p += 12, 0.0)       /* Need a function to convert from packed to double
+                          precision.   Actually, it's easier to print a
+                          packed number than a double anyway, so maybe
+                          there should be a special case to handle this... */
+\f
+/* Print the m68k instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn_m68k(addr, buffer, stream)
+     bfd_vma addr;
+unsigned    char *buffer;
+     FILE *stream;
+{
+  register unsigned int i;
+  register unsigned char *p;
+  register char *d;
+  register unsigned int bestmask;
+  int best;
+
+
+
+  bestmask = 0;
+  best = -1;
+  for (i = 0; i < NOPCODES; i++)
+    {
+      register unsigned int opcode = m68k_opcodes[i].opcode;
+      register unsigned int match = m68k_opcodes[i].match;
+      if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
+         && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
+         && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
+         && ((0xff & buffer[3] & match) == (0xff & opcode)))
+       {
+         /* Don't use for printout the variants of divul and divsl
+            that have the same register number in two places.
+            The more general variants will match instead.  */
+         for (d = m68k_opcodes[i].args; *d; d += 2)
+           if (d[1] == 'D')
+             break;
+
+         /* Don't use for printout the variants of most floating
+            point coprocessor instructions which use the same
+            register number in two places, as above. */
+         if (*d == 0)
+           for (d = m68k_opcodes[i].args; *d; d += 2)
+             if (d[1] == 't')
+               break;
+
+         if (*d == 0 && match > bestmask)
+           {
+             best = i;
+             bestmask = match;
+           }
+       }
+    }
+
+  /* Handle undefined instructions.  */
+  if (best < 0)
+    {
+      fprintf (stream, "0%o", (unsigned) (buffer[0] << 8) + buffer[1]);
+      return 2;
+    }
+
+  fprintf (stream, "%s", m68k_opcodes[best].name);
+
+  /* Point at first word of argument data,
+     and at descriptor for first argument.  */
+  p = buffer + 2;
+  
+  /* Why do this this way? -MelloN */
+  for (d = m68k_opcodes[best].args; *d; d += 2)
+    {
+      if (d[0] == '#')
+       {
+         if (d[1] == 'l' && p - buffer < 6)
+           p = buffer + 6;
+         else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
+           p = buffer + 4;
+       }
+      if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
+       p = buffer + 4;
+      if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
+       p = buffer + 6;
+      if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
+       p = buffer + 4;
+    }
+
+  d = m68k_opcodes[best].args;
+
+  if (*d)
+    fputs (" ", stream);
+
+  while (*d)
+    {
+      p = print_insn_arg (d, buffer, p, addr + p - buffer, stream);
+      d += 2;
+      if (*d && *(d - 2) != 'I' && *d != 'k')
+       fputs (",", stream);
+    }
+  return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, buffer, p, addr, stream)
+     char *d;
+     unsigned char *buffer;
+     register unsigned char *p;
+ bfd_vma addr;         /* PC for this arg to be relative to */
+     FILE *stream;
+{
+  register int val;
+  register int place = d[1];
+  int regno;
+  register char *regname;
+  register unsigned char *p1;
+  register double flval;
+  int flt_p;
+
+  switch (*d)
+    {
+    case 'C':
+      fprintf (stream, "ccr");
+      break;
+
+    case 'S':
+      fprintf (stream, "sr");
+      break;
+
+    case 'U':
+      fprintf (stream, "usp");
+      break;
+
+    case 'J':
+      {
+       static struct { char *name; int value; } names[]
+         = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
+            {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
+            {"msp", 0x803}, {"isp", 0x804}};
+
+       val = fetch_arg (buffer, place, 12);
+       for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
+         if (names[regno].value == val)
+           {
+             fprintf (stream, names[regno].name);
+             break;
+           }
+       if (regno < 0)
+         fprintf (stream, "%d", val);
+      }
+      break;
+
+    case 'Q':
+      val = fetch_arg (buffer, place, 3);
+      if (val == 0) val = 8;
+      fprintf (stream, "#%d", val);
+      break;
+
+    case 'M':
+      val = fetch_arg (buffer, place, 8);
+      if (val & 0x80)
+       val = val - 0x100;
+      fprintf (stream, "#%d", val);
+      break;
+
+    case 'T':
+      val = fetch_arg (buffer, place, 4);
+      fprintf (stream, "#%d", val);
+      break;
+
+    case 'D':
+      fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
+      break;
+
+    case 'A':
+      fprintf (stream, "%s",
+                       reg_names[fetch_arg (buffer, place, 3) + 010]);
+      break;
+
+    case 'R':
+      fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
+      break;
+
+    case 'F':
+      fprintf (stream, "fp%d", fetch_arg (buffer, place, 3));
+      break;
+
+    case 'O':
+      val = fetch_arg (buffer, place, 6);
+      if (val & 0x20)
+       fprintf (stream, "%s", reg_names [val & 7]);
+      else
+       fprintf (stream, "%d", val);
+      break;
+
+    case '+':
+      fprintf (stream, "%s@+",
+                       reg_names[fetch_arg (buffer, place, 3) + 8]);
+      break;
+
+    case '-':
+      fprintf (stream, "%s@-",
+              reg_names[fetch_arg (buffer, place, 3) + 8]);
+      break;
+
+    case 'k':
+      if (place == 'k')
+       fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
+      else if (place == 'C')
+       {
+         val = fetch_arg (buffer, place, 7);
+         if ( val > 63 )               /* This is a signed constant. */
+           val -= 128;
+         fprintf (stream, "{#%d}", val);
+       }
+      else
+       fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+              *d, place);
+      break;
+
+    case '#':
+    case '^':
+      p1 = buffer + (*d == '#' ? 2 : 4);
+      if (place == 's')
+       val = fetch_arg (buffer, place, 4);
+      else if (place == 'C')
+       val = fetch_arg (buffer, place, 7);
+      else if (place == '8')
+       val = fetch_arg (buffer, place, 3);
+      else if (place == '3')
+       val = fetch_arg (buffer, place, 8);
+      else if (place == 'b')
+       val = NEXTBYTE (p1);
+      else if (place == 'w')
+       val = NEXTWORD (p1);
+      else if (place == 'l')
+       val = NEXTLONG (p1);
+      else
+       fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+              *d, place);
+      fprintf (stream, "#%d", val);
+      break;
+
+    case 'B':
+      if (place == 'b')
+       val = NEXTBYTE (p);
+      else if (place == 'w')
+       val = NEXTWORD (p);
+      else if (place == 'l')
+       val = NEXTLONG (p);
+      else if (place == 'g')
+       {
+         val = ((char *)buffer)[1];
+         if (val == 0)
+           val = NEXTWORD (p);
+         else if (val == -1)
+           val = NEXTLONG (p);
+       }
+      else if (place == 'c')
+       {
+         if (buffer[1] & 0x40)         /* If bit six is one, long offset */
+           val = NEXTLONG (p);
+         else
+           val = NEXTWORD (p);
+       }
+      else
+       fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+              *d, place);
+      print_address (addr + val, stream);
+      break;
+
+    case 'd':
+      val = NEXTWORD (p);
+      fprintf (stream, "%s@(%d)",
+                       reg_names[fetch_arg (buffer, place, 3)], val);
+      break;
+
+    case 's':
+      fprintf (stream, "%s",
+                       fpcr_names[fetch_arg (buffer, place, 3)]);
+      break;
+
+    case 'I':
+      val = fetch_arg (buffer, 'd', 3);                  /* Get coprocessor ID... */
+      if (val != 1)                            /* Unusual coprocessor ID? */
+       fprintf (stream, "(cpid=%d) ", val);
+      if (place == 'i')
+       p += 2;                      /* Skip coprocessor extended operands */
+      break;
+
+    case '*':
+    case '~':
+    case '%':
+    case ';':
+    case '@':
+    case '!':
+    case '$':
+    case '?':
+    case '/':
+    case '&':
+
+      if (place == 'd')
+       {
+         val = fetch_arg (buffer, 'x', 6);
+         val = ((val & 7) << 3) + ((val >> 3) & 7);
+       }
+      else
+       val = fetch_arg (buffer, 's', 6);
+
+      /* Get register number assuming address register.  */
+      regno = (val & 7) + 8;
+      regname = reg_names[regno];
+      switch (val >> 3)
+       {
+       case 0:
+         fprintf (stream, "%s", reg_names[val]);
+         break;
+
+       case 1:
+         fprintf (stream, "%s", regname);
+         break;
+
+       case 2:
+         fprintf (stream, "%s@", regname);
+         break;
+
+       case 3:
+         fprintf (stream, "%s@+", regname);
+         break;
+
+       case 4:
+         fprintf (stream, "%s@-", regname);
+         break;
+
+       case 5:
+         val = NEXTWORD (p);
+         fprintf (stream, "%s@(%d)", regname, val);
+         break;
+
+       case 6:
+         p = print_indexed (regno, p, addr, stream);
+         break;
+
+       case 7:
+         switch (val & 7)
+           {
+           case 0:
+             val = NEXTWORD (p);
+             fprintf (stream, "@#");
+             print_address (val, stream);
+             break;
+
+           case 1:
+             val = NEXTLONG (p);
+             fprintf (stream, "@#");
+             print_address (val, stream);
+             break;
+
+           case 2:
+             val = NEXTWORD (p);
+             print_address (addr + val, stream);
+             break;
+
+           case 3:
+             p = print_indexed (-1, p, addr, stream);
+             break;
+
+           case 4:
+             flt_p = 1;        /* Assume it's a float... */
+             switch( place )
+             {
+               case 'b':
+                 val = NEXTBYTE (p);
+                 flt_p = 0;
+                 break;
+
+               case 'w':
+                 val = NEXTWORD (p);
+                 flt_p = 0;
+                 break;
+
+               case 'l':
+                 val = NEXTLONG (p);
+                 flt_p = 0;
+                 break;
+
+               case 'f':
+                 flval = NEXTSINGLE(p);
+                 break;
+
+               case 'F':
+                 flval = NEXTDOUBLE(p);
+                 break;
+
+               case 'x':
+                 flval = NEXTEXTEND(p);
+                 break;
+
+               case 'p':
+                 flval = NEXTPACKED(p);
+                 break;
+
+               default:
+                 fprintf(stderr, "Invalid arg format in opcode table: \"%c%c\".",
+                      *d, place);
+             }
+             if ( flt_p )      /* Print a float? */
+               fprintf (stream, "#%g", flval);
+             else
+               fprintf (stream, "#%d", val);
+             break;
+
+           default:
+             fprintf (stream, "<invalid address mode 0%o>", (unsigned) val);
+           }
+       }
+      break;
+
+    case 'L':
+    case 'l':
+       if (place == 'w')
+         {
+           char doneany;
+           p1 = buffer + 2;
+           val = NEXTWORD (p1);
+           /* Move the pointer ahead if this point is farther ahead
+              than the last.  */
+           p = p1 > p ? p1 : p;
+           if (val == 0)
+             {
+               fputs ("#0", stream);
+               break;
+             }
+           if (*d == 'l')
+             {
+               register int newval = 0;
+               for (regno = 0; regno < 16; ++regno)
+                 if (val & (0x8000 >> regno))
+                   newval |= 1 << regno;
+               val = newval;
+             }
+           val &= 0xffff;
+           doneany = 0;
+           for (regno = 0; regno < 16; ++regno)
+             if (val & (1 << regno))
+               {
+                 int first_regno;
+                 if (doneany)
+                   fputs ("/", stream);
+                 doneany = 1;
+                 fprintf (stream, "%s", reg_names[regno]);
+                 first_regno = regno;
+                 while (val & (1 << (regno + 1)))
+                   ++regno;
+                 if (regno > first_regno)
+                   fprintf (stream, "-%s", reg_names[regno]);
+               }
+         }
+       else if (place == '3')
+         {
+           /* `fmovem' insn.  */
+           char doneany;
+           val = fetch_arg (buffer, place, 8);
+           if (val == 0)
+             {
+               fputs ("#0", stream);
+               break;
+             }
+           if (*d == 'l')
+             {
+               register int newval = 0;
+               for (regno = 0; regno < 8; ++regno)
+                 if (val & (0x80 >> regno))
+                   newval |= 1 << regno;
+               val = newval;
+             }
+           val &= 0xff;
+           doneany = 0;
+           for (regno = 0; regno < 8; ++regno)
+             if (val & (1 << regno))
+               {
+                 int first_regno;
+                 if (doneany)
+                   fputs ("/", stream);
+                 doneany = 1;
+                 fprintf (stream, "fp%d", regno);
+                 first_regno = regno;
+                 while (val & (1 << (regno + 1)))
+                   ++regno;
+                 if (regno > first_regno)
+                   fprintf (stream, "-fp%d", regno);
+               }
+         }
+       else
+         abort ();
+      break;
+
+    default:
+      fprintf(stderr, "Invalid arg format in opcode table: \"%c\".", *d);
+    }
+
+  return (unsigned char *) p;
+}
+
+/* Fetch BITS bits from a position in the instruction specified by CODE.
+   CODE is a "place to put an argument", or 'x' for a destination
+   that is a general address (mode and register).
+   BUFFER contains the instruction.  */
+
+static int
+fetch_arg (buffer, code, bits)
+     unsigned char *buffer;
+     char code;
+     int bits;
+{
+  register int val;
+  switch (code)
+    {
+    case 's':
+      val = buffer[1];
+      break;
+
+    case 'd':                  /* Destination, for register or quick.  */
+      val = (buffer[0] << 8) + buffer[1];
+      val >>= 9;
+      break;
+
+    case 'x':                  /* Destination, for general arg */
+      val = (buffer[0] << 8) + buffer[1];
+      val >>= 6;
+      break;
+
+    case 'k':
+      val = (buffer[3] >> 4);
+      break;
+
+    case 'C':
+      val = buffer[3];
+      break;
+
+    case '1':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 12;
+      break;
+
+    case '2':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 6;
+      break;
+
+    case '3':
+    case 'j':
+      val = (buffer[2] << 8) + buffer[3];
+      break;
+
+    case '4':
+      val = (buffer[4] << 8) + buffer[5];
+      val >>= 12;
+      break;
+
+    case '5':
+      val = (buffer[4] << 8) + buffer[5];
+      val >>= 6;
+      break;
+
+    case '6':
+      val = (buffer[4] << 8) + buffer[5];
+      break;
+
+    case '7':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 7;
+      break;
+      
+    case '8':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 10;
+      break;
+
+    default:
+      abort ();
+    }
+
+  switch (bits)
+    {
+    case 3:
+      return val & 7;
+    case 4:
+      return val & 017;
+    case 5:
+      return val & 037;
+    case 6:
+      return val & 077;
+    case 7:
+      return val & 0177;
+    case 8:
+      return val & 0377;
+    case 12:
+      return val & 07777;
+    default:
+      abort ();
+      return(0);
+    }
+} /* fetch_arg() */
+
+/* Print an indexed argument.  The base register is BASEREG (-1 for pc).
+   P points to extension word, in buffer.
+   ADDR is the nominal core address of that extension word.  */
+
+static unsigned char *
+print_indexed (basereg, p, addr, stream)
+     int basereg;
+     unsigned char *p;
+     FILE *stream;
+bfd_vma addr;
+{
+  register int word;
+  static char *scales[] = {"", "*2", "*4", "*8"};
+  register int base_disp;
+  register int outer_disp;
+  char buf[40];
+
+  word = NEXTWORD (p);
+
+  /* Generate the text for the index register.
+     Where this will be output is not yet determined.  */
+  sprintf (buf, "[%s.%c%s]",
+          reg_names[(word >> 12) & 0xf],
+          (word & 0x800) ? 'l' : 'w',
+          scales[(word >> 9) & 3]);
+
+  /* Handle the 68000 style of indexing.  */
+
+  if ((word & 0x100) == 0)
+    {
+      print_base (basereg,
+                 ((word & 0x80) ? word | 0xff00 : word & 0xff)
+                 + ((basereg == -1) ? addr : 0),
+                 stream);
+      fputs (buf, stream);
+      return p;
+    }
+
+  /* Handle the generalized kind.  */
+  /* First, compute the displacement to add to the base register.  */
+
+  if (word & 0200)
+    basereg = -2;
+  if (word & 0100)
+    buf[0] = 0;
+  base_disp = 0;
+  switch ((word >> 4) & 3)
+    {
+    case 2:
+      base_disp = NEXTWORD (p);
+      break;
+    case 3:
+      base_disp = NEXTLONG (p);
+    }
+  if (basereg == -1)
+    base_disp += addr;
+
+  /* Handle single-level case (not indirect) */
+
+  if ((word & 7) == 0)
+    {
+      print_base (basereg, base_disp, stream);
+      fputs (buf, stream);
+      return p;
+    }
+
+  /* Two level.  Compute displacement to add after indirection.  */
+
+  outer_disp = 0;
+  switch (word & 3)
+    {
+    case 2:
+      outer_disp = NEXTWORD (p);
+      break;
+    case 3:
+      outer_disp = NEXTLONG (p);
+    }
+
+  fprintf (stream, "%d(", outer_disp);
+  print_base (basereg, base_disp, stream);
+
+  /* If postindexed, print the closeparen before the index.  */
+  if (word & 4)
+    fprintf (stream, ")%s", buf);
+  /* If preindexed, print the closeparen after the index.  */
+  else
+    fprintf (stream, "%s)", buf);
+
+  return p;
+}
+
+/* Print a base register REGNO and displacement DISP, on STREAM.
+   REGNO = -1 for pc, -2 for none (suppressed).  */
+
+static void
+print_base (regno, disp, stream)
+     int regno;
+     int disp;
+     FILE *stream;
+{
+  if (regno == -2)
+    fprintf (stream, "%d", disp);
+  else if (regno == -1)
+    fprintf (stream, "0x%x", (unsigned) disp);
+  else
+    fprintf (stream, "%d(%s)", disp, reg_names[regno]);
+}
diff --git a/binutils/nm.c b/binutils/nm.c
new file mode 100644 (file)
index 0000000..ac490f7
--- /dev/null
@@ -0,0 +1,387 @@
+/*** nm.c -- Describe symbol table of a rel file. */
+#include "sysdep.h"
+#include "bfd.h"
+#include "getopt.h"
+#include "stab.gnu.h"
+#include <ranlib.h>
+
+
+
+PROTO(static boolean, display_file, (char *filename));
+PROTO(static boolean, do_one_rel_file, (bfd *file));
+PROTO(static unsigned int, filter_symbols, (bfd *file, asymbol **syms,
+                                        unsigned long symcount));
+
+PROTO(static void, print_symbols, (bfd *file, asymbol **syms,
+                                    unsigned long symcount));
+extern PROTO(int, (*sorters[2][2]), (char *x, char *y));
+PROTO(static void, print_symdef_entry, (bfd * abfd));
+
+/* Command options.  */
+
+int external_only = 0; /* print external symbols only */
+int file_on_each_line = 0; /* print file name on each line */
+int no_sort = 0;       /* don't sort; print syms in order found */
+int print_debug_syms = 0; /* print debugger-only symbols too */
+int print_armap = 0;   /* describe __.SYMDEF data in archive files.  */
+int reverse_sort = 0;  /* sort in downward(alpha or numeric) order */
+int sort_numerically = 0; /* sort in numeric rather than alpha order */
+int undefined_only = 0;        /* print undefined symbols only */
+
+boolean print_each_filename = false; /* Ick.  Used in archives. */
+
+/* IMPORT */
+extern char *program_name;
+extern char *program_version;
+extern char *target;
+
+struct option long_options[] = {
+       {"debug-syms",      0, &print_debug_syms,  1},
+       {"extern-only",     0, &external_only,     1},
+       {"no-sort",         0, &no_sort,           1},
+       {"numeric-sort",    0, &sort_numerically,  1},
+       {"print-armap",     0, &print_armap,       1},
+       {"print-file-name", 0, &file_on_each_line, 1},
+       {"reverse-sort",    0, &reverse_sort,      1},
+       {"target",          2, NULL,               NULL},
+       {"undefined-only",  0, &undefined_only,    1},
+       {0, 0, 0, 0}
+};
+\f
+/* Some error-reporting functions */
+
+void
+usage ()
+{
+  fprintf(stderr, "nm %s\nUsage: %s [-agnoprsu] filename...\n",
+         program_version, program_name);
+  exit(0);
+}
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c; /* sez which option char */
+  int ind = 0; /* used by getopt and ignored by us */
+  extern int optind; /* steps thru options */
+       
+  program_name = *argv;
+       
+  while ((c = getopt_long(argc, argv, "agnoprsu", long_options, &ind)) != EOF) {
+    switch (c) {
+    case 'a': print_debug_syms = 1; break;
+    case 'g': external_only = 1; break;
+    case 'n': sort_numerically = 1; break;
+    case 'o': file_on_each_line = 1; break;
+    case 'p': no_sort = 1; break;
+    case 'r': reverse_sort = 1; break;
+    case 's': print_armap = 1; break;
+    case 'u': undefined_only = 1; break;
+                       
+    case  0:
+      if (!strcmp("target",(long_options[option_index]).name)) {
+       target = optarg;
+      }
+                       
+      break; /* we've been given a long option */
+                       
+    default:
+      usage ();
+    }
+  }
+       
+  /* Strangely, for the shell you should return only a nonzero value
+     on sucess -- the inverse of the C sense. */
+  
+  /* OK, all options now parsed.  If no filename specified, do a.out. */
+  if (optind == argc) return !display_file ("a.out");
+  
+  /* We were given several filenames to do: */
+  while (optind < argc)
+    if (!display_file (argv[optind++])) return 1;
+
+  return 0;
+}
+\f
+/** Display a file's stats */
+
+/* goto here is marginally cleaner than the nested if syntax */
+
+static boolean
+display_file (filename)
+     char *filename;
+{
+  boolean retval = false;
+  bfd *file;
+  bfd *arfile = NULL;
+       
+  file = bfd_openr(filename, target);
+  if (file == NULL) {
+    bfd_fatal (filename);
+  }
+
+  if (bfd_check_format(file, bfd_object)) {
+    retval = do_one_rel_file (file);
+    goto closer;
+  }
+
+  if (!bfd_check_format (file, bfd_archive)) {
+    fprintf (stderr, "%s:  %s: unknown format.\n", program_name, filename);
+    retval = false;
+    goto closer;
+  }
+
+  printf("In archive %s:\n", filename);
+  if (print_armap) print_symdef_entry (file);
+  for (;;) {
+    arfile = bfd_openr_next_archived_file (file, arfile);
+
+    if (arfile == NULL) {
+      if (bfd_error != no_more_archived_files)
+       bfd_fatal (filename);
+      goto closer;
+    }
+                       
+    if (!bfd_check_format(arfile, bfd_object))
+      printf("%s: not an object file\n", arfile->filename);
+    else {
+      printf ("\n%s:\n", arfile->filename);
+      if (!do_one_rel_file (arfile)) return false;
+    }
+  }
+
+ closer:
+  if (bfd_close(file) == false)
+    bfd_fatal (filename);
+
+  return retval;
+}
+\f
+
+static boolean
+do_one_rel_file (abfd)
+     bfd *abfd;
+{
+  unsigned int storage;
+  asymbol **syms;
+  unsigned int symcount = 0;
+
+  if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) {
+    (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
+    return true;
+  }
+
+      
+  storage = get_symtab_upper_bound (abfd);
+  if (storage == 0) {
+  nosymz:
+    fprintf (stderr, "%s: Symflags set but there are none?\n",
+            bfd_get_filename (abfd));
+    exit (1);
+  }
+
+  syms = (asymbol **) xmalloc (storage);
+
+  symcount = bfd_canonicalize_symtab (abfd, syms);
+  if (symcount == 0) goto nosymz;
+
+  /* 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, syms, symcount);
+       
+  if (!no_sort) 
+    qsort((char *) syms, symcount, sizeof (asymbol *),
+         sorters[sort_numerically][reverse_sort]);
+
+  if (print_each_filename && !file_on_each_line)
+    printf("\n%s:\n", bfd_get_filename(abfd));
+       
+  print_symbols (abfd, syms, symcount);
+  free (syms);
+  return true;
+}
+\f
+/* Symbol-sorting predicates */
+#define valueof(x)  ((x)->section ? (x)->section->vma + (x)->value : (x)->value)
+int
+numeric_forward (x, y)
+     char *x;
+     char *y;
+{
+
+  return (valueof(*(asymbol **)x) - valueof(*(asymbol **) y));;
+}
+
+int
+numeric_reverse (x, y)
+     char *x;
+     char *y;
+{
+  return (valueof(*(asymbol **)y) - valueof(*(asymbol **) x));
+
+}
+
+int
+non_numeric_forward (x, y)
+     char *x;
+     char *y;
+{
+  char *xn = (*(asymbol **) x)->name;
+  char *yn = (*(asymbol **) y)->name;
+
+  return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
+         ((yn == NULL) ? 1 : strcmp (xn, yn)));
+}
+
+int
+non_numeric_reverse (x, y)
+     char *x;
+     char *y;
+{
+  return -(non_numeric_forward (x, y));
+}
+
+int (*sorters[2][2])() = {
+       {non_numeric_forward, non_numeric_reverse},
+       {numeric_forward, numeric_reverse},
+};
+\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 unsigned int
+filter_symbols (abfd, syms, symcount)
+     bfd *abfd;
+     asymbol **syms;
+     unsigned long symcount;
+{
+  asymbol **from, **to;
+  unsigned int dst_count = 0;
+  unsigned int src_count;
+  for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
+    int keep = 0;
+    flagword flags = (from[src_count])->flags;
+
+    if (undefined_only) {
+      keep = (flags & BSF_UNDEFINED);
+    } else if (external_only) {
+      keep = ((flags & BSF_GLOBAL) || (flags & BSF_UNDEFINED) ||
+             (flags & BSF_FORT_COMM));
+    } else {
+      keep = 1;
+    }
+               
+    if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) {
+      keep = 0;
+    }
+
+    if (keep) {
+      to[dst_count++] = from[src_count];
+    }
+  }
+       
+  return dst_count;
+}
+\f
+
+/* Return a lower-case character corresponding to the symbol class of sym */
+char
+decode_symclass (sym)
+     asymbol *sym;
+{
+  flagword flags = sym->flags;
+  
+  if ((sym->value == 0) && (sym->section != NULL))
+    /* Huh?  All section names don't begin with "." */
+    return (sym->section->name)[1];
+
+  if (flags & BSF_FORT_COMM) return 'C';
+  if (flags & BSF_UNDEFINED) return 'U';
+  if (flags & BSF_ABSOLUTE)  return 'a';
+
+   if ( (flags & BSF_GLOBAL) || (flags & BSF_LOCAL) ){
+     if ( !strcmp(sym->section->name, ".text") ){
+       return 't';
+     } else if ( !strcmp(sym->section->name, ".data") ){
+       return 'd';
+     } else if ( !strcmp(sym->section->name, ".bss") ){
+       return 'b';
+     } else {
+       return 'o';
+     }
+    }
+
+  /* We don't have to handle these cases just yet, but we will soon:
+     N_SETV: 'v'; 
+     N_SETA: 'l'; 
+     N_SETT: 'x';
+     N_SETD: 'z';
+     N_SETB: 's';
+     N_INDR: 'i';
+     */
+  return '?';
+}
+
+static void
+print_symbols (abfd, syms, symcount)
+     bfd *abfd;
+     asymbol **syms;
+     unsigned long symcount;
+{
+  asymbol **sym = syms, **end = syms + symcount;
+  char class;
+
+  for (; sym < end; ++sym) {
+    if (file_on_each_line) printf("%s:", bfd_get_filename(abfd));
+
+    if (undefined_only) {
+      if ((*sym)->flags & BSF_UNDEFINED)
+       puts ((*sym)->name);
+    }
+    else {
+      asymbol *p = *sym;
+      if (p) {
+      class = decode_symclass (p);
+
+      if (p->flags & BSF_GLOBAL)
+       class = toupper (class);
+      
+      if (p->value || ((p->flags & BSF_UNDEFINED) !=  BSF_UNDEFINED))
+       printf ("%08lx ", (p->section ? p->value + p->section->vma : p->value));
+      else fputs ("         ", stdout);
+
+      printf ("%c %s\n", class, p->name);
+    }
+    }
+  }
+}
+
+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 (thesym->name != (char *)NULL) {
+    printf ("%s in %s\n", thesym->name, bfd_get_filename (elt));
+}
+  }
+}
diff --git a/binutils/objdump.c b/binutils/objdump.c
new file mode 100644 (file)
index 0000000..352adc3
--- /dev/null
@@ -0,0 +1,714 @@
+/*** objdump.c -- dump information about an object file. */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* 
+   $Id$
+   $Log$
+   Revision 1.1  1991/03/21 21:26:48  gumby
+   Initial revision
+
+ * Revision 1.2  1991/03/15  18:34:14  rich
+ * foo
+ *
+ * Revision 1.1  1991/03/13  00:34:19  chrisb
+ * Initial revision
+ *
+ * Revision 1.9  1991/03/09  04:36:33  rich
+ *  Modified Files:
+ *     sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
+ *     binutils.h
+ *
+ * Pulled sysdep.h out of bfd.h.
+ *
+ * Revision 1.8  1991/03/09  03:42:01  rich
+ *  Modified Files:
+ *     Makefile alloca.c ar.c i960-pinsn.c nm.c objdump.c ostrip.c
+ *     strip.c
+ *
+ * Ports for intel960 group Portland.
+ *
+ * Revision 1.7  1991/03/08  21:54:47  rich
+ *  Modified Files:
+ *     Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
+ *     i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
+ *     sparc-pinsn.c strip.c
+ *
+ * Verifying Portland tree with steve's last changes.  Also, some partial
+ * porting.
+ *
+ * Revision 1.6  1991/03/08  07:46:26  sac
+ * Added -l option to disassembly - prints line numbers too.
+ *
+ * Revision 1.5  1991/03/07  21:50:24  sac
+ * More intelligent reloc printing
+ *
+ * Revision 1.4  1991/03/05  16:36:54  sac
+ * Fixed bug where empty symbols would print (null) on suns and crash elsewhere.
+ *
+*/
+/*
+ * Until there is other documentation, refer to the manual page dump(1) in
+ * the system 5 program's reference manual
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "getopt.h"
+#include <stdio.h>
+#include <ctype.h>
+
+char *malloc();
+char *realloc();
+char *xmalloc();
+
+char *default_target = NULL;   /* default at runtime */
+
+char *program_name = NULL;
+
+int dump_section_contents;     /* -s */
+int dump_section_headers;      /* -h */
+boolean dump_file_header;      /* -f */
+int dump_symtab;               /* -t */
+int dump_reloc_info;           /* -r */
+int dump_ar_hdrs;              /* -a */
+int with_line_numbers;          /* -l */
+boolean disassemble;             /* -d */
+char *only;
+
+PROTO (void, display_file, (char *filename, char *target));
+PROTO (void, dump_data, (bfd *abfd));
+PROTO (void, dump_relocs, (bfd *abfd));
+PROTO (void, dump_symbols, (bfd *abfd));
+PROTO (void, print_arelt_descr, (bfd *abfd, boolean verbose));
+
+
+
+
+
+
+\f
+char *machine = (char *)NULL;
+  asymbol **syms;
+  asymbol **syms2;
+
+
+unsigned int storage;
+
+unsigned int symcount = 0;
+
+void
+usage ()
+{
+  fprintf (stderr,
+          "usage: %s [-ahfdrtxsl] [-m machine] [-j section_name] obj ...\n",
+          program_name);
+  exit (1);
+}
+
+static struct option long_options[] = 
+       {{"syms",   0, &dump_symtab,          1},
+        {"reloc",  0, &dump_reloc_info,      1},
+        {"header", 0, &dump_section_headers, 1},
+        {0, 0, 0, 0}};
+
+
+
+static void
+dump_headers(abfd)
+bfd *abfd;
+{
+  asection *section;
+  for (section = abfd->sections;
+       section != (asection *) NULL;
+       section = section->next) 
+    {
+      char *comma = "";
+#define PF(x,y) \
+      if (section->flags & x) {  printf("%s%s",comma,y); comma = ", "; }
+
+      printf("SECTION %d [%s]\t: size %08x",
+            section->index,
+            section->name,
+(unsigned)     section->size);
+      printf(" vma %08lx align 2**%2u\n ",
+            section->vma,
+            section->alignment_power);
+      PF(SEC_ALLOC,"ALLOC");
+      PF(SEC_LOAD,"LOAD");
+      PF(SEC_RELOC,"RELOC");
+      PF(SEC_BALIGN,"BALIGN");
+      PF(SEC_READONLY,"READONLY");
+      PF(SEC_CODE,"CODE");
+      PF(SEC_DATA,"DATA");
+      PF(SEC_ROM,"ROM");
+      printf("\n");
+#undef PF
+    }
+}
+
+static asymbol **
+slurp_symtab(abfd)
+bfd *abfd;
+{
+  asymbol **sy;
+  if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) {
+    (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
+    return(NULL);
+  }
+
+  storage = get_symtab_upper_bound (abfd);
+  if (storage) {
+    sy = (asymbol **) malloc (storage);
+    if (sy == NULL) {
+      fprintf (stderr, "%s: out of memory.\n", program_name);
+      exit (1);
+    }
+  }
+  symcount = bfd_canonicalize_symtab (abfd, sy);
+return sy;
+}
+/* Sort symbols into value order */
+static int comp(ap,bp)
+asymbol **ap;
+asymbol **bp;
+{
+  asymbol *a = *ap;
+  asymbol *b = *bp;
+  int diff;
+
+  if ( a->name== (char *)NULL || (a->flags &( BSF_DEBUGGING| BSF_UNDEFINED) )) 
+    a->the_bfd = 0;
+  if  ( b->name== (char *)NULL || (b->flags &( BSF_DEBUGGING|BSF_UNDEFINED))) 
+    b->the_bfd =0;
+
+  diff = a->the_bfd - b->the_bfd;
+  if (diff) {
+    return -diff;
+  }
+  diff = a->value - b->value;
+  if (diff) {
+    return diff;
+  }
+  return   a->section - b->section;
+}
+
+/* Print the supplied address symbolically if possible */
+void
+print_address(vma, stream)
+bfd_vma vma;
+FILE *stream;
+{
+  /* Perform a binary search looking for the closest symbol to
+     the required value */
+
+  unsigned int min = 0;
+  unsigned int max = symcount;
+
+  unsigned int thisplace = 1;
+  unsigned int oldthisplace ;
+
+  int vardiff;
+  if (symcount == 0)
+    fprintf(stream,"%08lx", vma);
+  else {
+    while (true) {
+      oldthisplace = thisplace;
+      thisplace = (max + min )/2  ;
+      if (thisplace == oldthisplace) break;
+
+
+       vardiff = syms[thisplace]->value - vma;
+
+      if (vardiff) {
+       if (vardiff > 0) {
+         max = thisplace;
+       }
+       else {
+         min = thisplace;
+       }
+      }
+      else {
+       /* Totally awesome! the exact right symbol */
+       fprintf(stream,"%08lx (%s)", vma, syms[thisplace]->name);
+       return;
+      }
+    }
+    /* We've run out of places to look, print the symbol before this one */
+    /* see if this or the symbol before describes this location the best */
+
+    if (thisplace != 0) {
+      if (syms[thisplace-1]->value - vma >
+         syms[thisplace]->value-vma) {
+       /* Previous symbol is in correct section and is closer */
+       thisplace --;
+      }
+    }
+    
+    {
+      char *section_name;
+      asection *sec = syms[thisplace]->section;
+      if (sec) {
+       section_name = sec->name;
+      }
+      else {
+       section_name = "abs";
+      }
+    }
+    if (syms[thisplace]->value > vma) {
+      fprintf(stream,"%08lx (%s-%lx)", vma, syms[thisplace]->name,
+             syms[thisplace]->value - vma);
+
+    }
+    else {
+      fprintf(stream,"%08lx (%s+%lx)", vma, 
+             syms[thisplace]->name,
+             vma - syms[thisplace]->value);
+    }
+  }
+}
+
+void
+disassemble_data(abfd)
+bfd *abfd;
+{
+  bfd_byte *data = NULL;
+  unsigned int datasize = 0;
+  unsigned int i;
+  int (*print)() ;
+  int print_insn_m68k();
+  int print_insn_i960();
+  int print_insn_sparc();
+  enum bfd_architecture a;
+  unsigned long m;
+  asection *section;
+  /* Replace symbol section relative values with abs values */
+
+  
+  for (i = 0; i < symcount; i++) {
+    if (syms[i]->section != (asection *)NULL) {
+      syms[i]->value += syms[i]->section->vma;
+    }
+  }
+
+  /* We keep a copy of the symbols in the original order */
+  syms2 = slurp_symtab(abfd);
+
+  /* Sort the symbols into section and symbol order */
+  (void)   qsort(syms, symcount, sizeof(asymbol *), comp);
+
+  /* Find the first useless symbol */
+  { unsigned int i;
+    for (i =0; i < symcount; i++) {
+      if (syms[i]->the_bfd == 0) {
+       symcount =i;
+       break;
+      }
+    }
+  }
+
+
+  if (machine!= (char *)NULL) {
+    if (bfd_scan_arch_mach(machine, &a, &m) == false) {
+      fprintf(stderr,"%s: Can't use supplied machine %s\n",
+             program_name,
+             machine);
+      exit(1);
+    }
+  }
+  else {
+    a =   bfd_get_architecture(abfd);
+  }
+  switch (a) {
+
+  case bfd_arch_sparc:
+    print = print_insn_sparc;
+    break;
+  case bfd_arch_m68k:
+    print = print_insn_m68k;
+    break;
+  case bfd_arch_i960:
+    print = print_insn_i960;
+    break;
+  default:
+    fprintf(stderr,"%s: Can't disassemble for architecture %s\n",
+           program_name,
+           bfd_printable_arch_mach(bfd_get_architecture(abfd),0));
+    exit(1);
+  }
+
+
+  for (section = abfd->sections;
+       section != (asection *)NULL;
+       section =  section->next) {
+
+    if (only == (char *)NULL || strcmp(only,section->name) == 0){
+      printf("Disassembly of section %s:\n", section->name);
+
+      if (section->size == 0) continue;
+
+      data = (bfd_byte *)malloc(section->size);
+
+      if (data == (bfd_byte *)NULL) {
+       fprintf (stderr, "%s: memory exhausted.\n", program_name);
+       exit (1);
+      }
+      datasize = section->size;
+
+
+      bfd_get_section_contents (abfd, section, data, 0, section->size);
+
+      i = 0;
+      while ((size_t)i <section->size) {
+       if (with_line_numbers) {
+         static prevline;
+         char *filename;
+         char *functionname;
+         int line;
+         bfd_find_nearest_line(abfd,
+                               section,
+                               syms,
+                               section->vma + i,
+                               &filename,
+                               &functionname,
+                               &line);
+
+         if (filename && functionname && line && line != prevline) {
+           printf("%s:%d\n", filename, line);
+           prevline = line;
+         }
+       }
+       print_address(section->vma + i, stdout);
+       printf(" ");
+
+       i +=   print(section->vma + i, 
+                    data + i,
+                    stdout);
+       putchar ('\n')  ;  
+      }
+
+
+
+
+      free(data);
+    }
+  }
+}
+
+void
+display_bfd (abfd)
+     bfd *abfd;
+{
+
+  if (!bfd_check_format (abfd, bfd_object)) {
+    fprintf (stderr,"%s: %s not an object file\n", program_name,
+            abfd->filename);
+    return;
+  }
+  printf ("\n%s:     file format %s\n", abfd->filename, abfd->xvec->name);
+  if (dump_ar_hdrs) print_arelt_descr (abfd, true);
+
+  if (dump_file_header) {
+    char *comma = "";
+
+    printf("architecture: %s, ",
+          bfd_printable_arch_mach (bfd_get_architecture (abfd),
+                                   bfd_get_machine (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");
+    printf("\nstart address 0x%08lx", abfd->start_address);
+  }
+  printf("\n");
+
+  if (dump_section_headers)
+    dump_headers(abfd);
+  if (dump_symtab || dump_reloc_info || disassemble) {
+syms =  slurp_symtab(abfd);
+  }
+  if (dump_symtab) dump_symbols (abfd);
+  if (dump_reloc_info) dump_relocs(abfd);
+  if (dump_section_contents) dump_data (abfd);
+  if (disassemble) disassemble_data(abfd);
+}
+
+void
+display_file (filename, target)
+     char *filename;
+     char *target;
+{
+  bfd *file, *arfile = (bfd *) NULL;
+
+  file = bfd_openr (filename, target);
+  if (file == NULL) {
+    bfd_perror (filename);
+    return;
+  }
+
+  if (bfd_check_format (file, bfd_archive) == true) {
+    printf ("In archive %s:\n", bfd_get_filename (file));
+    for(;;) {
+      bfd_error = no_error;
+
+      arfile = bfd_openr_next_archived_file (file, arfile);
+      if (arfile == NULL) {
+       if (bfd_error != no_more_archived_files)
+         bfd_perror (bfd_get_filename(file));
+       return;
+      }
+
+      display_bfd (arfile);
+      /* Don't close the archive elements; we need them for next_archive */
+    }
+  }
+  else
+    display_bfd(file);
+
+  bfd_close(file);
+}
+\f
+/* Actually display the various requested regions */
+
+
+
+
+
+
+
+
+
+
+void
+dump_data (abfd)
+     bfd *abfd;
+{
+  asection *section;
+  bfd_byte  *data ;
+  unsigned int datasize = 0;
+  size_t i;
+
+  for (section = abfd->sections; section != NULL; section =
+       section->next) {
+    int onaline = 16;
+
+    if (only == (char *)NULL || 
+       strcmp(only,section->name) == 0){
+
+
+
+      printf("Contents of section %s:\n", section->name);
+
+      if (section->size == 0) continue;
+      data = (bfd_byte *)malloc(section->size);
+      if (data == (bfd_byte *)NULL) {
+       fprintf (stderr, "%s: memory exhausted.\n", program_name);
+       exit (1);
+      }
+      datasize = section->size;
+
+
+      bfd_get_section_contents (abfd, section, data, 0, section->size);
+
+      for (i= 0; i < section->size; i += onaline) {
+       size_t j;
+       printf(" %04lx ", i + section->vma);
+       for (j = i; j < i+ onaline; j++) {
+         if (j < section->size)
+           printf("%02x", (unsigned)(data[j]));
+         else 
+           printf("  ");
+         if ((j & 3 ) == 3) printf(" ");
+       }
+
+       printf(" ");
+       for (j = i; j < i+onaline ; j++) {
+         if (j >= section->size)
+           printf(" ");
+         else
+           printf("%c", isprint(data[j]) ?data[j] : '.');
+       }
+       putchar ('\n');
+      }
+    }
+
+    free (data);
+  }
+}
+
+
+
+/* Should perhaps share code and display with nm? */
+void
+dump_symbols (abfd)
+     bfd *abfd;
+{
+
+  unsigned int count;
+  asymbol **current = syms;
+  printf("SYMBOL TABLE:\n");
+
+  for (count = 0; count < symcount; count++) {
+    if ((*current)->the_bfd) {
+      bfd_print_symbol((*current)->the_bfd,
+                      stdout,
+                      *current, bfd_print_symbol_all_enum);
+
+      printf("\n");
+    }
+    current++;
+  }
+  printf("\n");
+  printf("\n");
+}
+
+
+void
+dump_relocs(abfd)
+bfd *abfd;
+{
+  arelent **relpp;
+  unsigned int relcount;
+  asection *a;
+  for (a = abfd->sections; a != (asection *)NULL; a = a->next) {
+    printf("RELOCATION RECORDS FOR [%s]:",a->name);
+    
+    if (get_reloc_upper_bound(abfd, a) == 0) {
+      printf(" (none)\n\n");
+    }
+    else {
+      arelent **p;
+
+      relpp = (arelent **) xmalloc( get_reloc_upper_bound(abfd,a) );
+      relcount = bfd_canonicalize_reloc(abfd,a,relpp, syms);
+      if (relcount == 0) {
+       printf(" (none)\n\n");
+      }
+      else {
+       printf("\n");
+       printf("OFFSET   TYPE      VALUE \n");
+
+       for (p =relpp; *p != (arelent *)NULL; p++) {
+         arelent *q = *p;
+         char *sym_name;
+         char *section_name =      q->section == (asection *)NULL ? "*abs" :
+         q->section->name;
+         if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
+           sym_name =  (*(q->sym_ptr_ptr))->name ;
+         }
+         else {
+           sym_name = 0;
+         }
+         if (sym_name) {
+           printf("%08lx %-8s  %s",
+                  q->address,
+                  q->howto->name,
+                  sym_name);
+         }
+         else {
+           printf("%08lx %-8s  [%s]",
+                  q->address,
+                  q->howto->name,
+                  section_name);
+         }
+         if (q->addend) {
+           printf("+0x%lx(%ld)", q->addend, (long) q->addend);
+         }
+         printf("\n");
+       }
+       printf("\n\n");
+       free(relpp);
+      }
+    }
+
+  }
+}
+
+
+/** main and like trivia */
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  extern int optind;
+  extern char *optarg;
+  char *target = default_target;
+  boolean seenflag = false;
+  int ind = 0;
+
+  program_name = *argv;
+
+  while ((c = getopt_long (argc, argv, "b:m:dlfahrtxsj:", long_options, &ind))
+        != EOF) {
+    seenflag = true;
+    switch (c) {
+    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 'x':
+      dump_symtab = 1; 
+      dump_reloc_info = 1;
+      dump_file_header = true;
+      dump_ar_hdrs = 1;
+      dump_section_headers = 1;
+      break;
+    case  0 : break;           /* we've been given a long option */
+    case 't': dump_symtab = 1; break;
+    case 'd': disassemble = true ; break;
+    case 's': dump_section_contents = 1; break;
+    case 'r': dump_reloc_info = 1; break;
+    case 'a': dump_ar_hdrs = 1; break;
+    case 'h': dump_section_headers = 1; break;
+    default:
+      usage ();
+    }
+  }
+
+  if (seenflag == false)
+    usage ();
+
+  if (optind == argc)
+    display_file ("a.out", target);
+  else
+    for (; optind < argc;)
+      display_file (argv[optind++], target);
+  return 0;
+}
diff --git a/binutils/ostrip.c b/binutils/ostrip.c
new file mode 100755 (executable)
index 0000000..6ba318c
--- /dev/null
@@ -0,0 +1,418 @@
+/* strip certain symbols from a rel file.
+   Copyright (C) 1986, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "sysdep.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "getopt.h"
+#include "bfd.h"
+
+enum strip_action {
+  strip_undef,
+  strip_all,                   /* strip all symbols */
+  strip_debug,                 /* strip all debugger symbols */
+};
+
+/* Which symbols to remove. */
+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. */
+enum locals_action discard_locals;
+
+/* The name this program was run with. */
+char *program_name;
+
+struct option long_options[] = {
+  {"strip-all", 0, 0, 's'},
+  {"strip-debug", 0, 0, 'S'},
+  {"discard-all", 0, 0, 'x'},
+  {"discard-locals", 0, 0, 'X'},
+  {0, 0, 0, 0},
+};
+
+static char *target = NULL;
+
+static int fatal_error;
+
+extern char *malloc();
+extern char *mktemp();
+extern char *realloc();
+extern char *strcpy();
+extern int exit();
+extern int fprintf();
+extern int free();
+extern int getpid();
+extern int kill();
+extern int perror();
+extern int sprintf();
+extern int unlink();
+
+#ifdef __STDC__
+static int strip_bfd(bfd *ibfd, bfd *obfd);
+static int strip_file(char *filetostrip);
+static void usage(void);
+#else
+static int strip_bfd();
+static int strip_file();
+static void usage();
+#endif /* __STDC__ */
+static void copy_sections ();
+static void setup_sections ();
+
+int main(argc, argv)
+char **argv;
+int argc;
+{
+       int ind;
+       int c;
+       program_name = argv[0];
+       
+       strip_symbols = strip_undef;    /* default is to strip everything.  */
+       discard_locals = locals_undef;
+       
+       while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
+               switch (c) {
+               case 0:
+                       break;
+               case 's':
+                       strip_symbols = strip_all;
+                       break;
+               case 'g':
+               case 'S':
+                       strip_symbols = strip_debug;
+                       break;
+               case 'T':
+                       target = optarg;
+                       break;
+               case 'x':
+                       discard_locals = locals_all;
+                       break;
+               case 'X':
+                       discard_locals = locals_start_L;
+                       break;
+               default:
+                       usage ();
+               } /* switch on option */
+       } /* for each option */
+       
+       if (strip_symbols == strip_undef && discard_locals == locals_undef) {
+               strip_symbols = strip_all;
+       } /* Default is to strip all symbols.  */
+       
+       
+       if (argc == optind) {
+               return(strip_file("a.out"));
+       } else {
+               int retval = 0;
+
+               for ( ; optind < argc; ++optind) {
+                       retval &= strip_file(argv[optind]);
+               } /* for each file to strip */
+
+               return(retval);
+       } /* if no arguments given */
+
+} /* main() */
+
+static int delayed_signal;
+
+void delay_signal(signo)
+int signo;
+{
+       delayed_signal = signo;
+       signal(signo, delay_signal);
+} /* delay_signal() */
+
+static int sigint_handled = 0;
+static int sighup_handled = 0;
+static int sigterm_handled = 0;
+
+void handle_sigs() {
+       /* Effectively defer handling of asynchronous kill signals.  */
+       delayed_signal = 0;
+       
+       if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
+               sigint_handled = 1;
+               signal(SIGINT, delay_signal);
+       } /* if not ignored */
+       
+       if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
+               sighup_handled = 1;
+               signal(SIGHUP, delay_signal);
+       } /* if not ignored */
+       
+       if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
+               sigterm_handled = 1;
+               signal(SIGTERM, delay_signal);
+       } /* if not ignored */
+       
+       return;
+} /* handle_sigs() */
+
+void unhandle_sigs() {
+       /* Effectively undefer handling.  */
+       if (sigint_handled)
+           signal (SIGINT, SIG_DFL);
+       if (sighup_handled)
+           signal (SIGHUP, SIG_DFL);
+       if (sigterm_handled)
+           signal (SIGTERM, SIG_DFL);
+       
+       /* Handle any signal that came in while they were deferred.  */
+       if (delayed_signal)
+           kill (getpid (), delayed_signal);
+       
+       return;
+} /* unhandle_sigs() */
+
+static int strip_file(filetostrip)
+char *filetostrip;
+{
+       bfd *ibfd;
+       bfd *obfd;
+       char tmpfilename[] = "stXXXXXX";
+
+       if ((ibfd = bfd_openr(filetostrip, (char *)NULL)) == NULL) {
+               bfd_perror(filetostrip);
+               return(1);
+       } /* on error opening input */
+       
+       obfd = bfd_openw(mktemp(tmpfilename),
+                        target? target: bfd_get_target (ibfd));
+       if (obfd == NULL) {
+               bfd_perror(tmpfilename);
+
+               if (bfd_close(ibfd) == false) {
+                       bfd_perror(bfd_get_filename(ibfd));
+               } /* on close error */
+
+               return(1);
+       } /* on error opening output */
+
+       handle_sigs();
+
+       if (bfd_check_format(ibfd, bfd_object) != false) {
+               if (bfd_set_format(obfd, bfd_get_format(ibfd)) != false) {
+                       if (!strip_bfd(ibfd, obfd)) {
+                               /* success */
+
+                               if (bfd_close(ibfd) == false) {
+                                       bfd_perror(bfd_get_filename(ibfd));
+                               } /* on close error */
+
+                               if (bfd_close(obfd) == false) {
+                                       bfd_perror(bfd_get_filename(obfd));
+                               } /* on close error */
+
+                               rename(tmpfilename, filetostrip);
+                               unhandle_sigs();
+                               return(0);
+                       } /* strip_bfd prints it's own failing messages */
+               } else {
+                       bfd_perror(filetostrip);
+               } /* can't set format */
+       } else {
+               /* not an object file */
+               (void) fprintf(stderr, "File %s has format 0x%x that will not be stripped.\n",
+                              filetostrip, (unsigned) bfd_get_format(ibfd));
+       } /* if anything fails along the way */
+       
+
+       if (bfd_close(ibfd) == false) {
+               bfd_perror(bfd_get_filename(ibfd));
+       } /* on close error */
+
+       if (bfd_close(obfd) == false) {
+               bfd_perror(bfd_get_filename(obfd));
+       } /* on close error */
+       
+       if (unlink(tmpfilename)) {
+               perror(tmpfilename);
+       } /* on error */
+       
+       unhandle_sigs();
+
+       return(1);
+} /* strip_file() */
+
+
+boolean
+bfd_set_start_address (abfd, new_address)
+     bfd *abfd;
+     bfd_vma new_address;
+{
+  bfd_get_start_address (abfd) = new_address;
+  return true;
+}
+
+
+
+static int
+strip_bfd(ibfd, obfd)
+       bfd *ibfd;
+       bfd *obfd;
+{
+       if (bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false
+           || bfd_set_file_flags(obfd, bfd_get_file_flags(ibfd) & ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS)) == false
+           || bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false) {
+               bfd_perror(bfd_get_filename(ibfd));
+               return(1);
+       } /* on error setting file attributes */
+
+      /* bfd mandates that all output sections be created and sizes set before
+        any output is done.  Thus, we traverse all sections twice.  */
+
+       fatal_error = 0;
+       bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
+       if (!fatal_error)
+               bfd_map_over_sections (ibfd, copy_sections,  (void *)obfd);
+       return fatal_error;
+}
+
+static void
+setup_sections(ibfd, isection, obfd)
+bfd *ibfd;
+sec_ptr isection;
+bfd *obfd;
+{
+       sec_ptr osection;
+       char *err;
+
+       do {
+           err = "making";
+           osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
+           if (osection == NULL)
+               break;
+           err = "size";
+           if (!bfd_set_section_size(obfd, osection, 
+                bfd_section_size(ibfd, isection)))
+               break;
+           err = "vma";
+           if (!bfd_set_section_vma(obfd, osection,
+                bfd_section_vma(ibfd, isection)))
+               break;
+           err = "alignment";
+           if (!bfd_set_section_alignment(obfd, osection,
+                bfd_section_alignment(ibfd, isection)))
+               break;
+           err = "flags";
+           if (!bfd_set_section_flags(obfd, osection,
+                bfd_get_section_flags(ibfd, isection)))
+               break;
+           return;
+       } while (0);
+
+       (void) fprintf(stderr, "file \"%s\", section \"%s\": error in %s: ",
+                      bfd_get_filename(ibfd),
+                      bfd_section_name(ibfd, isection),
+                      err);
+
+       bfd_perror("");
+       fatal_error = 1;
+}
+
+static void
+copy_sections(ibfd, isection, obfd)
+bfd *ibfd;
+sec_ptr isection;
+bfd *obfd;
+{
+       static char *memhunk = NULL;
+       static unsigned memhunksize = 0;
+
+       sec_ptr osection;
+       unsigned long size;
+       flagword iflg;
+       char *temp;
+
+       osection = bfd_get_section_by_name (obfd,
+                                           bfd_section_name(ibfd, isection));
+
+       size = bfd_section_size(ibfd, isection);
+       iflg = bfd_get_section_flags(ibfd, isection);
+
+       /* either:
+          we don't need any memory because there's nothing in this section,
+          we had no memory so we got some,
+          we had some memory but not enough so we got more,
+          or we fail to allocat. */
+
+       if (size == 0)
+               return;
+
+       if (memhunk == NULL) {
+               memhunk = malloc (size);
+               memhunksize = size;
+       }
+
+       if (size > memhunksize) {
+               temp = realloc (memhunk, size);
+               memhunksize = size;
+               if (!temp)      /* If realloc failed, blow away our mem */
+                       free (memhunk);
+               memhunk = temp;
+       }
+
+       if (memhunk == NULL) {
+               /* failed to allocate or reallocate */
+               /* FIXME, we should just copy in pieces. */
+               (void) fprintf(stderr,
+          "Could not allocate %lu bytes in which to copy section.\n", size);
+               return;
+       }
+
+       /* now we have enough memory */
+       
+       if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size)) {
+               bfd_perror(bfd_get_filename(ibfd));
+               fatal_error = 1;
+               return;
+       }
+       if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size)) {
+               bfd_perror(bfd_get_filename(obfd));
+               fatal_error = 1;
+               return;
+       }
+}
+
+void
+usage ()
+{
+  fprintf (stderr, "\
+Usage: %s [-gsxSX] [+strip-all] [+strip-debug] [+discard-all]\n\
+       [+discard-locals] file...\n", program_name);
+  exit (1);
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of strip.c */
diff --git a/binutils/size.c b/binutils/size.c
new file mode 100644 (file)
index 0000000..9f6800c
--- /dev/null
@@ -0,0 +1,320 @@
+/*** size.c -- report size of various sections of an executable file */
+/* 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 +predantic switch.
+*/
+#include "sysdep.h"
+#include "bfd.h"
+#include "getopt.h"
+
+
+#ifndef BSD_DEFAULT
+#define BSD_DEFAULT 1
+#endif
+
+PROTO(void, display_file, (char *filename));
+PROTO(void, print_sizes,  (bfd *file));
+
+/* Various 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;
+
+/* IMPORTS */
+extern char *program_version;
+extern char *program_name;
+extern char *target;
+\f
+/** main and like trivia */
+
+void
+usage ()
+{
+  fprintf (stderr, "size %s\nUsage: %s -{dox}{AB}V files ...\n",
+        program_version, program_name);
+  fputs("\t+radix={8|10|16} -- select appropriate output radix.\n\
+\t-d -- output in decimal\n\
+\t-o -- output in octal\n\
+\t-x -- output in hex", stderr);
+  fputs("\t+format={Berkeley|SysV} -- select display format.\n\
+\t-A -- SysV(AT&T) format\n\
+\t-B -- BSD format", stderr);
+#if BSD_DEFAULT
+  fputs("\t  (Default is +format=Berkeley)", stderr);
+#else
+  fputs("\t  (Default is +format=SysV)", stderr);
+#endif
+  fputs("\t-V, +version -- display program version, etc.\n\
+\t+help -- this message\n", stderr);
+  exit(1);
+}
+
+struct option long_options[] = {{"radix",   1, 0, 0},
+                               {"format",  1, 0, 0},
+                               {"version", 0, &show_version, 1},
+                               {"target",  2, NULL, NULL},
+                               {"help",    0, &show_help, 1},
+                               {0, 0, 0, 0}};
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int temp;
+  int c;                       /* sez which option char */
+  int option_index = 0;
+  extern int optind;           /* steps thru options */
+  program_name = *argv;
+
+  while ((c = getopt_long(argc, argv, "ABVdox", long_options,
+                         &option_index)) != EOF)
+    switch(c) {
+    case 0:
+      if (!strcmp("format",(long_options[option_index]).name)) {
+       switch(*optarg) {
+       case 'B': case 'b': berkeley_format = 1; break;
+       case 'S': case 's': berkeley_format = 0; break;
+       default: printf("Unknown option to +format: %s\n", optarg);
+         usage();
+       }
+       break;
+      }
+
+      if (!strcmp("target",(long_options[option_index]).name)) {
+       target = optarg;
+       break;
+      }
+
+      if (!strcmp("radix",(long_options[option_index]).name)) {
+#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("Unknown radix: %s\n", optarg);
+         usage();
+       }
+      }
+      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 '?': usage();
+    }
+
+  if (show_version) printf("%s version %s\n", program_name, program_version);
+  if (show_help) usage();
+       
+  if (berkeley_format)
+#if 0  /* intel doesn't like bss/stk b/c they don't gave core files */
+    puts((radix == octal) ? "text\tdata\tbss/stk\toct\thex\tfilename" :
+        "text\tdata\tbss/stk\tdec\thex\tfilename");
+#else
+    puts((radix == octal) ? "text\tdata\tbss\toct\thex\tfilename" :
+        "text\tdata\tbss\tdec\thex\tfilename");
+#endif
+  if (optind == argc)
+    display_file ("a.out");
+  else
+    for (; optind < argc;)
+      display_file (argv[optind++]);
+
+  return 0;
+}
+\f
+/** Display a file's stats */
+
+void
+display_bfd (abfd)
+     bfd *abfd;
+{
+  char *core_cmd;
+
+  if (bfd_check_format(abfd, bfd_archive)) return;
+
+  if (bfd_check_format(abfd, bfd_object)) {
+    print_sizes(abfd);
+    goto done;
+  }
+
+  if (bfd_check_format(abfd, bfd_core)) {
+    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(")");
+    goto done;
+  }
+  
+  printf("Unknown file format: %s.", bfd_get_filename(abfd));
+
+ done:
+
+
+  printf("\n");
+  return;
+}
+
+void
+display_file(filename)
+     char *filename;
+{
+  bfd *file, *arfile = (bfd *) NULL;
+
+  file = bfd_openr (filename, target);
+  if (file == NULL) {
+    bfd_perror (filename);
+    return;
+  }
+
+  if (bfd_check_format(file, bfd_archive) == true) {
+    for(;;) {
+      
+      bfd_error = no_error;
+
+       arfile = bfd_openr_next_archived_file (file, arfile);
+      if (arfile == NULL) {
+       if (bfd_error != no_more_archived_files)
+         bfd_perror (bfd_get_filename (file));
+       return;
+      }
+
+      display_bfd (arfile);
+      /* Don't close the archive elements; we need them for next_archive */
+    }
+  }
+  else
+    display_bfd (file);
+
+  bfd_close (file);
+}
+\f
+/* This is what lexical functions are for */
+void
+lprint_number (width, num)
+     int width, num;
+{
+  printf ((radix == decimal ? "%-*d\t" :
+          ((radix == octal) ? "%-*o\t" : "%-*x\t")), width, num);
+}
+
+void
+rprint_number(width, num)
+     int width, num;
+{
+  printf ((radix == decimal ? "%*d\t" :
+          ((radix == octal) ? "%*o\t" : "%*x\t")), width, num);
+}
+
+static char *bss_section_name = ".bss";
+static char *data_section_name = ".data";
+static char *stack_section_name = ".stack";
+static char *text_section_name = ".text";
+
+void print_berkeley_format(abfd)
+bfd *abfd;
+{
+  sec_ptr bsssection = NULL;
+  sec_ptr datasection = NULL;
+  sec_ptr textsection = NULL;
+  unsigned long bsssize = 0;
+  unsigned long datasize = 0;
+  unsigned long textsize = 0;
+  unsigned long total = 0;
+
+  
+  if ((textsection = bfd_get_section_by_name (abfd, text_section_name))
+      != NULL) {
+    textsize = bfd_section_size (abfd, textsection);
+  }
+
+  if ((datasection = bfd_get_section_by_name (abfd, data_section_name))
+      != NULL) {
+    datasize = bfd_section_size(abfd, datasection);
+  }
+       
+  if (bfd_get_format (abfd) == bfd_object) {
+    if ((bsssection = bfd_get_section_by_name (abfd, bss_section_name))
+       != NULL) {
+      bsssize = bfd_section_size(abfd, bsssection);
+    }
+  } else {
+    if ((bsssection = bfd_get_section_by_name (abfd, stack_section_name))
+       != NULL) {
+      bsssize = bfd_section_size(abfd, bsssection);
+    }
+  }
+       
+  total = textsize + datasize + bsssize;
+       
+  lprint_number (7, textsize);
+  lprint_number (7, datasize);
+  lprint_number (7, bsssize);
+  printf (((radix == octal) ? "%-7o\t%-7x\t" : "%-7d\t%-7x\t"), total, total);
+
+  fputs(bfd_get_filename(abfd), stdout);
+  if (abfd->my_archive) printf (" (ex %s)", abfd->my_archive->filename);
+}
+
+/* I REALLY miss lexical functions! */
+int svi_total = 0;
+
+void
+sysv_internal_printer(file, sec)
+     bfd *file;
+     sec_ptr sec;
+{
+  int size = bfd_section_size (file, sec);
+
+  svi_total += size;
+       
+  printf ("%-12s", bfd_section_name(file, sec));
+  rprint_number (8, size);
+  printf(" ");
+  rprint_number (8, bfd_section_vma(file, sec));
+  printf ("\n");
+}
+
+void
+print_sysv_format(file)
+     bfd *file;
+{
+  svi_total = 0;
+
+  printf ("%s  ", bfd_get_filename (file));
+  if (file->my_archive) printf (" (ex %s)", file->my_archive->filename);
+
+  puts(":\nsection\t\tsize\t     addr");
+  bfd_map_over_sections (file, sysv_internal_printer, NULL);
+
+  printf("Total       ");
+  rprint_number(8, svi_total);
+  printf("\n");  printf("\n");
+}
+
+void
+print_sizes(file)
+     bfd *file;
+{
+  if (berkeley_format)
+    print_berkeley_format(file);
+  else print_sysv_format(file);
+}
diff --git a/binutils/sparc-pinsn.c b/binutils/sparc-pinsn.c
new file mode 100644 (file)
index 0000000..041cade
--- /dev/null
@@ -0,0 +1,493 @@
+/* disassemble sparc instructions for objdump
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+
+This file is part of the binutils.
+
+The binutils are 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 1, or (at your option)
+any later version.
+
+The binutils are distributed in the hope that they 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 the binutils; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$
+   $Log$
+   Revision 1.1.1.1  1991/03/21 21:26:56  gumby
+   Back from Intel with Steve
+
+ * Revision 1.1  1991/03/21  21:26:55  gumby
+ * Initial revision
+ *
+ * Revision 1.1  1991/03/13  00:34:40  chrisb
+ * Initial revision
+ *
+ * Revision 1.3  1991/03/09  04:36:31  rich
+ *  Modified Files:
+ *     sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
+ *     binutils.h
+ *
+ * Pulled sysdep.h out of bfd.h.
+ *
+ * Revision 1.2  1991/03/08  21:54:53  rich
+ *  Modified Files:
+ *     Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
+ *     i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
+ *     sparc-pinsn.c strip.c
+ *
+ * Verifying Portland tree with steve's last changes.  Also, some partial
+ * porting.
+ *
+ * Revision 1.1  1991/02/22  16:48:04  sac
+ * Initial revision
+ *
+*/
+
+#include <stdio.h>
+#include "sysdep.h"
+#include "bfd.h"
+#include "sparc-opcode.h"
+
+extern int fputs();
+extern int print_address();
+
+static  char *reg_names[] =
+ { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",     
+  "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",      
+  "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",      
+  "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",      
+  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",      
+  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",        
+  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+  "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
+
+#define        freg_names      (&reg_names[4 * 8])
+
+union sparc_insn
+  {
+    unsigned long int code;
+    struct
+      {
+       unsigned int OP:2;
+#define        op      ldst.OP
+       unsigned int RD:5;
+#define        rd      ldst.RD
+       unsigned int op3:6;
+       unsigned int RS1:5;
+#define        rs1     ldst.RS1
+       unsigned int i:1;
+       unsigned int ASI:8;
+#define        asi     ldst.ASI
+       unsigned int RS2:5;
+#define        rs2     ldst.RS2
+#define        shcnt   rs2
+      } ldst;
+    struct
+      {
+       unsigned int OP:2, RD:5, op3:6, RS1:5, i:1;
+       unsigned int IMM13:13;
+#define        imm13   IMM13.IMM13
+      } IMM13;
+    struct
+      {
+       unsigned int OP:2;
+       unsigned int a:1;
+       unsigned int cond:4;
+       unsigned int op2:3;
+       unsigned int DISP22:22;
+#define        disp22  branch.DISP22
+      } branch;
+#define        imm22   disp22
+    struct
+      {
+       unsigned int OP:2;
+       unsigned int DISP30:30;
+#define        disp30  call.DISP30
+      } call;
+  };
+
+/* Nonzero if INSN is the opcode for a delayed branch.  */
+static int
+is_delayed_branch (insn)
+     union sparc_insn insn;
+{
+  unsigned int i;
+
+  for (i = 0; i < NUMOPCODES; ++i)
+    {
+      const struct sparc_opcode *opcode = &sparc_opcodes[i];
+      if ((opcode->match & insn.code) == opcode->match
+         && (opcode->lose & insn.code) == 0
+         && (opcode->delayed))
+       return 1;
+    }
+  return 0;
+}
+
+static int opcodes_sorted = 0;
+
+/* Print one instruction from MEMADDR on STREAM.  */
+int
+print_insn_sparc (memaddr, buffer,  stream)
+     bfd_vma memaddr;
+    bfd_byte  *buffer;
+     FILE *stream;
+     
+{
+  union sparc_insn insn;
+
+  register unsigned int i;
+
+  if (!opcodes_sorted)
+    {
+      static int compare_opcodes ();
+      qsort ((char *) sparc_opcodes, NUMOPCODES,
+            sizeof (sparc_opcodes[0]), compare_opcodes);
+      opcodes_sorted = 1;
+    }
+
+memcpy(&insn,buffer, sizeof (insn));
+
+  for (i = 0; i < NUMOPCODES; ++i)
+    {
+      const struct sparc_opcode *opcode = &sparc_opcodes[i];
+      if ((opcode->match & insn.code) == opcode->match
+         && (opcode->lose & insn.code) == 0)
+       {
+         /* Nonzero means that we have found an instruction which has
+            the effect of adding or or'ing the imm13 field to rs1.  */
+         int imm_added_to_rs1 = 0;
+
+         /* Nonzero means that we have found a plus sign in the args
+            field of the opcode table.  */
+         int found_plus = 0;
+         
+         /* Do we have an 'or' instruction where rs1 is the same
+            as rsd, and which has the i bit set?  */
+         if (opcode->match == 0x80102000
+             && insn.rs1 == insn.rd)
+           imm_added_to_rs1 = 1;
+
+         if (index (opcode->args, 'S') != 0)
+           /* Reject the special case for `set'.
+              The real `sethi' will match.  */
+           continue;
+         if (insn.rs1 != insn.rd
+             && index (opcode->args, 'r') != 0)
+             /* Can't do simple format if source and dest are different.  */
+             continue;
+
+         fputs (opcode->name, stream);
+
+         {
+           register const char *s;
+
+           if (opcode->args[0] != ',')
+             fputs (" ", stream);
+           for (s = opcode->args; *s != '\0'; ++s)
+             {
+               if (*s == ',')
+                 {
+                   fputs (",", stream);
+                   ++s;
+                   if (*s == 'a')
+                     {
+                       fputs ("a", stream);
+                       ++s;
+                     }
+                   fputs (" ", stream);
+                 }
+
+               switch (*s)
+                 {
+                 case '+':
+                   found_plus = 1;
+
+                   /* note fall-through */
+                 default:
+                   fprintf (stream, "%c", *s);
+                   break;
+
+                 case '#':
+                   fputs ("0", stream);
+                   break;
+
+#define        reg(n)  fprintf (stream, "%%%s", reg_names[n])
+                 case '1':
+                 case 'r':
+                   reg (insn.rs1);
+                   break;
+
+                 case '2':
+                   reg (insn.rs2);
+                   break;
+
+                 case 'd':
+                   reg (insn.rd);
+                   break;
+#undef reg
+
+#define        freg(n) fprintf (stream, "%%%s", freg_names[n])
+                 case 'e':
+                   freg (insn.rs1);
+                   break;
+
+                 case 'f':
+                   freg (insn.rs2);
+                   break;
+
+                 case 'g':
+                   freg (insn.rd);
+                   break;
+#undef freg
+
+#define        creg(n) fprintf (stream, "%%c%u", (unsigned int) (n))
+                 case 'b':
+                   creg (insn.rs1);
+                   break;
+
+                 case 'c':
+                   creg (insn.rs2);
+                   break;
+
+                 case 'D':
+                   creg (insn.rd);
+                   break;
+#undef creg
+
+                 case 'h':
+                   fprintf (stream, "%%hi(%#x)",
+                                     (unsigned int) insn.imm22 << 10);
+                   break;
+
+                 case 'i':
+                   {
+                     /* We cannot trust the compiler to sign-extend
+                        when extracting the bitfield, hence the shifts.  */
+                     int imm = ((int) insn.imm13 << 19) >> 19;
+
+                     /* Check to see whether we have a 1+i, and take
+                        note of that fact.
+
+                        Note: because of the way we sort the table,
+                        we will be matching 1+i rather than i+1,
+                        so it is OK to assume that i is after +,
+                        not before it.  */
+                     if (found_plus)
+                       imm_added_to_rs1 = 1;
+                     
+                     if (imm <= 9)
+                       fprintf (stream, "%d", imm);
+                     else
+                       fprintf (stream, "%#x", (unsigned) imm);
+                   }
+                   break;
+
+                 case 'L':
+                   print_address ((bfd_vma) memaddr + insn.disp30 * 4,
+                                  stream);
+                   break;
+
+                 case 'l':
+                   if ((insn.code >> 22) == 0)
+                     /* Special case for `unimp'.  Don't try to turn
+                        it's operand into a function offset.  */
+                     fprintf (stream, "%#x",
+                                       (unsigned) (((int) insn.disp22 << 10) >> 10));
+                   else
+                     /* We cannot trust the compiler to sign-extend
+                        when extracting the bitfield, hence the shifts.  */
+                     print_address ((bfd_vma)
+                                    (memaddr
+                                     + (((int) insn.disp22 << 10) >> 10) * 4),
+                                    stream);
+                   break;
+
+                 case 'A':
+                   fprintf (stream, "(%d)", (int) insn.asi);
+                   break;
+
+                 case 'C':
+                   fputs ("%csr", stream);
+                   break;
+
+                 case 'F':
+                   fputs ("%fsr", stream);
+                   break;
+
+                 case 'p':
+                   fputs ("%psr", stream);
+                   break;
+
+                 case 'q':
+                   fputs ("%fq", stream);
+                   break;
+
+                 case 'Q':
+                   fputs ("%cq", stream);
+                   break;
+
+                 case 't':
+                   fputs ("%tbr", stream);
+                   break;
+
+                 case 'w':
+                   fputs ("%wim", stream);
+                   break;
+
+                 case 'y':
+                   fputs ("%y", stream);
+                   break;
+                 }
+             }
+         }
+
+         /* If we are adding or or'ing something to rs1, then
+            check to see whether the previous instruction was
+            a sethi to the same register as in the sethi.
+            If so, attempt to print the result of the add or
+            or (in this context add and or do the same thing)
+            and its symbolic value.  */
+         if (imm_added_to_rs1)
+           {
+             union sparc_insn prev_insn;
+             int errcode;
+
+             memcpy(&prev_insn, buffer -4,  sizeof (prev_insn));
+
+             if (errcode == 0)
+               {
+                 /* If it is a delayed branch, we need to look at the
+                    instruction before the delayed branch.  This handles
+                    sequences such as
+
+                    sethi %o1, %hi(_foo), %o1
+                    call _printf
+                    or %o1, %lo(_foo), %o1
+                    */
+
+                 if (is_delayed_branch (prev_insn))
+                   memcpy(&prev_insn, buffer - 8, sizeof(prev_insn));
+
+               }
+
+             /* If there was a problem reading memory, then assume
+                the previous instruction was not sethi.  */
+             if (errcode == 0)
+               {
+                 /* Is it sethi to the same register?  */
+                 if ((prev_insn.code & 0xc1c00000) == 0x01000000
+                     && prev_insn.rd == insn.rs1)
+                   {
+                     fprintf (stream, "\t! ");
+                     /* We cannot trust the compiler to sign-extend
+                        when extracting the bitfield, hence the shifts.  */
+                     print_address (((int) prev_insn.imm22 << 10)
+                                    | (insn.imm13 << 19) >> 19, stream);
+                   }
+               }
+           }
+
+         return sizeof (insn);
+       }
+    }
+
+  fprintf ("%#8x", insn.code);
+  return sizeof (insn);
+}
+
+
+/* Compare opcodes A and B.  */
+
+static int
+compare_opcodes (a, b)
+     char *a, *b;
+{
+  struct sparc_opcode *op0 = (struct sparc_opcode *) a;
+  struct sparc_opcode *op1 = (struct sparc_opcode *) b;
+  unsigned long int match0 = op0->match, match1 = op1->match;
+  unsigned long int lose0 = op0->lose, lose1 = op1->lose;
+  register unsigned int i;
+
+  /* If a bit is set in both match and lose, there is something
+     wrong with the opcode table.  */
+  if (match0 & lose0)
+    {
+      fprintf (stderr, "Internal error:  bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+              op0->name, match0, lose0);
+      op0->lose &= ~op0->match;
+      lose0 = op0->lose;
+    }
+
+  if (match1 & lose1)
+    {
+      fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+              op1->name, match1, lose1);
+      op1->lose &= ~op1->match;
+      lose1 = op1->lose;
+    }
+
+  /* Because the bits that are variable in one opcode are constant in
+     another, it is important to order the opcodes in the right order.  */
+  for (i = 0; i < 32; ++i)
+    {
+      unsigned long int x = 1 << i;
+      int x0 = (match0 & x) != 0;
+      int x1 = (match1 & x) != 0;
+
+      if (x0 != x1)
+       return x1 - x0;
+    }
+
+  for (i = 0; i < 32; ++i)
+    {
+      unsigned long int x = 1 << i;
+      int x0 = (lose0 & x) != 0;
+      int x1 = (lose1 & x) != 0;
+
+      if (x0 != x1)
+       return x1 - x0;
+    }
+
+  /* They are functionally equal.  So as long as the opcode table is
+     valid, we can put whichever one first we want, on aesthetic grounds.  */
+  {
+    int length_diff = strlen (op0->args) - strlen (op1->args);
+    if (length_diff != 0)
+      /* Put the one with fewer arguments first.  */
+      return length_diff;
+  }
+
+  /* Put 1+i before i+1.  */
+  {
+    char *p0 = (char *) index(op0->args, '+');
+    char *p1 = (char *) index(op1->args, '+');
+
+    if (p0 && p1)
+      {
+       /* There is a plus in both operands.  Note that a plus
+          sign cannot be the first character in args,
+          so the following [-1]'s are valid.  */
+       if (p0[-1] == 'i' && p1[1] == 'i')
+         /* op0 is i+1 and op1 is 1+i, so op1 goes first.  */
+         return 1;
+       if (p0[1] == 'i' && p1[-1] == 'i')
+         /* op0 is 1+i and op1 is i+1, so op0 goes first.  */
+         return -1;
+      }
+  }
+
+  /* They are, as far as we can tell, identical.
+     Since qsort may have rearranged the table partially, there is
+     no way to tell which one was first in the opcode table as
+     written, so just say there are equal.  */
+  return 0;
+}
diff --git a/binutils/strip.c b/binutils/strip.c
new file mode 100755 (executable)
index 0000000..cd0f3af
--- /dev/null
@@ -0,0 +1,364 @@
+/*** strip.c -- strip certain symbols from a rel file.
+   Copyright (C) 1986, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* BUGS: When there's not enough memory, this should do the copy
+   in pieces rather than just fail as it does now */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "getopt.h"
+
+
+
+#include <signal.h>
+
+/* Various program options */
+
+int show_version = 0;
+
+/* Which symbols to remove. */
+enum strip_action {
+  strip_undef,
+  strip_all,                   /* strip all symbols */
+  strip_debug,                 /* strip all debugger symbols */
+} strip_symbols;
+
+/* Which local symbols to remove. */
+enum {
+  locals_undef,
+  locals_start_L,              /* discard locals starting with L */
+  locals_all,                  /* discard all locals */
+} discard_locals;
+
+extern char *mktemp();
+
+/* IMPORTS */
+extern char *program_version;
+extern char *program_name;
+extern char *target;
+extern char *xmalloc();
+
+PROTO(static boolean, strip_file, (char *filetostrip));
+PROTO(static void, copy_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
+PROTO(static void, setup_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
+\f
+/** main, etc */
+
+static void
+usage ()
+{
+  fprintf (stderr, "strip %s\nUsage: %s [-gsxSX] files ...\n",
+          program_version, program_name);
+  exit (1);
+}
+
+struct option long_options[] = {{"strip-all", 0, 0, 's'},
+                               {"strip-debug", 0, 0, 'S'},
+                               {"discard-all", 0, 0, 'x'},
+                               {"discard-locals", 0, 0, 'X'},
+                               {0, 0, 0, 0}
+                               };
+
+int
+main (argc, argv)
+     char **argv;
+     int argc;
+{
+  int ind;
+  int c;
+  program_name = argv[0];
+       
+  strip_symbols = strip_undef; /* default is to strip everything.  */
+  discard_locals = locals_undef;
+       
+  while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
+    switch (c) {
+    case 0:
+      break;
+    case 's':
+      strip_symbols = strip_all;
+      break;
+    case 'g':
+    case 'S':
+      strip_symbols = strip_debug;
+      break;
+    case 'T':
+      target = optarg;
+      break;
+    case 'x':
+      discard_locals = locals_all;
+      break;
+    case 'X':
+      discard_locals = locals_start_L;
+      break;
+    default:
+      usage ();
+    }
+  }
+
+  /* Default is to strip all symbols: */
+  if (strip_symbols == strip_undef && discard_locals == locals_undef) {
+    strip_symbols = strip_all;
+  }
+
+  /* OK, all options now parsed.  If no filename specified, do a.out. */
+  if (optind == argc) return !strip_file ("a.out");
+  
+  /* We were given several filenames to do: */
+  while (optind < argc)
+    if (!strip_file (argv[optind++])) return 1;
+
+  return 0;
+}
+\f
+/** Hack signals */
+
+/* Why does strip need to do this, and anyway, if it does shouldn't this be
+   handled by bfd? */
+
+static int delayed_signal;
+
+static int sigint_handled = 0;
+static int sighup_handled = 0;
+static int sigterm_handled = 0;
+
+void
+delay_signal (signo)
+     int signo;
+{
+  delayed_signal = signo;
+  signal (signo, delay_signal);
+}
+
+/* Effectively defer handling of asynchronous kill signals.  */
+void
+handle_sigs ()                 /* puff puff */
+{
+  delayed_signal = 0;
+       
+  if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
+    sigint_handled = 1;
+    signal (SIGINT, delay_signal);
+  }
+       
+  if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
+    sighup_handled = 1;
+    signal (SIGHUP, delay_signal);
+  }
+       
+  if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
+    sigterm_handled = 1;
+    signal (SIGTERM, delay_signal);
+  }
+       
+  return;
+}
+
+/* Effectively undefer handling.  */
+void
+unhandle_sigs ()               /* put them down */
+{
+  if (sigint_handled) signal (SIGINT, SIG_DFL);
+
+  if (sighup_handled) signal (SIGHUP, SIG_DFL);
+
+  if (sigterm_handled) signal (SIGTERM, SIG_DFL);
+       
+  /* Handle any signal that came in while they were deferred.  */
+  if (delayed_signal)
+    kill (getpid (), delayed_signal);
+       
+  return;
+}
+\f
+
+static boolean
+strip_file (filetostrip)
+     char *filetostrip;
+{
+  static char template[] = "stXXXXXX";
+  char *slash;
+  char *tmpname;
+  bfd *ibfd;
+  bfd *obfd;
+
+  ibfd = bfd_openr (filetostrip, target);
+
+  if (ibfd == NULL) bfd_fatal (filetostrip);
+
+  handle_sigs ();              /* light up */
+
+  if (!bfd_check_format (ibfd, bfd_object)) {
+    fprintf (stderr, "Can't strip %s file %s.\n",
+            bfd_format_string (bfd_get_format (ibfd)), filetostrip);
+    exit (1);
+  }
+
+  slash = strrchr( filetostrip, '/' );
+  if ( slash ){
+    *slash = 0;
+    tmpname = xmalloc( strlen(filetostrip) + sizeof(template) + 1 );
+    strcpy( tmpname, filetostrip );
+    strcat( tmpname, "/" );
+    strcat( tmpname, template );
+    mktemp( tmpname );
+    *slash = '/';
+  } else {
+    tmpname = xmalloc( sizeof(template) );
+    strcpy( tmpname, template );
+    mktemp( tmpname );
+  }
+
+  obfd = bfd_openw (mktemp(tmpname), (target ? target : bfd_get_target (ibfd)));
+  if (obfd == NULL) bfd_fatal (tmpname);
+
+  if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
+    bfd_fatal (tmpname);
+
+
+  if ((bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false) ||
+      (bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) &
+                                 ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS |
+                                   HAS_LOCALS))) == false) ||
+      bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false)
+    bfd_fatal (bfd_get_filename (ibfd));
+
+   /* Copy architecture of input file to output file */
+   if (!bfd_set_arch_mach (obfd, bfd_get_architecture (ibfd),
+                              bfd_get_machine (ibfd))) {
+     fprintf(stderr, "Output file cannot represent architecture %s",
+       bfd_printable_arch_mach (bfd_get_architecture(ibfd),
+                                bfd_get_machine (ibfd)));
+   }
+
+  /* bfd mandates that all output sections be created and sizes set before
+     any output is done.  Thus, we traverse all sections twice.  */
+  bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
+  bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
+
+  if (!bfd_close (obfd)) bfd_fatal (filetostrip);
+  if (!bfd_close (ibfd)) bfd_fatal (filetostrip);
+
+  rename(tmpname, filetostrip);
+  free(tmpname);
+
+  unhandle_sigs();
+
+  return true;
+}
+\f
+/** Actually do the work */
+static void
+setup_sections (ibfd, isection, obfd)
+     bfd *ibfd;
+     sec_ptr isection;
+     bfd *obfd;
+{
+  sec_ptr osection;
+  char *err;
+
+  osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
+  if (osection == NULL) {
+      err = "making";
+      goto loser;
+    }
+
+  if (!bfd_set_section_size(obfd, osection, bfd_section_size(ibfd, isection))) {
+     err = "size";
+     goto loser;
+  }
+
+  if (!bfd_set_section_vma (obfd, osection, bfd_section_vma (ibfd, isection))) {
+     err = "vma";
+     goto loser;
+  }
+
+  if (bfd_set_section_alignment (obfd, osection,
+                            bfd_section_alignment (ibfd, isection))
+      != true) {
+         err = "alignment";
+         goto loser;
+  } /* on error, I presume. */
+
+  if (!bfd_set_section_flags (obfd, osection,
+                             bfd_get_section_flags (ibfd, isection))) {
+     err = "flags";
+     goto loser;
+  }
+
+  /* All went well */
+  return;
+  
+ loser:
+  fprintf (stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
+          program_name,
+          bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
+          err, bfd_errmsg (bfd_error));
+  exit (1);
+}
+
+static void
+copy_sections (ibfd, isection, obfd)
+     bfd *ibfd;
+     sec_ptr isection;
+     bfd *obfd;
+{
+  static unsigned char *memhunk = NULL;
+  static unsigned memhunksize = 0;
+
+  sec_ptr osection;
+  unsigned long size;
+  flagword iflg;
+  unsigned char *temp;
+
+  osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
+
+  size = bfd_section_size (ibfd, isection);
+  iflg = bfd_get_section_flags (ibfd, isection);
+
+  /* either:
+     we don't need any memory because there's nothing in this section,
+     we had no memory so we got some,
+     we had some memory but not enough so we got more,
+     or we fail to allocat. */
+
+  if (size == 0)
+     return;
+
+  if ((iflg & SEC_HAS_CONTENTS) == 0)
+      return;
+
+  if (memhunk == NULL) {
+     memhunk = (unsigned char *) xmalloc (size);
+     memhunksize = size;
+  }
+
+  if (size > memhunksize) {
+     temp = (unsigned char *) xrealloc ((char *) memhunk, size);
+     memhunksize = size;
+     memhunk = temp;
+  }
+
+  /* now we have enough memory, just do it: */
+  if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
+     bfd_fatal (bfd_get_filename (ibfd));
+
+  if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
+     bfd_fatal (bfd_get_filename (obfd));
+}
diff --git a/binutils/version.c b/binutils/version.c
new file mode 100644 (file)
index 0000000..d3e5a13
--- /dev/null
@@ -0,0 +1,5 @@
+/*** version.c -- version number for binutils.
+     They all change in lockstep -- it's easier that way
+*/
+
+char *program_version = "1.10 (Cygnus BFD)";
diff --git a/gas/Makefile-intel b/gas/Makefile-intel
new file mode 100755 (executable)
index 0000000..54487c2
--- /dev/null
@@ -0,0 +1,146 @@
+#-----------------------------------------------------------------------------
+#              Makefile for gas960
+#
+# $Id$
+#-----------------------------------------------------------------------------
+
+# The following two lines should be uncommented for system V (i386v).
+#__i386v__#USG = -DUSG
+#__i386v__#LIBS = -lmalloc -lPW
+
+# The following two lines should be uncommented for HP-UX
+#__hp9000__#USG = -DUSG
+
+# The following line should be uncommented for Macintosh A/UX.
+#__mac-aux__#USG = -DUSG
+
+#Always build with static libraries on Sun systems
+#__sun3__#LDFLAGS = -Bstatic
+#__sun386i__#LDFLAGS = -Bstatic
+#__sun4__#LDFLAGS = -Bstatic
+
+# Essential under System V, harmless elsewhere
+SHELL = /bin/sh
+
+TARG   = gas960
+OPT    = -g
+IPATH  = ../../include
+CFLAGS = ${OPT} ${USG} -DI80960 -I${IPATH}
+
+
+OBJS = app.o append.o as.o atof-generic.o bignum-copy.o expr.o \
+       flonum-const.o flonum-copy.o flonum-mult.o frags.o gdb-blocks.o \
+       gdb-file.o gdb-lines.o gdb-symbols.o gdb.o hash.o hex-value.o \
+       input-file.o input-scrub.o messages.o obstack.o output-file.o read.o \
+       strstr.o subsegs.o symbols.o version.o write.o xmalloc.o xrealloc.o
+
+# Note that we use the 386 floating-point support for the i80960
+I960OBJ        = i960.o i960-opcode.o atof-i386.o
+
+gas960:        ${OBJS} ${I960OBJ} VERSION
+       make ver960.o
+       ${CC} -o gas960 ${LDFLAGS} ${OBJS} ${I960OBJ} ver960.o ${LIBS}
+
+hash.o:        hash.c
+       ${CC} -c ${CFLAGS} -Derror=as_fatal hash.c
+
+xmalloc.o:     xmalloc.c
+       ${CC} -c ${CFLAGS} -Derror=as_fatal xmalloc.c
+
+xrealloc.o:    xrealloc.c
+       ${CC} -c ${CFLAGS} -Derror=as_fatal xrealloc.c
+
+app.o:         as.h
+
+as.o:          ${IPATH}/b.out.h as.h read.h struc-symbol.h write.h
+atof-generic.o:        flonum.h
+bignum-copy.o: bignum.h
+expr.o:                ${IPATH}/b.out.h as.h expr.h flonum.h obstack.h read.h
+expr.o:                struc-symbol.h symbols.h
+flonum-const.o:        flonum.h
+flonum-copy.o: flonum.h
+flonum-mult.o: flonum.h
+flonum-normal.o:flonum.h
+flonum-print.o:        flonum.h
+frags.o:       ${IPATH}/b.out.h as.h frags.h obstack.h struc-symbol.h subsegs.h
+gdb.o:         as.h
+gdb-blocks.o:  as.h
+gdb-lines.o:   as.h frags.h obstack.h
+gdb-symbols.o: ${IPATH}/b.out.h as.h struc-symbol.h
+hash.o:                hash.h
+i960.o:                as.h ${IPATH}/b.out.h expr.h flonum.h frags.h hash.h
+i960.o:                i960-opcode.h md.h obstack.h struc-symbol.h write.h
+i960-opcode.o: i960-opcode.h
+input-file.o:  input-file.h
+input-scrub.o: as.h input-file.h read.h
+messages.o:    as.h
+obstack.o:     obstack.h
+read.o:                ${IPATH}/b.out.h as.h expr.h flonum.h frags.h hash.h md.h
+read.o:                obstack.h read.h struc-symbol.h symbols.h
+subsegs.o:     ${IPATH}/b.out.h as.h frags.h obstack.h struc-symbol.h subsegs.h
+subsegs.o:     write.h
+symbols.o:     ${IPATH}/b.out.h as.h frags.h hash.h obstack.h struc-symbol.h
+symbols.o:     symbols.h
+write.o:       ${IPATH}/b.out.h as.h md.h obstack.h struc-symbol.h subsegs.h
+write.o:       symbols.h write.h
+
+flonum.h:      bignum.h
+
+#-----------------------------------------------------------------------------
+#              'STANDARD' GNU/960 TARGETS BELOW THIS POINT
+#
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#-----------------------------------------------------------------------------
+
+ver960.c: FORCE
+       rm -f ver960.c
+       echo "char ${TARG}_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+       @V=`cat VERSION`                ; \
+       MAJ=`sed 's/\..*//' VERSION`    ; \
+       MIN=`sed 's/.*\.//' VERSION`    ; \
+       V=$$MAJ.`expr $$MIN + 1`        ; \
+       rm -f VERSION                   ; \
+       echo $$V >VERSION               ; \
+       echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+FORCE:
+
+# 'G960BASE' will be defined at invocation
+install:
+       make ${TARG} OPT=-O
+       strip ${TARG}
+       rm -f ${G960BASE}/bin/${TARG}
+       mv ${TARG} ${G960BASE}/bin/${TARG}
+
+clean:
+       rm -f ${TARG} *.o core
+
+# Target to uncomment host-specific lines in this makefile.  Such lines must
+# have the following string beginning in column 1: #__<hostname>__#
+# Original Makefile is backed up as 'Makefile.old'.
+#
+# Invoke with:  make make HOST=xxx
+#
+make:
+       -@if test $(HOST)x = x ; then \
+               echo '\aSpecify "make make HOST=???"'; \
+               exit 1; \
+       fi ; \
+       grep -s "^#The next line was generated by 'make make'" Makefile; \
+       if test $$? = 0 ; then  \
+               echo "\aMakefile has already been processed with 'make make'";\
+               exit 1; \
+       fi ; \
+       mv -f Makefile Makefile.old; \
+       echo "#The next line was generated by 'make make'"       >Makefile ; \
+       echo "HOST=$(HOST)"                                     >>Makefile ; \
+       echo                                                    >>Makefile ; \
+       sed "s/^#__$(HOST)__#//" < Makefile.old                 >>Makefile
diff --git a/gas/Makefile.generic b/gas/Makefile.generic
new file mode 100755 (executable)
index 0000000..1bf57a3
--- /dev/null
@@ -0,0 +1,586 @@
+host = generic
+target = generic
+# Makefile for GNU Assembler
+#   Copyright (C) 1987, 1988, 1990, 1991 Free Software Foundation, Inc.
+
+#This file is part of GNU GAS.
+
+#GNU GAS is free software; you can redistribute it and/or modify
+#it under the terms of the GNU General Public License as published by
+#the Free Software Foundation; either version 1, or (at your option)
+#any later version.
+
+#GNU GAS is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with GNU GAS; see the file COPYING.  If not, write to
+#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# $Id$
+
+# The targets for external use include:
+# all, doc, proto, install, uninstall, includes, TAGS,
+# clean, cleanconfig, realclean, stage1, stage2, stage3, stage4.
+
+# Variables that exist for you to override.
+# See below for how to change them for certain systems.
+
+ALLOCA =
+CFLAGS = -g $(XCFLAGS) # -I$(srcdir)/../include
+INTERNAL_CFLAGS = $(CROSS)
+OLDCC = cc
+BISON = bison
+BISONFLAGS = -v
+AR = ar
+OLDAR_FLAGS = qc
+AR_FLAGS = rc
+SHELL = /bin/sh
+# on sysV, define this as cp.
+INSTALL = install -c
+# These permit overriding just for certain files.
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_FILE = $(INSTALL)
+
+# Define this as & to perform parallel make on a Sequent.
+# Note that this has some bugs, and it seems currently necessary 
+# to compile all the gen* files first by hand to avoid erroneous results.
+P =
+
+# How to invoke ranlib.
+RANLIB = ranlib
+# Test to use to see whether ranlib exists on the system.
+RANLIB_TEST = [ -f /usr/bin/ranlib -o -f /bin/ranlib ]
+
+# CFLAGS for use with OLDCC, for compiling gnulib.
+# NOTE: -O does not work on some Unix systems!
+CCLIBFLAGS = -O
+
+# Version of ar to use when compiling gnulib. 
+OLDAR = ar
+
+version=`./gcc -dumpversion`
+
+# Directory where sources are, from where we are.
+srcdir = .
+# Common prefix for installation directories.
+# NOTE: This directory must exist when you start installation.
+prefix = /usr/local
+# Directory in which to put the executable for the command `gcc'
+bindir = $(prefix)/bin
+# Directory in which to put the directories used by the compiler.
+libdir = $(prefix)/lib
+# Directory in which the compiler finds executables, libraries, etc.
+libsubdir = $(libdir)/gcc/$(target)/$(version)
+# Number to put in man-page filename.
+manext = 1
+# Directory in which to put man pages.
+mandir = $(prefix)/man/man$(manext)
+
+# Additional system libraries to link with.
+CLIB=
+
+# Change this to a null string if obstacks are installed in the
+# system library.
+OBSTACK=obstack.o
+
+# Specify the rule for actually making gnulib.
+GNULIB = gnulib.portable
+
+# Specify the rule for actually making gnulib2.
+GNULIB2 = gnulib2.portable
+
+# List of extra C and assembler files to add to gnulib.
+# Assembler files should have names ending in `.asm'.
+LIBFUNCS_EXTRA = 
+
+# Program to convert libraries.
+LIBCONVERT = 
+
+# Control whether header files are installed.
+INSTALL_HEADERS=install-headers
+
+# Change this to empty to prevent installing limits.h
+LIMITS_H = limits.h
+
+# Directory to link to, when using the target `maketest'.
+DIR = ../gcc
+
+# For better debugging under COFF, define SEPARATE_AUX_OUTPUT in config.h
+# and define the following variable as `aux-output2.c' in make-...
+AUX_OUTPUT2 =
+
+# Flags to use when cross-building GCC.
+# Prefix to apply to names of object files when using them
+# to run on the machine we are compiling on.
+HOST_PREFIX=
+# Prefix to apply to names of object files when compiling them
+# to run on the machine we are compiling on.
+# The default for this variable is chosen to keep these rules 
+# out of the way of the other rules for compiling the same source files.
+HOST_PREFIX_1=loser-
+HOST_CC=$(CC)
+HOST_CFLAGS=$(ALL_CFLAGS)
+HOST_LDFLAGS=$(LDFLAGS)
+HOST_CPPFLAGS=$(CPPFLAGS)
+
+# Choose the real default target.
+ALL=bootstrap
+
+# End of variables for you to override.
+
+# Lists of files for various purposes.
+
+REAL_SOURCES = \
+       $(srcdir)/app.c \
+       $(srcdir)/as.c \
+       $(srcdir)/atof-generic.c \
+       $(srcdir)/bignum-copy.c \
+       $(srcdir)/cond.c \
+       $(srcdir)/expr.c \
+       $(srcdir)/flonum-const.c \
+       $(srcdir)/flonum-copy.c \
+       $(srcdir)/flonum-mult.c \
+       $(srcdir)/frags.c \
+       $(srcdir)/hash.c \
+       $(srcdir)/hex-value.c \
+       $(srcdir)/input-file.c \
+       $(srcdir)/input-scrub.c \
+       $(srcdir)/messages.c \
+       $(srcdir)/output-file.c \
+       $(srcdir)/read.c \
+       $(srcdir)/strstr.c \
+       $(srcdir)/subsegs.c \
+       $(srcdir)/symbols.c \
+       $(srcdir)/version.c \
+       $(srcdir)/write.c \
+       $(srcdir)/xmalloc.c \
+       $(srcdir)/xrealloc.c
+
+# in an expedient order
+LINKED_SOURCES = \
+       targ-cpu.c \
+       obj-format.c \
+       atof-targ.c
+
+SOURCES = $(LINKED_SOURCES) $(REAL_SOURCES)
+
+REAL_HEADERS = \
+       $(srcdir)/as.h \
+       $(srcdir)/bignum.h \
+       $(srcdir)/expr.h \
+       $(srcdir)/flonum.h \
+       $(srcdir)/frags.h \
+       $(srcdir)/hash.h \
+       $(srcdir)/input-file.h \
+       $(srcdir)/tc.h \
+       $(srcdir)/obj.h \
+       $(srcdir)/read.h \
+       $(srcdir)/reloc.h \
+       $(srcdir)/struc-symbol.h \
+       $(srcdir)/subsegs.h \
+       $(srcdir)/symbols.h \
+       $(srcdir)/syscalls.h \
+       $(srcdir)/write.h
+
+LINKED_HEADERS = \
+       a.out.gnu.h \
+       a.out.h \
+       host.h \
+       targ-env.h \
+       targ-cpu.h \
+       obj-format.h \
+       atof-targ.h
+
+HEADERS = $(LINKED_HEADERS) $(REAL_HEADERS)
+
+OBJS = \
+       targ-cpu.o \
+       obj-format.o \
+       atof-targ.o \
+       app.o \
+       as.o \
+       atof-generic.o \
+       bignum-copy.o \
+       cond.o \
+       expr.o \
+       flonum-const.o \
+       flonum-copy.o \
+       flonum-mult.o \
+       frags.o \
+       hash.o \
+       hex-value.o \
+       input-file.o \
+       input-scrub.o \
+       messages.o \
+       output-file.o \
+       read.o \
+       strstr.o \
+       subsegs.o \
+       symbols.o \
+       version.o \
+       write.o \
+       xmalloc.o \
+       xrealloc.o
+
+# Definition of `all' is here so that new rules inserted by sed
+# do not specify the default target.
+# The real definition is under `all.internal'.
+
+all: $(ALL)
+
+# sed inserts variable overrides after the following line.
+####
+
+# Now figure out from those variables how to compile and link.
+
+# This is the variable actually used when we compile.
+ALL_CFLAGS = $(INTERNAL_CFLAGS) $(CFLAGS)
+
+# Even if ALLOCA is set, don't use it if compiling with GCC.
+USE_ALLOCA= `if [ x"${CC}" = x"${OLDCC}" ] ; then echo ${ALLOCA}; else true; fi`
+USE_HOST_ALLOCA= `if [ x"${CC}" = x"${OLDCC}" ] ; then echo ${HOST_PREFIX}${ALLOCA}; else true; fi`
+
+# Dependency on obstack, alloca, malloc or whatever library facilities
+# are not installed in the system libraries.
+# We don't use USE_ALLOCA because backquote expansion doesn't work in deps.
+LIBDEPS= $(OBSTACK) $(ALLOCA) $(MALLOC)
+
+# Likewise, for use in the tools that must run on this machine
+# even if we are cross-building GCC.
+# We don't use USE_ALLOCA because backquote expansion doesn't work in deps.
+HOST_LIBDEPS= $(HOST_PREFIX)$(OBSTACK) $(HOST_PREFIX)$(ALLOCA) $(HOST_PREFIX)$(MALLOC)
+
+# How to link with both our special library facilities
+# and the system's installed libraries.
+LIBS = $(OBSTACK) $(USE_ALLOCA) $(MALLOC) $(CLIB)
+
+# Likewise, for use in the tools that must run on this machine
+# even if we are cross-building GCC.
+HOST_LIBS = $(HOST_PREFIX)$(OBSTACK) $(USE_HOST_ALLOCA) $(HOST_PREFIX)$(MALLOC) $(CLIB)
+
+# Specify the directories to be searched for header files.
+# Both . and srcdir are used, in that order,
+# so that tm.h and config.h will be found in the compilation
+# subdirectory rather than in the source directory.
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/config
+SUBDIR_INCLUDES = -I.. -I../$(srcdir) -I../$(srcdir)/config
+
+# Always use -I$(srcdir)/config when compiling.
+.c.o:
+       $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $<
+
+# This tells GNU make version 3 not to export all the variables
+# defined in this file into the environment.
+.NOEXPORT:
+
+# Files to be copied away after each stage in building.
+STAGE_GCC=gcc
+STAGESTUFF = *.o gas 
+
+# The files that "belong" in CONFIG_H are deliberately omitted
+# because having them there would not be useful in actual practice.
+# All they would do is cause complete recompilation every time
+# one of the machine description files is edited.
+# That may or may not be what one wants to do.
+# If it is, rm *.o is an easy way to do it.
+# CONFIG_H = config.h tm.h
+CONFIG_H =
+
+gas: $(OBJS) $(LIBDEPS)
+       $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o gas $(OBJS) $(LIBS)
+
+all.internal: native
+# This is what is made with the host's compiler if making a cross assembler.
+native: config.status gas
+
+config.status:
+       @echo You must configure gas.  Look at the INSTALL file for details.
+       @false
+
+compilations: ${OBJS}
+
+# Compiling object files from source files.
+
+# Note that dependencies on obstack.h are not written
+# because that file is not part of GAS.
+
+app.o : app.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h 
+as.o : as.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h 
+atof-generic.o : atof-generic.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h 
+bignum-copy.o : bignum-copy.c as.h host.h \
+  targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h 
+cond.o : cond.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  obstack.h 
+debug.o : debug.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  subsegs.h 
+expr.o : expr.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  obstack.h 
+flonum-const.o : flonum-const.c flonum.h bignum.h 
+flonum-copy.o : flonum-copy.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h 
+flonum-mult.o : flonum-mult.c flonum.h bignum.h 
+frags.o : frags.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  subsegs.h obstack.h 
+hash.o : hash.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h 
+hex-value.o : hex-value.c 
+input-file.o : input-file.c as.h host.h \
+   targ-env.h obj-format.h targ-cpu.h \
+   struc-symbol.h reloc.h write.h flonum.h bignum.h expr.h \
+  frags.h hash.h read.h symbols.h tc.h obj.h input-file.h 
+input-scrub.o : input-scrub.c /usr/include/errno.h /usr/include/sys/errno.h \
+  as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  input-file.h 
+messages.o : messages.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+obstack.o : obstack.c obstack.h 
+output-file.o : output-file.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  output-file.h 
+read.o : read.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  obstack.h 
+strstr.o : strstr.c   
+subsegs.o : subsegs.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  subsegs.h obstack.h 
+symbols.o : symbols.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  obstack.h subsegs.h 
+version.o : version.c 
+write.o : write.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h  struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+  subsegs.h obstack.h output-file.h 
+xmalloc.o : xmalloc.c
+xrealloc.o : xrealloc.c 
+atof-targ.o : atof-targ.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+  symbols.h tc.h obj.h 
+obj-format.o : obj-format.c as.h host.h targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+  symbols.h tc.h obj.h obstack.h 
+targ-cpu.o : targ-cpu.c targ-env.h obj-format.h \
+  targ-cpu.h struc-symbol.h reloc.h \
+  write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+  symbols.h tc.h obj.h obstack.h
+
+# Normally this target is not used; but it is used if you
+# define ALLOCA=alloca.o.  In that case, you must get a suitable alloca.c
+# from the GNU Emacs distribution.
+# Note some machines won't allow $(CC) without -S on this source file.
+alloca.o:      alloca.c
+       $(CC) $(ALL_CFLAGS) $(CPPFLAGS) -S `echo $(srcdir)/alloca.c | sed 's,^\./,,'`
+       as alloca.s -o alloca.o
+
+# Compile the libraries to be used by gen*.
+# If we are not cross-building, gen* use the same .o's that cc1 will use,
+# and HOST_PREFIX_1 is `foobar', just to ensure these rules don't conflict
+# with the rules for rtl.o, alloca.o, etc.
+$(HOST_PREFIX_1)alloca.o: alloca.c
+       rm -f $(HOST_PREFIX)alloca.c
+       cp $(srcdir)/alloca.c $(HOST_PREFIX)alloca.c
+       $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)alloca.c
+
+$(HOST_PREFIX_1)obstack.o: obstack.c
+       rm -f $(HOST_PREFIX)obstack.c
+       cp $(srcdir)/obstack.c $(HOST_PREFIX)obstack.c
+       $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)obstack.c
+
+$(HOST_PREFIX_1)malloc.o: malloc.c
+       rm -f $(HOST_PREFIX)malloc.c
+       cp $(srcdir)/malloc.c $(HOST_PREFIX)malloc.c
+       $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)malloc.c
+
+# Remake the info files.
+
+doc: $(srcdir)/gas.info
+
+$(srcdir)/gas.info: $(srcdir)/gas.texinfo
+       makeinfo `echo $(srcdir)/gas.texinfo | sed 's,^\./,,'`
+
+
+# Deletion of files made during compilation.
+# There are three levels of this: `clean', `cleanconfig' and `realclean'.
+# `clean' deletes what you want to delete ordinarily to save space.
+# This is most, but not all, of the files made by compilation.
+# `cleanconfig' also deletes everything depending
+# on the choice of config files.
+# `realclean' also deletes everything that could be regenerated automatically.
+
+clean:
+       -rm -f $(STAGESTUFF)
+# Delete the temporary source copies for cross compilation.
+       -rm -f $(HOST_PREFIX_1)alloca.c $(HOST_PREFIX_1)malloc.c
+       -rm -f $(HOST_PREFIX_1)obstack.c 
+# Delete the stamp files except stamp-gnulib2.
+       -rm -f core
+
+# Like clean but also delete the links made to configure gas.
+cleanconfig: clean
+       -rm -f config.status Makefile host.h targ-env.h
+       -rm -f targ-cpu.h targ-cpu.c
+       -rm -f obj-format.h obj-format.c
+       -rm -f atof-targ.c
+
+# Get rid of every file that's generated from some other file (except INSTALL).
+realclean: cleanconfig
+       -rm -f gas.aux gas.cps gas.fns gas.info gas.kys gas.pgs gas.tps gas.vrs
+       -rm -f TAGS 
+       -rm -f gas.info* gas.?? gas.??s gas.log gas.toc gas.*aux
+       -rm -f *.dvi
+
+# Entry points `install', `includes' and `uninstall'.
+
+# Copy the files into directories where they will be run.
+install:
+       $(INSTALL_PROGRAM) gas $(bindir)/as
+
+# Create the installation directory.
+install-dir:
+       -mkdir $(libdir)
+       -mkdir $(libdir)/gcc
+       -mkdir $(libdir)/gcc/$(target)
+       -mkdir $(libdir)/gcc/$(target)/$(version)
+
+# Install the compiler executables built during cross compilation.
+install-cross: native install-dir
+       -if [ -f cc1 ] ; then $(INSTALL_PROGRAM) cc1 $(libsubdir)/cc1; else true; fi
+       -if [ -f cc1plus ] ; then $(INSTALL_PROGRAM) cc1plus $(libsubdir)/cc1plus; else true; fi
+       $(INSTALL_PROGRAM) cpp $(libsubdir)/cpp
+       ./gcc -dumpspecs > $(libsubdir)/specs
+       $(INSTALL_PROGRAM) gcc $(bindir)/gcc
+
+# Install the man pages.
+install-man: install-dir $(srcdir)/gcc.1 protoize.1 unprotoize.1
+       $(INSTALL_FILE) $(srcdir)/gcc.1 $(mandir)/gcc.$(manext)
+       chmod a-x $(mandir)/gcc.$(manext)
+       $(INSTALL_FILE) $(srcdir)/protoize.1 $(mandir)/protoize.$(manext)
+       chmod a-x $(mandir)/protoize.$(manext)
+       $(INSTALL_FILE) $(srcdir)/unprotoize.1 $(mandir)/unprotoize.$(manext)
+       chmod a-x $(mandir)/unprotoize.$(manext)
+
+# Cancel installation by deleting the installed files.
+uninstall:
+       -rm -rf $(libsubdir)
+       -rm -rf $(bindir)/gas
+       -rm -rf $(mandir)/gas.$(manext)
+
+
+# These exist for maintenance purposes.
+
+tags TAGS: force
+       etags $(REAL_SOURCES) $(REAL_HEADERS) README Makefile config/*.[hc]
+       
+bootstrap: gas force
+       $(MAKE) stage1
+       $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= gas
+       $(MAKE) stage2
+       $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= gas
+       for i in *.o; do cmp $$i stage2/$$i; done
+
+bootstrap2: force
+       $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= gas
+       $(MAKE) stage2
+       $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= gas
+       for i in *.o; do cmp $$i stage2/$$i; done
+
+bootstrap3: force
+       $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= gas
+       for i in *.o; do cmp $$i stage2/$$i; done
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1: force
+       -mkdir stage1
+       -mv $(STAGESTUFF) stage1
+       -(cd stage1 ; ln -s gas as)
+
+stage2: force
+       -mkdir stage2
+       -mv $(STAGESTUFF) stage2
+       -(cd stage2 ; ln -s gas as)
+
+
+stage3: force
+       -mkdir stage3
+       -mv $(STAGESTUFF) $(STAGE_GCC) stage3
+       -rm -f stage3/gnulib
+       -cp gnulib stage3
+       -if $(RANLIB_TEST) ; then $(RANLIB) stage3/gnulib; else true; fi
+
+stage4: force
+       -mkdir stage4
+       -mv $(STAGESTUFF) $(STAGE_GCC) stage4
+       -rm -f stage4/gnulib
+       -cp gnulib stage4
+       -if $(RANLIB_TEST) ; then $(RANLIB) stage4/gnulib; else true; fi
+
+# Copy just the executable files from a particular stage into a subdirectory,
+# and delete the object files.  Use this if you're just verifying a version
+# that is pretty sure to work, and you are short of disk space.
+risky-stage1: force
+       -mkdir stage1
+       -mv cc1 cpp cccp gcc stage1
+       -rm -f stage1/gnulib
+       -cp gnulib stage1 && $(RANLIB) stage1/gnulib
+       -make clean
+
+risky-stage2: force
+       -mkdir stage2
+       -mv cc1 cpp cccp gcc stage2
+       -rm -f stage2/gnulib
+       -cp gnulib stage2 && $(RANLIB) stage2/gnulib
+       -make clean
+
+risky-stage3: force
+       -mkdir stage3
+       -mv cc1 cpp cccp gcc stage3
+       -rm -f stage3/gnulib
+       -cp gnulib stage3 && $(RANLIB) stage3/gnulib
+       -make clean
+
+risky-stage4: force
+       -mkdir stage4
+       -mv cc1 cpp cccp gcc stage4
+       -rm -f stage4/gnulib
+       -cp gnulib stage4 && $(RANLIB) stage4/gnulib
+       -make clean
+
+#In GNU Make, ignore whether `stage*' exists.
+.PHONY: stage1 stage2 stage3 stage4 clean realclean TAGS bootstrap
+.PHONY: risky-stage1 risky-stage2 risky-stage3 risky-stage4
+
+force:
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/configure
+       $(srcdir)/configure.was -srcdir=$(srcdir) -host=$(host) $(target)
diff --git a/gas/a.out.gnu.h b/gas/a.out.gnu.h
new file mode 100755 (executable)
index 0000000..a7f02a5
--- /dev/null
@@ -0,0 +1,461 @@
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+#include "target.h"            /* Figure out which target and host systems */
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+struct exec
+{
+  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
+  unsigned a_text;             /* length of text, in bytes */
+  unsigned a_data;             /* length of data, in bytes */
+  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;             /* length of symbol table data in file, in bytes */
+  unsigned a_entry;            /* start address */
+  unsigned a_trsize;           /* length of relocation info for text, in bytes */
+  unsigned a_drsize;           /* length of relocation info for data, in bytes */
+};
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+/* These symbols could be defined by code from Suns...punt 'em */
+#undef M_OLDSUN2
+#undef M_68010
+#undef M_68020
+#undef M_SPARC
+enum machine_type {
+  M_OLDSUN2 = 0,
+  M_68010 = 1,
+  M_68020 = 2,
+  M_SPARC = 3,
+  /* skip a bunch so we don't run into any of sun's numbers */
+  M_386 = 100,
+  M_29K = 101,
+};
+
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+       ((exec).a_info = ((magic) & 0xffff) \
+        | (((int)(type) & 0xff) << 16) \
+        | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+       ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+       ((exec).a_info = \
+        ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+       ((exec).a_info = \
+        ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+/* Code indicating object file or impure executable.  */
+#define OMAGIC 0407
+/* Code indicating pure executable.  */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable.  */
+#define ZMAGIC 0413
+
+#define N_BADMAG(x)                                    \
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC         \
+  && N_MAGIC(x) != ZMAGIC)
+
+#define _N_BADMAG(x)                                   \
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC         \
+  && N_MAGIC(x) != ZMAGIC)
+
+#define _N_HDROFF(x) (1024 - sizeof (struct exec))
+
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
+
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+
+#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
+
+#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
+
+#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
+
+/* Address of text segment in memory after it is loaded.  */
+/* Don't load things at zero, it encourages zero-pointer bugs */
+#ifndef TEXT_START_ADDR
+#define        TEXT_START_ADDR 0x10000
+#endif
+#define N_TXTADDR(x) TEXT_START_ADDR
+
+/* Address of data segment in memory after it is loaded.
+   Note that it is up to you to define SEGMENT_SIZE
+   on machines not listed here.  */
+#ifndef SEGMENT_SIZE
+#if defined(vax) || defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE page_size
+#endif
+#ifdef sony
+#define        SEGMENT_SIZE    0x2000
+#endif /* Sony.  */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define PAGE_SIZE 0x400
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+#endif
+
+#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+    (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+     : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#endif
+
+/* Address of bss segment in memory after it is loaded.  */
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+\f
+struct nlist {
+  union {
+    char *n_name;
+    struct nlist *n_next;
+    long n_strx;
+  } n_un;
+  unsigned char n_type;
+  char n_other;
+  short n_desc;
+  unsigned long n_value;
+};
+
+#define N_UNDF 0
+#define N_ABS 2
+#define N_TEXT 4
+#define N_DATA 6
+#define N_BSS 8
+#define N_FN 15
+
+#define N_EXT 1
+#define N_TYPE 036
+#define N_STAB 0340
+
+/* The following type indicates the definition of a symbol as being
+   an indirect reference to another symbol.  The other symbol
+   appears as an undefined reference, immediately following this symbol.
+
+   Indirection is asymmetrical.  The other symbol's value will be used
+   to satisfy requests for the indirect symbol, but not vice versa.
+   If the other symbol does not have a definition, libraries will
+   be searched to find a definition.  */
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+   All the N_SET[ATDB] symbols with the same name form one set.
+   Space is allocated for the set in the text section, and each set
+   element's value is stored into one word of the space.
+   The first word of the space is the length of the set (number of elements).
+
+   The address of the set is made into an N_SETV symbol
+   whose name is the same as the name of the set.
+   This symbol acts like a N_DATA global symbol
+   in that it can satisfy undefined external references.  */
+
+/* These appear as input to LD, in a .o file.  */
+#define        N_SETA  0x14            /* Absolute set element symbol */
+#define        N_SETT  0x16            /* Text set element symbol */
+#define        N_SETD  0x18            /* Data set element symbol */
+#define        N_SETB  0x1A            /* Bss set element symbol */
+
+/* This is output from LD.  */
+#define N_SETV 0x1C            /* Pointer to set vector in data area.  */
+\f
+/* This structure describes a single relocation to be performed.
+   The text-relocation section of the file is a vector of these structures,
+   all of which apply to the text section.
+   Likewise, the data-relocation section applies to the data section.  */
+
+#if TARGET == TARGET_SPARC || TARGET == TARGET_AM29K
+/*
+ * The following enum and struct were borrowed from
+ * sunOS  /usr/include/sun4/a.out.h  and extended to handle
+ * other machines.
+ */
+
+enum reloc_type
+{
+    RELOC_8,        RELOC_16,        RELOC_32,       RELOC_DISP8,
+    RELOC_DISP16,   RELOC_DISP32,    RELOC_WDISP30,  RELOC_WDISP22,
+    RELOC_HI22,     RELOC_22,        RELOC_13,       RELOC_LO10,
+    RELOC_SFA_BASE, RELOC_SFA_OFF13, RELOC_BASE10,   RELOC_BASE13,
+    RELOC_BASE22,   RELOC_PC10,      RELOC_PC22,     RELOC_JMP_TBL,
+    RELOC_SEGOFF16, RELOC_GLOB_DAT,  RELOC_JMP_SLOT, RELOC_RELATIVE,
+
+/* 29K relocation types */
+    RELOC_JUMPTARG, RELOC_CONST,     RELOC_CONSTH,
+
+    NO_RELOC
+};
+
+#define        RELOC_TYPE_NAMES \
+"8",           "16",           "32",           "DISP8",        \
+"DISP16",      "DISP32",       "WDISP30",      "WDISP22",      \
+"HI22",                "22",           "13",           "LO10",         \
+"SFA_BASE",    "SFAOFF13",     "BASE10",       "BASE13",       \
+"BASE22",      "PC10",         "PC22",         "JMP_TBL",      \
+"SEGOFF16",    "GLOB_DAT",     "JMP_SLOT",     "RELATIVE",     \
+"JUMPTARG",    "CONST",        "CONSTH",                       \
+"NO_RELOC",                                                    \
+"XXX_28", "XXX_29", "XXX_30", "XXX_31"
+
+struct reloc_info_extended
+{
+  unsigned long r_address;
+  unsigned int  r_index:24;
+# define       r_symbolnum  r_index
+  unsigned     r_extern:1;
+  unsigned     :2;
+  enum reloc_type r_type:5;
+  long int     r_addend;
+};
+
+/* Let programs know what they're dealing with */
+#define        RELOC_EXTENDED                  1
+
+#undef relocation_info
+#define relocation_info                        reloc_info_extended
+#define RELOC_ADDRESS(r)               ((r)->r_address)
+#define RELOC_EXTERN_P(r)               ((r)->r_extern)
+#define RELOC_TYPE(r)                   ((r)->r_index)
+#define        RELOC_EXTENDED_TYPE(r)          ((r)->r_type)
+#define RELOC_SYMBOL(r)                 ((r)->r_index)
+#define RELOC_MEMORY_SUB_P(r)          0
+#define RELOC_MEMORY_ADD_P(r)           0
+#define RELOC_ADD_EXTRA(r)              ((r)->r_addend)
+#define RELOC_PCREL_P(r)             \
+        (  ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22) \
+        || (r)->r_type == RELOC_JUMPTARG )
+#define RELOC_VALUE_RIGHTSHIFT(r)       (reloc_target_rightshift[(r)->r_type])
+#define RELOC_TARGET_SIZE(r)            (reloc_target_size[(r)->r_type])
+#define RELOC_TARGET_BITPOS(r)          0
+#define RELOC_TARGET_BITSIZE(r)         (reloc_target_bitsize[(r)->r_type])
+
+/* Note that these are very dependent on the order of the enums in
+   enum reloc_type (in a.out.h); if they change the following must be
+   changed */
+/* Also note that some of these may be incorrect; I have no information */
+#ifndef __STDC__
+#define const  /**/
+#endif
+static const int reloc_target_rightshift[] = {
+  0, 0, 0, 0,
+  0, 0, 2, 2,
+ 10, 0, 0, 0,
+  0, 0, 0, 0,
+  0, 0, 0, 0,
+  0, 0, 0, 0,
+  2, 0,16,     /* 29K jumptarg, const, consth */
+  0,
+};
+#define RELOC_SIZE_SPLIT16     13
+static const int reloc_target_size[] = {
+  0, 1, 2, 0,
+  1, 2, 2, 2,
+  2, 2, 2, 2,
+  2, 2, 2, 2,
+  2, 2, 2, 2,
+  2, 2, 2, 2,
+  RELOC_SIZE_SPLIT16, RELOC_SIZE_SPLIT16, RELOC_SIZE_SPLIT16,
+  0,
+};
+static const int reloc_target_bitsize[] = {
+  8, 16, 32, 8,
+ 16, 32, 30, 22,
+ 22, 22, 13, 10,
+ 32, 32, 16,  0,
+  0,  0,  0,  0,       /* dunno */
+  0,  0,  0,  0,
+ 16, 16, 16,           /* 29K jumptarg, const, consth */
+  0,
+};
+
+#define        MAX_ALIGNMENT   (sizeof (double))
+
+#else  /* Not SPARC or AM29K */
+
+struct relocation_info
+{
+  /* Address (within segment) to be relocated.  */
+  int r_address;
+  /* The meaning of r_symbolnum depends on r_extern.  */
+  unsigned int r_symbolnum:24;
+  /* Nonzero means value is a pc-relative offset
+     and it should be relocated for changes in its own address
+     as well as for changes in the symbol or section specified.  */
+  unsigned int r_pcrel:1;
+  /* Length (as exponent of 2) of the field to be relocated.
+     Thus, a value of 2 indicates 1<<2 bytes.  */
+  unsigned int r_length:2;
+  /* 1 => relocate with value of symbol.
+          r_symbolnum is the index of the symbol
+         in file's the symbol table.
+     0 => relocate with the address of a segment.
+          r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+         (the N_EXT bit may be set also, but signifies nothing).  */
+  unsigned int r_extern:1;
+  /* Four bits that aren't used, but when writing an object file
+     it is desirable to clear them.  */
+  unsigned int r_pad:4;
+};
+#endif
+
+/*
+ * Ok.  Following are the relocation information macros.  If your
+ * system should not be able to use the default set (below), you must
+ * define the following:
+
+ *   relocation_info: This must be typedef'd (or #define'd) to the type
+ * of structure that is stored in the relocation info section of your
+ * a.out files.  Often this is defined in the a.out.h for your system.
+ *
+ *   RELOC_ADDRESS (rval): Offset into the current section of the
+ * <whatever> to be relocated.  *Must be an lvalue*.
+ *
+ *   RELOC_EXTERN_P (rval):  Is this relocation entry based on an
+ * external symbol (1), or was it fully resolved upon entering the
+ * loader (0) in which case some combination of the value in memory
+ * (if RELOC_MEMORY_ADD_P) and the extra (if RELOC_ADD_EXTRA) contains
+ * what the value of the relocation actually was.  *Must be an lvalue*.
+ *
+ *   RELOC_TYPE (rval): If this entry was fully resolved upon
+ * entering the loader, what type should it be relocated as?
+ *
+ *   RELOC_EXTENDED_TYPE (rval): If this entry is for a machine using
+ * extended relocatino, what type of field is it?  (For example, on RISC
+ * machines, odd-sized displacements or split displacements occur.)
+ *
+ *   RELOC_SYMBOL (rval): If this entry was not fully resolved upon
+ * entering the loader, what is the index of it's symbol in the symbol
+ * table?  *Must be a lvalue*.
+ *
+ *   RELOC_MEMORY_ADD_P (rval): This should return true if the final
+ * relocation value output here should be added to memory, or if the
+ * section of memory described should simply be set to the relocation
+ * value.
+ *
+ *   RELOC_ADD_EXTRA (rval): (Optional) This macro, if defined, gives
+ * an extra value to be added to the relocation value based on the
+ * individual relocation entry.  *Must be an lvalue if defined*.
+ *
+ *   RELOC_PCREL_P (rval): True if the relocation value described is
+ * pc relative.
+ *
+ *   RELOC_VALUE_RIGHTSHIFT (rval): Number of bits right to shift the
+ * final relocation value before putting it where it belongs.
+ *
+ *   RELOC_TARGET_SIZE (rval): log to the base 2 of the number of
+ * bytes of size this relocation entry describes; 1 byte == 0; 2 bytes
+ * == 1; 4 bytes == 2, and etc.  This is somewhat redundant (we could
+ * do everything in terms of the bit operators below), but having this
+ * macro could end up producing better code on machines without fancy
+ * bit twiddling.  Also, it's easier to understand/code big/little
+ * endian distinctions with this macro.
+ *
+ *   RELOC_TARGET_BITPOS (rval): The starting bit position within the
+ * object described in RELOC_TARGET_SIZE in which the relocation value
+ * will go.
+ *
+ *   RELOC_TARGET_BITSIZE (rval): How many bits are to be replaced
+ * with the bits of the relocation value.  It may be assumed by the
+ * code that the relocation value will fit into this many bits.  This
+ * may be larger than RELOC_TARGET_SIZE if such be useful.
+ *
+ *
+ *             Things I haven't implemented
+ *             ----------------------------
+ *
+ *    Values for RELOC_TARGET_SIZE other than 0, 1, or 2.
+ *
+ *    Pc relative relocation for External references.
+ */
+#if TARGET == TARGET_SEQUENT
+#define RELOC_ADDRESS(r)               ((r)->r_address)
+#define RELOC_EXTERN_P(r)              ((r)->r_extern)
+#define RELOC_TYPE(r)          ((r)->r_symbolnum)
+#define RELOC_SYMBOL(r)                ((r)->r_symbolnum)
+#define RELOC_MEMORY_SUB_P(r)  ((r)->r_bsr)
+#define RELOC_MEMORY_ADD_P(r)  1
+#undef RELOC_ADD_EXTRA
+#define RELOC_PCREL_P(r)               ((r)->r_pcrel || (r)->r_bsr)
+#define RELOC_VALUE_RIGHTSHIFT(r)      0
+#define RELOC_TARGET_SIZE(r)           ((r)->r_length)
+#define RELOC_TARGET_BITPOS(r) 0
+#define RELOC_TARGET_BITSIZE(r)        32
+#endif
+
+/* Default macros */
+#ifndef RELOC_ADDRESS
+#define RELOC_ADDRESS(r)               ((r)->r_address)
+#define RELOC_EXTERN_P(r)              ((r)->r_extern)
+#define RELOC_TYPE(r)                  ((r)->r_symbolnum)
+#define RELOC_SYMBOL(r)                        ((r)->r_symbolnum)
+#define RELOC_MEMORY_SUB_P(r)          0
+#define RELOC_MEMORY_ADD_P(r)          1
+#undef RELOC_ADD_EXTRA
+#define RELOC_PCREL_P(r)               ((r)->r_pcrel)
+#define RELOC_VALUE_RIGHTSHIFT(r)      0
+#define RELOC_TARGET_SIZE(r)           ((r)->r_length)
+#define RELOC_TARGET_BITPOS(r)         0
+#define RELOC_TARGET_BITSIZE(r)                32
+#endif
+
+/* Maximum alignment required of a common'd variable.  If a var of this
+   size or larger is allocated in BSS when nobody defines it, it gets
+   this alignment.  */
+
+#ifndef MAX_ALIGNMENT
+#define        MAX_ALIGNMENT   (sizeof (int))
+#endif
+
+
+/* Definitions for routines that read and write GNU a.out files */
+
+enum objfile_kind {
+       OBJFILE_ERROR,
+       OBJFILE_UNKNOWN,
+       OBJFILE_SINGLE,
+       OBJFILE_ARCHIVE,
+};
+
+enum objfile_kind read_aout_header();  /* (desc, &header)  read&swap header */
+
+/* Read an a.out header from DESC and call rel_fn(DESC, header)
+   if it is an object file, lib_fn(DESC) if it is a library, else
+   call err_fn("msg") */
+void handle_aout_header();             /* (desc, rel_fn, lib_fn, err_fn) */
+
+/* Byte-swapping definitions */
+
+void swap_aoutheader();                /* BSD a.out header */
+short swap_getshort ();
+void swap_putshort();
+long swap_getlong ();
+void swap_putlong();
+void swap_reloc_info_in();     /* BSD relocation information */
+void swap_reloc_info_out();    /* BSD relocation information */
+void swap_nlists();            /* BSD symbol name lists */
+void swap_root_updates();      /* GDB Symseg */
+
+/* Bring on the encapsulation, if configured in! */
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#endif
+
+#endif /* __A_OUT_GNU_H__ */
diff --git a/gas/config/a.out.h b/gas/config/a.out.h
new file mode 100755 (executable)
index 0000000..5043249
--- /dev/null
@@ -0,0 +1,150 @@
+/* This file describes the a.out file format
+   Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#ifdef USE_HP_INC_HDR
+#include "../binutils/hp-include/a.out.h"
+#else
+
+#ifdef USE_SYSTEM_HDR
+#include "/usr/include/a.out.h"
+#else
+
+#ifdef USE_HP_HDR
+/* The `exec' structure and overall layout must be close to HP's when
+   we are running on an HP system, otherwise we will not be able to
+   execute the resulting file. */
+
+struct exec
+{
+  unsigned short a_machtype;   /* machine type */
+  unsigned short a_magic;      /* magic number */
+  unsigned long a_spare1;
+  unsigned long a_spare2;
+  unsigned long a_text;                /* length of text, in bytes */
+  unsigned long a_data;                /* length of data, in bytes */
+  unsigned long a_bss;         /* length of uninitialized data area for file, in bytes */
+  unsigned long a_trsize;      /* length of relocation info for text, in bytes */
+  unsigned long a_drsize;      /* length of relocation info for data, in bytes */
+  unsigned long a_spare3;      /* HP = pascal interface size */
+  unsigned long a_spare4;      /* HP = symbol table size */
+  unsigned long a_spare5;      /* HP = debug name table size */
+  unsigned long a_entry;       /* start address */
+  unsigned long a_spare6;      /* HP = source line table size */
+  unsigned long a_spare7;      /* HP = value table size */
+  unsigned long a_syms;                /* length of symbol table data in file, in bytes */
+  unsigned long a_spare8;
+};
+
+#define N_MAGIC(exec) ((exec) . a_magic)
+#define N_MACHTYPE(exec) ((exec) . a_machtype)
+#define N_SET_MAGIC(exec, magic) (((exec) . a_magic) = (magic))
+#define N_SET_MACHTYPE(exec, machtype) (((exec) . a_machtype) = (machtype))
+
+#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x)))
+
+#define _N_BADMACH(x)                                                  \
+(((N_MACHTYPE (x)) != HP9000S200_ID) &&                                        \
+ ((N_MACHTYPE (x)) != HP98x6_ID))
+
+#define _N_BADMAG(x) \
+ (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
+
+#define HP98x6_ID 0x20A
+#define HP9000S200_ID 0x20C
+
+#else
+
+       /* A Generic machine. . . */
+
+/* JF I'm not sure where this file came from.  I put the permit.text message in
+   it anyway.  This file came to me as part of the original VAX assembler, but had
+   no copyright notices in it. */
+
+struct exec {
+       long    a_magic;                        /* number identifies as .o file and gives type of such. */
+       unsigned a_text;                /* length of text, in bytes */
+       unsigned a_data;                /* length of data, in bytes */
+       unsigned a_bss;         /* length of uninitialized data area for file, in bytes */
+       unsigned a_syms;                /* length of symbol table data in file, in bytes */
+       unsigned a_entry;               /* start address */
+       unsigned a_trsize;              /* length of relocation info for text, in bytes */
+       unsigned a_drsize;              /* length of relocation info for data, in bytes */
+};
+
+#define N_BADMAG(x) \
+ (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
+
+#endif
+
+       /* From here down is common to both the HP and the generic machine */
+#define OMAGIC 0407
+#define NMAGIC 0410
+#define ZMAGIC 0413
+
+
+#define N_TXTOFF(x) \
+ ((x).a_magic == ZMAGIC ? 1024 : sizeof(struct exec))
+
+#define N_SYMOFF(x) \
+ (N_TXTOFF(x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize)
+
+#define N_STROFF(x) \
+ (N_SYMOFF(x) + (x).a_syms)
+
+struct nlist {
+       union {
+               char    *n_name;
+               struct nlist *n_next;
+               long    n_strx;
+       } n_un;
+       char    n_type;
+       char    n_other;
+       short   n_desc;
+       unsigned n_value;
+};
+
+#define N_UNDF 0
+#define N_ABS  2
+#define N_TEXT 4
+#define N_DATA 6
+#define N_BSS  8
+#define N_FN   31              /* JF: Someone claims this should be 31 instead of
+                          15.  I just inherited this file; I didn't write
+                          it.  Who is right? */
+
+
+#define N_EXT 1
+#define N_TYPE 036
+#define N_STAB 0340
+
+struct relocation_info {
+       int      r_address;
+       unsigned r_symbolnum:24,
+                r_pcrel:1,
+                r_length:2,
+                r_extern:1,
+                r_bsr:1, /* OVE: used on ns32k based systems, if you want */
+                r_disp:1, /* OVE: used on ns32k based systems, if you want */
+                nuthin:2;
+};
+
+#endif
+#endif
diff --git a/gas/config/coff.gnu.h b/gas/config/coff.gnu.h
new file mode 100755 (executable)
index 0000000..281ac17
--- /dev/null
@@ -0,0 +1,568 @@
+/*** coff information for 80960.  Origins: Intel, AMD, etc., natch. */
+
+/*
+ * At this point I'm sure this file is right for i960 and I'm pretty sure it's
+ * right for a29k, although it hasn't been tested rigorously.  Please feel free
+ * to add your own machine's description here.  Without that info, it isn't
+ * possible to build cross development tools from elsewhere nor is it easy to
+ * continue to support your machines format.
+ *
+ * The TC_foo ifdef's are mine.  They are what gas uses.  The other ifdef's
+ * remain for documentation from other scavenged files.   xoxorich.
+ */
+
+/* $Id$ */
+
+/********************** FILE HEADER **********************/
+
+struct filehdr {
+       unsigned short  f_magic;        /* magic number                 */
+       unsigned short  f_nscns;        /* number of sections           */
+       long            f_timdat;       /* time & date stamp            */
+       long            f_symptr;       /* file pointer to symtab       */
+       long            f_nsyms;        /* number of symtab entries     */
+       unsigned short  f_opthdr;       /* sizeof(optional hdr)         */
+       unsigned short  f_flags;        /* flags                        */
+};
+
+/* Bits for f_flags:
+ *     F_RELFLG        relocation info stripped from file
+ *     F_EXEC          file is executable (no unresolved externel references)
+ *     F_LNNO          line nunbers stripped from file
+ *     F_LSYMS         local symbols stripped from file
+ *     F_AR32WR        file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+#define F_RELFLG       (0x0001)
+#define F_EXEC         (0x0002)
+#define F_LNNO         (0x0004)
+#define F_LSYMS                (0x0008)
+
+#ifdef TC_I960
+#define F_AR32WR       (0x0010) /* File has 32 bits per word, least
+                                   significant byte first. */
+#else /* TC_I960 */
+#define F_AR32WR       (0x0100)
+#endif /* TC_I960 */
+
+#define F_MINMAL       (0x0010) /* ??? */
+#define F_UPDATE       (0x0020) /* ??? */
+#define F_SWABD                (0x0040) /* ??? */
+#define F_AR16WR       (0x0080) /* File has the byte ordering used by
+                                   the PDP*-11/70 processor. */
+#define F_AR32W                (0x0200) /* File has 32 bits per word, most
+                                   significant byte first. */
+
+/*
+ *     Intel 80960 (I960) processor flags.
+ *     F_I960TYPE == mask for processor type field. 
+ */
+
+#define        F_I960TYPE      (0xf000)
+#define        F_I960CORE      (0x1000)
+#define        F_I960KB        (0x2000)
+#define        F_I960SB        (0x2000)
+#define        F_I960MC        (0x3000)
+#define        F_I960XA        (0x4000)
+#define        F_I960CA        (0x5000)
+#define        F_I960KA        (0x6000)
+#define        F_I960SA        (0x6000)
+
+/*
+ * i80960 Magic Numbers
+ */
+
+#define I960ROMAGIC    (0x160) /* read-only text segments */
+#define I960RWMAGIC    (0x161) /* read-write text segments */
+
+#define I960BADMAG(x) (((x).f_magic != I960ROMAGIC) && ((x).f_magic != I960RWMAGIC))
+
+#define        SIPFBOMAGIC     (0x17a) /* Am29000 (Byte 0 is MSB - Big Endian) */
+#define        SIPRBOMAGIC     (0x17b) /* Am29000 (Byte 0 is LSB - Little Endian) */
+
+#define A29KBADMAG(x)  (((x).f_magic != SIPFBOMAGIC) && ((x).f_magic != SIPRBOMAGIC))
+
+#define        FILHDR  struct filehdr
+#define        FILHSZ  sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+typedef struct {
+       unsigned long   phys_addr;
+       unsigned long   bitarray;
+} TAGBITS;
+
+/*  These appear to be used only by exec(2).  I don't know who cares
+    about them in a cross development environment.  In any case, this
+    is my collection after researching the issue for a few hours.
+    Apparently, most have these have remained essentially unchanged
+    since v7 days, although a few new ones have been added.  xoxorich. */
+
+#define BAD0MAGIC      (0401) /* (?) "lpd (UNIX/RT)" */
+#define BAD1MAGIC      (0405) /* (?) overlay */
+#define        OMAGIC          (0407) /* old impure format. data immediately
+                                 follows text. both sections are rw. */
+#define        NMAGIC          (0410) /* split i&d, read-only text */
+#define A_MAGIC3       (0411) /* (?) "separated I&D" */
+#define        ZMAGIC          (0413) /* like NMAGIC, but demand loaded */
+#define PAGEMAGIC2     (0414) /* (?) like ZMAGIC, but address zero
+                                 explicitly unmapped. */
+#define REGMAGIC       (0414) /* (?) a PAGEMAGIC2 alias? */
+#define PAGEMAGIC3     (0415) /* (?) like ZMAGIC, but address zero mapped. */
+#define A_MAGIC5       (0437) /* (?) "system overlay, separated I&D" */
+ /* intended for non-unix cross development */
+#define SASMAGIC       (010000) /* Single Address Space */    
+#define MASMAGIC       (020000) /* (?) "Multiple (separate I & D) Address Spaces" */
+
+typedef        struct aouthdr {
+       short           magic;  /* type of file                         */
+       short           vstamp; /* version stamp                        */
+       unsigned long   tsize;  /* text size in bytes, padded to FW bdry*/
+       unsigned long   dsize;  /* initialized data "  "                */
+       unsigned long   bsize;  /* uninitialized data "   "             */
+#if U3B
+       unsigned long   dum1;
+       unsigned long   dum2;   /* pad to entry point   */
+#endif
+       unsigned long   entry;  /* entry pt.                            */
+       unsigned long   text_start;     /* base of text used for this file */
+       unsigned long   data_start;     /* base of data used for this file */
+ /* CAREFUL: some formats omit the tagentries member. */
+       unsigned long   tagentries;     /* number of tag entries to
+                                          follow (always zero for i960) */
+} AOUTHDR;
+
+/* return a pointer to the tag bits array */
+
+#define TAGPTR(aout) ((TAGBITS *) (&(aout.tagentries)+1))
+
+/* compute size of a header */
+
+/*#define AOUTSZ(aout) (sizeof(AOUTHDR)+(aout.tagentries*sizeof(TAGBITS)))*/
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+/********************** STORAGE CLASSES **********************/
+
+#define C_EFCN         -1      /* physical end of function */
+#define C_NULL         0
+#define C_AUTO         1       /* automatic variable */
+#define C_EXT          2       /* external symbol */
+#define C_STAT         3       /* static */
+#define C_REG          4       /* register variable */
+#define C_EXTDEF       5       /* external definition */
+#define C_LABEL                6       /* label */
+#define C_ULABEL       7       /* undefined label */
+#define C_MOS          8       /* member of structure */
+#define C_ARG          9       /* function argument */
+#define C_STRTAG       10      /* structure tag */
+#define C_MOU          11      /* member of union */
+#define C_UNTAG                12      /* union tag */
+#define C_TPDEF                13      /* type definition */
+#define C_USTATIC      14      /* undefined static */
+#define C_ENTAG                15      /* enumeration tag */
+#define C_MOE          16      /* member of enumeration */
+#define C_REGPARM      17      /* register parameter */
+#define C_FIELD                18      /* bit field */
+
+#ifdef TC_I960
+#define C_AUTOARG      19      /* auto argument */
+#define C_LASTENT      20      /* dummy entry (end of block) */
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+#define C_GLBLREG      19              /* global register */
+#define C_EXTREG       20              /* external global register */
+#define        C_DEFREG        21              /* ext. def. of global register */
+#define C_STARTOF      22              /* as29 $SIZEOF and $STARTOF symbols */
+#endif /* TC_A29K */
+
+#define C_BLOCK                100     /* ".bb" or ".eb" */
+#define C_FCN          101     /* ".bf" or ".ef" */
+#define C_EOS          102     /* end of structure */
+#define C_FILE         103     /* file name */
+#define C_LINE         104     /* line # reformatted as symbol table entry */
+#define C_ALIAS                105     /* duplicate tag */
+#define C_HIDDEN       106     /* ext symbol in dmert public lib. like static,
+                                  used to avoid name conflicts. */
+
+#ifdef TC_I960
+       /* New storage classes for 80960 */
+#define C_SCALL                107     /* Procedure reachable via system call  */
+ /* C_LEAFPROC is obsolete.  Use C_LEAFEXT or C_LEAFSTAT */
+#define C_LEAFPROC     108     /* Leaf procedure, "call" via BAL */
+#define C_LEAFEXT       108
+#define C_OPTVAR       109     /* Optimized variable */
+#define C_DEFINE       110     /* Preprocessor #define */
+#define C_PRAGMA       111     /* Advice to compiler or linker */
+#define C_SEGMENT      112     /* 80960 segment name */
+#define C_LEAFSTAT      113     /* Static leaf */
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+#define C_SHADOW       107 /* shadow symbol */
+#endif /* TC_A29K */
+
+/********************** SECTION HEADER **********************/
+
+struct scnhdr {
+       char            s_name[8];      /* section name */
+       long            s_paddr;        /* physical address, aliased s_nlib */
+       long            s_vaddr;        /* virtual address */
+       long            s_size;         /* section size */
+       long            s_scnptr;       /* file ptr to raw data for section */
+       long            s_relptr;       /* file ptr to relocation */
+       long            s_lnnoptr;      /* file ptr to line numbers */
+       unsigned short  s_nreloc;       /* number of relocation entries */
+       unsigned short  s_nlnno;        /* number of line number entries */
+       long            s_flags;        /* flags */
+
+#ifdef TC_I960
+       unsigned long   s_align;        /* section alignment */
+#endif /* TC_I960 */
+};
+
+#define        SCNHDR  struct scnhdr
+#define        SCNHSZ  sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT  ".text"
+#define _DATA  ".data"
+#define _BSS   ".bss"
+
+/*
+ * s_flags "type"
+ */
+
+/*
+ * In instances where it is necessary for a linker to
+ * produce an output file which contains text or data not
+ * based at virtual address 0, e.g. for a ROM, then the
+ * linker should accept address base information as command
+ * input and use PAD sections to skip over unused addresses.
+ * (at least for a29k.  Maybe others.)
+ */
+
+#define STYP_REG        (0x0000) /* "regular" section: allocated, relocated, loaded */
+#define STYP_DSECT      (0x0001) /* "dummy" section: not allocated, relocated, not loaded */
+#define STYP_NOLOAD     (0x0002) /* "noload" section: allocated, relocated, not loaded */
+#define STYP_GROUP      (0x0004) /* "grouped" section: formed of input sections */
+#define STYP_PAD        (0x0008) /* "padding" section: not allocated, not relocated, loaded */
+#define STYP_COPY       (0x0010) /* "copy" section: for decision function used by field update;  not allocated, not relocated,
+                                    loaded; reloc & lineno entries processed normally */
+#define STYP_TEXT       (0x0020) /* section contains text only */
+#define S_SHRSEG        (0x0020) /* In 3b Update files (output of ogen), sections which appear in SHARED segments of the Pfile
+                                    will have the S_SHRSEG flag set by ogen, to inform dufr that updating 1 copy of the proc. will
+                                    update all process invocations. */
+#define STYP_DATA       (0x0040) /* section contains data only */
+#define STYP_BSS        (0x0080) /* section contains bss only */
+#define S_NEWFCN        (0x0100) /* In a minimal file or an update file, a new function (as compared with a replaced function) */
+#define STYP_INFO       (0x0200) /* comment section : not allocated not relocated, not loaded */
+#define STYP_OVER       (0x0400) /* overlay section : relocated not allocated or loaded */
+#define STYP_LIB        (0x0800) /* for .lib section : same as INFO */
+#define STYP_MERGE      (0x2000) /* merge section -- combines with text, data or bss sections only */
+#define STYP_REVERSE_PAD (0x4000) /* section will be padded with no-op instructions wherever padding is necessary and there is a
+                                    word of contiguous bytes beginning on a word boundary. */
+
+#ifdef TC_A29K
+/* NOTE:  The use of STYP_BSSREG for relocation is not yet defined. */
+#define        STYP_BSSREG     0x1200  /* Global register area (like STYP_INFO) */
+#define STYP_ENVIR     0x2200  /* Environment (like STYP_INFO) */
+#define STYP_ABS       0x4000  /* Absolute (allocated, not reloc, loaded) */
+#define STYP_LIT       0x8020  /* Literal data (like STYP_TEXT) */
+#endif /* TC_A29K */
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct lineno {
+       union {
+               long l_symndx;  /* symbol index of function name, iff l_lnno == 0*/
+               long l_paddr;   /* (physical) address of line number */
+       } l_addr;
+       unsigned short  l_lnno; /* line number */
+#ifdef TC_I960
+ /* not used on a29k */
+       char padding[2];        /* force alignment */
+#endif /* TC_I960 */
+};
+
+#define        LINENO  struct lineno
+#define        LINESZ  sizeof(LINENO) 
+
+
+/********************** SYMBOLS **********************/
+
+#define SYMNMLEN       8       /* # characters in a symbol name        */
+#define FILNMLEN       14      /* # characters in a file name          */
+#define DIMNUM         4       /* # array dimensions in auxiliary entry */
+
+struct syment {
+       union {
+               char    _n_name[SYMNMLEN];      /* old COFF version     */
+               struct {
+                       long    _n_zeroes;      /* new == 0             */
+                       long    _n_offset;      /* offset into string table */
+               } _n_n;
+               char    *_n_nptr[2];    /* allows for overlaying        */
+       } _n;
+       long            n_value;        /* value of symbol              */
+       short           n_scnum;        /* section number               */
+
+#ifdef TC_I960
+ /* This isn't yet used on the i960.  In some formats this
+    is two bytes of padding.  In others, it is missing entirely. */
+       unsigned short  n_flags;        /* copy of flags from filhdr    */
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+       unsigned short  n_type;         /* type and derived type        */
+#else /* TC_A29K */
+ /* at least i960 uses long */
+       unsigned long   n_type;         /* type and derived type        */
+#endif /* TC_A29K */
+
+       char            n_sclass;       /* storage class                */
+       char            n_numaux;       /* number of aux. entries       */
+
+#ifndef TC_A29K
+       char            pad2[2];        /* force alignment              */
+#endif /* TC_A29K */
+};
+
+#define        SYMENT  struct syment
+#define        SYMESZ  sizeof(SYMENT) /* This had better also be sizeof(AUXENT) */
+
+#define n_name         _n._n_name
+#define n_ptr          _n._n_nptr[1]
+#define n_zeroes       _n._n_n._n_zeroes
+#define n_offset       _n._n_n._n_offset
+
+/*
+ * Relocatable symbols have number of the section in which they are defined,
+ * or one of the following:
+ */
+
+#define N_SCNUM        ((short) 1-65535) /* section num where symbol defined */
+#define N_UNDEF        ((short)0)  /* undefined symbol */
+#define N_ABS  ((short)-1) /* value of symbol is absolute */
+#define N_DEBUG        ((short)-2) /* debugging symbol -- symbol value is meaningless */
+#define N_TV   ((short)-3) /* indicates symbol needs preload transfer vector */
+#define P_TV   ((short)-4) /* indicates symbol needs transfer vector (postload) */
+
+/*
+ * Type of a symbol, in low 4 bits of the word
+ */
+#define T_NULL         0 /* type not assigned */
+#define T_VOID         1 /* function argument (only used by compiler) (but now
+                            real void). */
+#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 */
+
+#ifdef TC_I960
+#define T_LNGDBL       16      /* long double */
+#endif /* TC_I960 */
+
+/*
+ * derived types, in n_type
+ */
+#define DT_NON         (0)     /* no derived type */
+#define DT_PTR         (1)     /* pointer */
+#define DT_FCN         (2)     /* function */
+#define DT_ARY         (3)     /* array */
+
+#ifndef TC_I960
+
+#define N_BTMASK       (0x0f)
+#define N_TMASK                (0x30)
+#define N_BTSHFT       (4)
+#define N_TSHIFT       (2)
+
+#else /* TC_I960 */
+
+#define N_BTMASK       (0x1f)
+#define N_TMASK                (0x60)
+#define N_BTSHFT       (5)
+#define N_TSHIFT       (2)
+
+#endif /* TC_I960 */
+
+#define BTYPE(x)       ((x) & N_BTMASK)
+
+#define ISPTR(x)       (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
+#define ISFCN(x)       (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
+#define ISARY(x)       (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
+
+#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
+
+union auxent {
+       struct {
+               long x_tagndx;  /* str, un, or enum tag indx */
+               union {
+                       struct {
+                           unsigned short x_lnno; /* declaration line number */
+                           unsigned short x_size; /* str/union/array size */
+                       } x_lnsz;
+                       long x_fsize;   /* size of function */
+               } x_misc;
+               union {
+                       struct {                /* if ISFCN, tag, or .bb */
+                           long x_lnnoptr;     /* ptr to fcn line # */
+                           long x_endndx;      /* entry ndx past block end */
+                       } x_fcn;
+                       struct {                /* if ISARY, up to 4 dimen. */
+                           unsigned short x_dimen[DIMNUM];
+                       } x_ary;
+               } x_fcnary;
+               unsigned short x_tvndx;         /* tv index */
+       } x_sym;
+
+ /* This was just a struct x_file with x_fname only in a29k.  xoxorich. */
+       union {
+               char x_fname[FILNMLEN];
+               struct {
+                       long x_zeroes;
+                       long x_offset;
+               } x_n;
+       } x_file;
+
+       struct {
+               long x_scnlen;                  /* section length */
+               unsigned short x_nreloc;        /* # relocation entries */
+               unsigned short x_nlinno;        /* # line numbers */
+       } x_scn;
+
+       struct {
+               long            x_tvfill;       /* tv fill value */
+               unsigned short  x_tvlen;        /* length of .tv */
+
+ /* This field was typo'd x_tvrna on a29k. xoxorich. */
+               unsigned short  x_tvran[2];     /* tv range */
+       } x_tv;         /* info about .tv section (in auxent of symbol .tv)) */
+
+#ifdef TC_I960
+       /******************************************
+        *  I960-specific *2nd* aux. entry formats
+        ******************************************/
+       struct {
+ /* This is a very old typo that keeps getting propogated. */
+#define x_stdindx x_stindx
+               long x_stindx;  /* sys. table entry */
+       } x_sc; /* system call entry */
+
+       struct {
+               unsigned long x_balntry; /* BAL entry point */
+       } x_bal; /* BAL-callable function */
+
+       struct {
+               unsigned long   x_timestamp;            /* time stamp */
+               char    x_idstring[20];         /* producer identity string */
+       } x_ident;                              /* Producer ident info */
+
+       char a[sizeof(struct syment)];  /* force auxent/syment sizes to match */
+#endif /* TC_I960 */
+};
+
+#define        AUXENT  union auxent
+#define        AUXESZ  sizeof(AUXENT) /* This had better also be sizeof(SYMENT) */
+
+#if VAX || I960
+#      define _ETEXT   "_etext"
+#else
+#      define _ETEXT   "etext"
+#endif
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct reloc {
+       long r_vaddr;           /* Virtual address of reference */
+       long r_symndx;          /* Index into symbol table */
+       unsigned short r_type;  /* Relocation type */
+#ifdef TC_I960
+ /* not used for a29k */
+       char pad[2];            /* Unused */
+#endif /* TC_I960 */
+};
+
+#define RELOC struct reloc
+#define RELSZ sizeof(RELOC)
+
+#ifdef TC_I960
+#define R_RELLONG      (0x11)  /* Direct 32-bit relocation */
+#define R_IPRSHORT     (0x18)
+#define R_IPRMED       (0x19)  /* 24-bit ip-relative relocation */
+#define R_IPRLONG      (0x1a)
+#define R_OPTCALL      (0x1b)  /* 32-bit optimizable call (leafproc/sysproc) */
+#define R_OPTCALLX     (0x1c)  /* 64-bit optimizable call (leafproc/sysproc) */
+#define R_GETSEG       (0x1d)
+#define R_GETPA                (0x1e)
+#define R_TAGWORD      (0x1f)
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+/*
+ * NOTE: All the "I" forms refer to Am29000 instruction
+ * formats.  The linker is expected to know how the numeric
+ * information is split and/or aligned within the
+ * instruction word(s).  R_BYTE works for instructions, too.
+ *
+ * If the parameter to a CONSTH instruction is a relocatable
+ * type, two relocation records are written.  The first has
+ * an r_type of R_IHIHALF (33 octal) and a normal r_vaddr
+ * and r_symndx.  The second relocation record has an r_type
+ * of R_IHCONST (34 octal), a normal r_vaddr (which is
+ * redundant), and an r_symndx containing the 32-bit
+ * constant offset to the relocation instead of the actual
+ * symbol table index.  This second record is always
+ * written, even if the constant offset is zero.  The
+ * constant fields of the instruction are set to zero.
+ */
+
+#define        R_ABS           (0x00) /* reference is absolute */
+#define        R_IREL          (0x18) /* instruction relative (jmp/call) */
+#define        R_IABS          (0x19) /* instruction absolute (jmp/call) */
+#define        R_ILOHALF       (0x1a) /* instruction low half  (const)  */
+#define        R_IHIHALF       (0x1b) /* instruction high half (consth) part 1 */
+#define        R_IHCONST       (0x1c) /* instruction high half (consth) part 2
+                                 constant offset of R_IHIHALF relocation */
+#define        R_BYTE          (0x1d) /* relocatable byte value */
+#define R_HWORD                (0x1e) /* relocatable halfword value */
+#define R_WORD         (0x1f) /* relocatable word value */
+#define        R_IGLBLRC       (0x20) /* instruction global register RC */
+#define        R_IGLBLRA       (0x21) /* instruction global register RA */
+#define        R_IGLBLRB       (0x22) /* instruction global register RB */
+#endif /* TC_A29K */
+
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 16
+/* For new sections we havn't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
+
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * End:
+ */
+
+/* end of coff.gnu.h */
diff --git a/gas/config/ho-ansi.h b/gas/config/ho-ansi.h
new file mode 100644 (file)
index 0000000..b7fc587
--- /dev/null
@@ -0,0 +1,40 @@
+/* ho-ansi.h  Host-specific header file for generic ansi environments.
+   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define M_ANSI 1
+
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#define sys_nerr       _sys_nerr
+#define sys_errlist    _sys_errlist
+#define bzero(b,l)     (memset((b),0,(l)))
+
+/*
+ * $Log$
+ * Revision 1.1  1991/04/04 18:15:38  rich
+ * Initial revision
+ *
+ *
+ */
+
+/* end of ho-ansi.h */
diff --git a/gas/config/ho-cygnus.h b/gas/config/ho-cygnus.h
new file mode 100755 (executable)
index 0000000..9b39153
--- /dev/null
@@ -0,0 +1,41 @@
+/* ho-ansi.h  Host-specific header file for generic ansi environments.
+   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define M_ANSI 1
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define sys_nerr       _sys_nerr
+#define sys_errlist    _sys_errlist
+#define bzero(s,l)     (memset((s),0,(l)))
+
+/*
+ * $Log$
+ * Revision 1.1  1991/04/04 18:15:40  rich
+ * Initial revision
+ *
+ *
+ */
+
+/* end of ho-ansi.h */
diff --git a/gas/config/ho-generic.h b/gas/config/ho-generic.h
new file mode 100644 (file)
index 0000000..40c49e9
--- /dev/null
@@ -0,0 +1,32 @@
+/* ho-generic.h  Generic host-specific header file.
+   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define M_GENERIC 1
+
+/*
+ * $Log$
+ * Revision 1.1  1991/04/04 18:15:42  rich
+ * Initial revision
+ *
+ *
+ */
+
+/* end of ho-generic.h */
diff --git a/gas/config/ho-hpux.h b/gas/config/ho-hpux.h
new file mode 100644 (file)
index 0000000..751b4ee
--- /dev/null
@@ -0,0 +1,34 @@
+/* ho-hpux.h -- Header to compile the assembler under HP-UX
+   Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#include "ho-sysv.h"
+
+/* This header file contains the #defines specific
+   to HPUX changes sent me by cph@zurich.ai.mit.edu */
+#ifndef hpux
+#define hpux
+#endif
+
+#ifdef setbuffer
+#undef setbuffer
+#endif /* setbuffer */
+
+#define setbuffer(stream, buf, size)
diff --git a/gas/config/ho-i386.h b/gas/config/ho-i386.h
new file mode 100644 (file)
index 0000000..94dd8c2
--- /dev/null
@@ -0,0 +1,28 @@
+/* ho-i386.h  i386 specific header file.
+   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define HO_I386 1
+
+#define NO_STDARG
+
+#include "ho-sysv.h"
+
+/* end of ho-i386.h */
diff --git a/gas/config/ho-sun3.h b/gas/config/ho-sun3.h
new file mode 100644 (file)
index 0000000..33b74c3
--- /dev/null
@@ -0,0 +1,7 @@
+/* $Id$ */
+
+#include <ho-sunos.h>
+
+extern int sprintf();
+
+/* end of ho-sun3.h */
diff --git a/gas/config/ho-sun386.h b/gas/config/ho-sun386.h
new file mode 100644 (file)
index 0000000..00eacad
--- /dev/null
@@ -0,0 +1,7 @@
+/* $Id$ */
+
+#include <ho-sunos.h>
+
+extern int sprintf();
+
+/* end of ho-sun386.h */
diff --git a/gas/config/ho-sun4.h b/gas/config/ho-sun4.h
new file mode 100644 (file)
index 0000000..6cfd6b4
--- /dev/null
@@ -0,0 +1,5 @@
+/* $Id$ */
+
+#include <ho-sunos.h>
+
+/* end of ho-sun4.h */
diff --git a/gas/config/ho-sunos.h b/gas/config/ho-sunos.h
new file mode 100644 (file)
index 0000000..13d5c3d
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Id$ */
+
+#ifndef __STDC__
+#define NO_STDARG
+#include <memory.h>
+#endif /* not __STDC__ */
+
+#include <ctype.h>
+#include <string.h>
+
+/* externs for system libraries. */
+
+extern char *strchr();
+extern char *malloc();
+extern char *realloc();
+extern char *strrchr();
+extern int _filbuf();
+extern int _flsbuf();
+extern int abort();
+extern int bcopy();
+extern int bzero();
+extern int bzero();
+extern int exit();
+extern int fclose();
+extern int fprintf();
+extern int fread();
+extern int free();
+extern int perror();
+extern int printf();
+extern int setvbuf();
+extern int sscanf();
+extern int strcmp();
+extern int strlen();
+extern int strncmp();
+extern int time();
+extern int ungetc();
+extern int vfprintf();
+extern int vprintf();
+extern long atol();
+
+#ifndef tolower
+extern int tolower();
+#endif /* tolower */
+
+#ifndef toupper
+extern int toupper();
+#endif /* toupper */
+
+/*
+ * Local Variables:
+ * fill-column: 80
+ * comment-column: 0
+ * End:
+ */
+
+/* end of ho-sun4.h */
diff --git a/gas/config/ho-sysv.h b/gas/config/ho-sysv.h
new file mode 100644 (file)
index 0000000..af8dd6e
--- /dev/null
@@ -0,0 +1,31 @@
+/* ho-sysv.h  System V specific header file.
+   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define HO_USG
+
+#define bcopy(from,to,n) memcpy((to),(from),(n))
+#define bzero(s,n) memset((s),0,(n))
+#define setbuffer(stream, buf, size) setvbuf((stream), (buf), _IOLBF, (size))
+
+extern int free();
+extern char *malloc();
+
+/* end of ho-sysv.h */
diff --git a/gas/configure.was b/gas/configure.was
new file mode 100755 (executable)
index 0000000..2485927
--- /dev/null
@@ -0,0 +1,340 @@
+#!/bin/sh
+# Configuration script for GNU GAS
+#   Copyright (C) 1988, 1990, 1991 Free Software Foundation, Inc.
+
+#This file is not yet part of GNU GAS.
+
+#GNU GAS is free software; you can redistribute it and/or modify
+#it under the terms of the GNU General Public License as published by
+#the Free Software Foundation; either version 1, or (at your option)
+#any later version.
+
+#GNU GAS is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with GNU GAS; see the file COPYING.  If not, write to
+#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# $Id$
+
+#
+# Shell script to create proper links to machine-dependent files in
+# preparation for compiling gas.
+#
+# Usage: configure [-srcdir=DIR] [-host=HOST] TARGET
+#
+# If configure succeeds, it leaves its status in config.status.
+# If configure fails after disturbing the status quo, 
+#      config.status is removed.
+#
+
+progname=$0
+
+remove=rm
+hard_link=ln
+symbolic_link='ln -s'
+
+host=
+target=
+
+#for Test
+#remove="echo rm"
+#hard_link="echo ln"
+#symbolic_link="echo ln -s"
+
+for arg in $*;
+do
+  case $arg in
+   -srcdir=* | +srcdir=* | +srcdi=* | +srcd=* | +src=* | +sr=* | +s=*)
+       srcdir=`echo $arg | sed 's/[+-]s[a-z]*=//'`
+       ;;
+   -host=* | +host=* | +hos=* | +ho=* | +h=*)
+       host=`echo $arg | sed 's/[+-]h[a-z]*=//'`
+       ;; 
+   *)
+# Allow configure HOST TARGET
+       if [ x$host = x ]
+       then
+               host=$target
+       fi
+       target=$arg
+       ;;
+  esac
+done
+
+# Complain if an arg is missing
+if [ x$target = x ]
+then
+       echo "Usage: $progname [+srcdir=DIR] [+host=HOST] TARGET"
+       echo -n "Where HOST and TARGET are something like "
+       echo "\`vax', \`sun3', \`encore', etc."
+       if [ -r config.status ]
+       then
+               cat config.status
+       fi
+       exit 1
+fi
+
+# Default other arg
+if [ x$host = x ]
+then
+       host=$target
+fi
+
+# Find the source files, if location was not specified.
+if [ x$srcdir = x ]
+then
+       srcdirdefaulted=1
+       srcdir=.
+       if [ ! -r as.c ]
+       then
+               srcdir=..
+       fi
+fi
+
+if [ ! -r ${srcdir}/as.c ]
+then
+       if [ x$srcdirdefaulted = x ]
+       then
+         echo "$progname: Can't find assembler sources in \`${srcdir}'." 1>&2
+       else
+         echo "$progname: Can't find assembler sources in \`.' or \`..'." 1>&2
+       fi
+       exit 1
+fi
+
+# Decode the host machine, then the target machine.
+# For the host machine, we save the ho variable as host_ho;
+# then we decode the target machine and forget everything else
+# that came from the host machine.
+for machine in $host $target; do
+       tc=
+       obj=
+
+       host_header=
+       obj_header=
+       obj_source=
+       te_header=
+       tc_header=
+       tc_source=
+
+       make_var_file=
+
+       case $machine in
+       generic)
+               ;;
+       i860)
+               tc=i860
+               obj=aout
+               ;;
+       pmax | dec3100)
+               ho=pmax
+               ;;
+       sun386)
+               ho=sun386
+               ;;
+       sun4 | sun4-aout | sun-4 | sun4-os4 | sun-4-os4)
+               ho=sun4
+               tc=sparc
+               obj=aout
+               ;;
+       sun4-bout)
+               tc=sparc
+               obj=bout
+               ;;
+       sun4-bfd-sunos)
+               tc=sparc
+               obj=bfd-sunos
+               ;;
+       i960 | i960-coff)
+               tc=i960
+               obj=coff
+               te=ic960
+               ;;
+       i960-bout)
+               tc=i960
+               obj=bout
+               ;;
+       i960-aout)
+               tc=i960
+               obj=aout
+               ;;
+       sun3 | sun3-aout)
+               ho=sun3
+               tc=m68k
+               obj=aout
+               te=sun3
+               ;;
+       a29k | a29k-aout)
+               tc=a29k
+               obj=aout
+               ;;
+       a29k-coff)
+               tc=a29k
+               obj=coff
+               ;;
+       i386)
+               tc=i386
+               obj=aout
+               ;;
+       ns32k)
+               tc=ns32k
+               obj=aout
+               ;;
+       vax)
+               tc=vax
+               obj=aout
+               ;;
+       rs6000)
+               ;;
+       esac
+       if [ x$pass1done = x ]
+       then
+               if [ x$ho = x ]; then ho=$host; fi
+               if [ x$ho_header = x ]; then ho_ho_header=ho-$ho.h
+               else ho_ho_header=$ho_header
+               fi
+               if [ x$make_var_file = x ]
+               then make_var_file=make-$ho; fi
+               ho_make_var_file=$make_var_file
+               pass1done=yes
+       else
+               host_make_var_file=$ho_make_var_file
+               ho_header=$ho_ho_header
+       fi
+done
+
+
+# Default the machine-specific variables that were not explicitly set.
+if [ x$te = x ]
+then te=generic; fi
+
+if [ x$te_header = x ]
+then te_header=te-$te.h; fi
+
+
+if [ x$tc = x ]
+then tc=generic; fi
+
+if [ x$tc_header = x ]
+then tc_header=tc-$tc.h; fi
+
+if [ x$tc_source = x ]
+then tc_source=tc-$tc.c; fi
+
+
+if [ x$obj = x ]
+then obj=generic; fi
+
+if [ x$obj_header = x ]
+then obj_header=obj-$obj.h; fi
+
+if [ x$obj_source = x ]
+then obj_source=obj-$obj.c; fi
+
+
+if [ x$atof_source = x ]
+then atof_source=atof-ieee.c; fi
+
+# Set up the list of links to be made.
+# $links is the list of link names, and $files is the list of names to link to.
+files="$ho_header $te_header $tc_header $tc_source $obj_header $obj_source $atof_source"
+links="host.h targ-env.h targ-cpu.h targ-cpu.c obj-format.h obj-format.c atof-targ.c"
+
+# Make the links.
+while [ -n "$files" ]
+do
+       # set file to car of files, files to cdr of files
+       set $files; file=$1; shift; files=$*
+       set $links; link=$1; shift; links=$*
+
+       if [ ! -r ${srcdir}/config/$file ]
+       then
+               echo "$progname: cannot create a link \`$link'," 1>&2
+               echo "since the file \`config/$file' does not exist." 1>&2
+               exit 1
+       fi
+
+       $remove -f $link
+       rm -f config.status
+       # Make a symlink if possible, otherwise try a hard link
+       $symbolic_link ${srcdir}/config/$file $link 2>/dev/null || $hard_link ${srcdir}/config/$file $link
+
+       if [ ! -r $link ]
+       then
+               echo "$progname: unable to link \`$link' to \`${srcdir}/config/$file'." 1>&2
+               exit 1
+       fi
+       echo "Linked \`$link' to \`${srcdir}/config/$file'."
+done
+
+# Build a Makefile
+
+# Install a makefile, and make it set srcdir
+# if necessary so that the sources are found.
+# Also change its value of srcdir.
+# Also create a .gdbinit file which runs the one in srcdir
+# and tells GDB to look there for source files.
+case $srcdir in
+.)
+       ;;
+*)
+       echo "VPATH = ${srcdir}" > x
+       cat x ${srcdir}/Makefile.in | sed "s@^srcdir = \.@srcdir = ${srcdir}@" > Makefile.in
+       rm x
+       echo "dir ." > .gdbinit
+       echo "dir ${srcdir}" >> .gdbinit
+       echo "source ${srcdir}/.gdbinit" >> .gdbinit
+       ;;
+esac
+
+# Conditionalize the makefile for this machine.
+if [ -f ${srcdir}/config/${host_make_var_file} ]
+then
+       sed -e "/####/  r ${srcdir}/config/${host_make_var_file}" Makefile.in > Makefile.tem
+else
+       cp Makefile.in Makefile.tem
+fi
+
+# Remove all formfeeds, since some Makes get confused by them.
+sed "s/\f//" Makefile.tem > Makefile.tem1
+
+# Delete the intermediate files
+rm Makefile.tem
+if [ x$srcdir != x. ]
+then
+       rm Makefile.in
+fi
+
+
+# actual Makefile starts here.
+
+echo "host = $host" > Makefile
+echo "target = $target" >> Makefile
+
+# Define macro CROSS_ASSEMBLE in compilation if this is a cross-assembler.
+if [ x$host = x$target ]
+then
+       sed "/^ALL=gas/s//ALL=bootstrap/" < Makefile.tem1 >> Makefile
+else
+       echo "CROSS=-DCROSS_ASSEMBLE" >> Makefile
+       cat Makefile.tem1 >> Makefile
+fi
+
+rm Makefile.tem1
+
+echo "Edited the makefile"
+
+if [ x$host = x$target ]
+then
+       echo "Links are now set up for use with a $target." \
+               | tee config.status
+else
+       echo "Links are now set up for host $host and target $target." \
+               | tee config.status
+fi
+
+exit 0
diff --git a/gas/doc/a29k.m4 b/gas/doc/a29k.m4
new file mode 100644 (file)
index 0000000..cf3ba38
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_AMD29K__>,<1>)
+_define__(<_HOST__>,<AMD 29K>)
+_define__(<_MACH_DEP__>,<AMD29K Dependent>
+_divert__<>
\ No newline at end of file
index ee3c3d2992445de25f39fb1df4fe424fd3c746c4..e9f45cdd80655425fbf7301a31ee55f7903bb0ab 100644 (file)
@@ -1,15 +1,86 @@
-\input texinfo @c -*-texinfo-*-
-@tex
-\special{twoside}
-@end tex
-@setfilename as
-@settitle as
+\input texinfo
+@c @tex
+@c \special{twoside}
+@c @end tex
+_if__(_ALL_ARCH__)
+@setfilename as.info
+_fi__(_ALL_ARCH__)
+_if__(_AMD29K__ && !_ALL_ARCH__)
+@setfilename as-29k.info
+_fi__(_AMD29K__ && !_ALL_ARCH__)
+_if__(_I960__ && !_ALL_ARCH__)
+@setfilename as-960.info
+_fi__(_I960__ && !_ALL_ARCH__)
+_if__(_M680X0__ && !_ALL_ARCH__)
+@setfilename as-m680x0.info
+_fi__(_M680X0__ && !_ALL_ARCH__)
+@c
+@c NOTE: this manual is marked up for preprocessing with a collection
+@c of m4 macros called "pretex.m4".  If you see <_if__> and <_fi__>
+@c scattered around the source, you have the full source before
+@c preprocessing; if you don't, you have the source configured for
+@c _HOST__ architectures (and you can of course get the full source,
+@c with all configurations, from wherever you got this).
+_if__(0)
+
+THIS IS THE FULL SOURCE.  The full source needs to be run through m4
+before either tex- or info- formatting: for example,
+    m4 pretex.m4 none.m4 m680x0.m4 as.texinfo >as-680x0.texinfo
+will produce (assuming your path finds either GNU or SysV m4; Berkeley
+won't do) a file suitable for formatting.  See the text in "pretex.m4"
+for a fuller explanation (and the macro definitions).
+
+_fi__(0)
+@c
+@synindex ky cp
+@ifinfo
+This file documents the GNU Assembler "_AS__".
+
+Copyright (C) 1991 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 also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and 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 the section entitled ``GNU General Public License'' may be
+included in a translation approved by the author instead of in the
+original English.
+@end ifinfo
+@iftex
+@finalout
+@end iftex
+@smallbook
+@setchapternewpage odd
+_if__(_ALL_ARCH__)
+@settitle Using _AS__
+_fi__(_ALL_ARCH__)
+_if__(!_ALL_ARCH__)
+@settitle Using _AS__ (_HOST__)
+_fi__(!_ALL_ARCH__)
 @titlepage
-@center @titlefont{as}
+@title{Using _AS__}
+@subtitle{The GNU Assembler}
+_if__(!_ALL_ARCH__)
+@subtitle{for the _HOST__ family}
+_fi__(!_ALL_ARCH__)
 @sp 1
-@center The GNU Assembler
-@sp 2
-@center Dean Elsner, Jay Fenlason & friends
+@subtitle March 1991
 @sp 13
 The Free Software Foundation Inc.  thanks The Nice Computer
 Company of Australia for loaning Dean Elsner to write the
@@ -18,462 +89,551 @@ The proprietors, management and staff of TNCCA thank FSF for
 distracting the boss while they got some work
 done.
 @sp 3
+@author{Dean Elsner, Jay Fenlason & friends}
+@author{revised by Roland Pesch for Cygnus Support}
+@c pesch@cygnus.com
+@page
+@tex
+\def\$#1${{#1}}  % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision$}  % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+%"boxit" macro for figures:
+%Modified from Knuth's ``boxit'' macro from TeXbook (answer to exercise 21.3)
+\gdef\boxit#1#2{\vbox{\hrule\hbox{\vrule\kern3pt
+     \vbox{\parindent=0pt\parskip=0pt\hsize=#1\kern3pt\strut\hfil
+#2\hfil\strut\kern3pt}\kern3pt\vrule}\hrule}}%box with visible outline
+\gdef\ibox#1#2{\hbox to #1{#2\hfil}\kern8pt}% invisible box
+@end tex
 
-Copyright @copyright{} 1986,1987 Free Software Foundation, Inc.
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991 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.
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and 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.
-
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' may be
+included in a translation approved by the author instead of in the
+original English.
 @end titlepage
-@node top, Syntax, top, top
-@chapter Overview, Usage
-@menu
-* Syntax::           The (machine independent) syntax that assembly language
-                files must follow.  The machine dependent syntax
-                can be found in the machine dependent section of
-                the manual for the machine that you are using.
-* Segments::         How to use segments and subsegments, and how the
-                assembler and linker will relocate things.
-* Symbols::          How to set up and manipulate symbols.
-* Expressions::      And how the assembler deals with them.
-* PseudoOps::        The assorted machine directives that tell the
-                assembler exactly what to do with its input.
-* MachineDependent:: Information specific to each machine.
-* Maintenance::      Keeping the assembler running.
-* Retargeting::      Teaching the assembler about new machines.
-@end menu
-               
-This document describes the GNU assembler @code{as}.  This document
-does @emph{not} describe what an assembler does, or how it works.
-This document also does @emph{not} describe the opcodes, registers
-or addressing modes that @code{as} uses on any paticular computer
-that @code{as} runs on.  Consult a good book on assemblers or the
-machine's architecture if you need that information.
-
-This document describes the directives that @code{as} understands,
-and their syntax.  This document also describes some of the
-machine-dependent features of various flavors of the assembler.
+@page
+@node Top,,,
+@ifinfo
+This file is a user guide to the GNU assembler @code{_AS__}.
+_if__(!_ALL_ARCH__)
+This version of the file describes @code{_AS__} configured to generate
+code for _HOST__ architectures.
+_fi__(!_ALL_ARCH__)
+@end ifinfo
+@node Overview,,,
+@chapter Overview
+@iftex
+This manual is a user guide to the GNU assembler @code{_AS__}.
+_if__(!_ALL_ARCH__)
+This version of the manual describes @code{_AS__} configured to generate
+code for _HOST__ architectures.
+_fi__(!_ALL_ARCH__)
+@end iftex
+
+@node Invoking,,,
+@section Invoking @code{_AS__}
+
+Here is a brief summary of how to invoke @code{_AS__}.  For details,
+@pxref{Options}.
+
+@c We don't use @deffn and friends for the following because they seem
+@c to be limited to one line for the header.
+@smallexample
+  _AS__ [ -D ] [ -f ] [ -I @var{path} ] [ -k ] [ -L ]
+   [ -o @var{objfile} ] [ -R ] [ -v ] [ -w ]
+_if__(_AMD29K__)
+@c am29k has no machine-dependent assembler options
+_fi__(_AMD29K__)
+_if__(_I960__)
+@c see md_parse_option in i960.c
+   [ -ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC ]
+   [ -b ] [ -norelax ]
+_fi__(_I960__)
+_if__(_M680X0__)
+   [ -l ] [ -mc68000 | -mc68010 | -mc68020 ]
+_fi__(_M680X0__)
+   [ -- | @var{files} @dots{} ]
+@end smallexample
+
+@table @code
+
+@item -D
+This option is accepted only for script compatibility with calls to
+other assemblers; it has no effect on @code{_AS__}.
+
+@item -f
+``fast''---skip preprocessing (assume source is compiler output)
+
+@item -I @var{path}
+Add @var{path} to the search list for @code{.include} directives
+
+@item -k
+_if__(_AMD29K__ || _I960__)
+This option is accepted but has no effect on the _HOST__ family.
+_fi__(_AMD29K__ || _I960__)
+_if__(!(_AMD29K__||_I960__))
+Issue warnings when difference tables altered for long displacements
+_fi__(!(_AMD29K__||_I960__))
+
+@item -L
+Keep (in symbol table) local symbols, starting with @samp{L}
+
+@item -o @var{objfile}
+Name the object-file output from @code{_AS__}
+
+@item -R
+Fold data segment into text segment
+
+@item -W
+Suppress warning messages
+
+_if__(_I960__)
+@item -ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC
+Specify which variant of the 960 architecture is the target.
+
+@item -b
+Add code to collect statistics about branches taken.
+
+@item -norelax
+Do not alter compare-and-branch instructions for long displaements;
+error if necessary.
+_fi__(_I960__)
+
+_if__(_M680X0__)
+@item -l
+Shorten references to undefined symbols, to one word instead of two
+
+@item -mc68000 | -mc68010 | -mc68020
+Specify what processor in the 68000 family is the target (default 68020)
+_fi__(_M680X0__)
+
+@item -- | @var{files} @dots{}
+Source files to assemble, or standard input
+@end table
+
+@node Manual, GNU Assembler, Invoking, Overview
+@section Structure of this Manual
+This document is intended to describe what you need to know to use
+@code{_AS__}.  We cover the syntax expected in source files, including
+notation for symbols, constants, and expressions; the directives that
+@code{_AS__} understands; and of course how to invoke @code{_AS__}.
+
+_if__(!_ALL_ARCH__)
+We also cover special features in the _HOST__
+configuration of @code{_AS__}, including assembler directives.
+_fi__(!_ALL_ARCH__)
+_if__(_ALL_ARCH__)
+This document also describes some of the machine-dependent features of
+various flavors of the assembler.
+_fi__(_ALL_ARCH__)
+_if__(_INTERNALS__)
 This document also describes how the assembler works internally, and
 provides some information that may be useful to people attempting to
 port the assembler to another machine.
+_fi__(_INTERNALS__)
+@refill
 
+On the other hand, this manual is @emph{not} intended as an introduction
+to programming in assembly language---let alone programming in general!
+In a similar vein, we make no attempt to introduce the machine
+architecture; we do @emph{not} describe the instruction set, standard
+mnemonics, registers or addressing modes that are standard to a
+particular architecture.  You may want to consult the manufacturer's
+machine architecture manual for this information.
 
+
+@c I think this is premature---pesch@cygnus.com, 17jan1991
+@ignore
 Throughout this document, we assume that you are running @dfn{GNU},
 the portable operating system from the @dfn{Free Software
 Foundation, Inc.}.  This restricts our attention to certain kinds of
-computer (in paticular, the kinds of computers that GNU can run on);
+computer (in particular, the kinds of computers that GNU can run on);
 once this assumption is granted examples and definitions need less
 qualification.
 
-Readers should already comprehend:
-@itemize @bullet
-@item
-Central processing unit
-@item
-registers
-@item
-memory address
-@item
-contents of memory address
-@item
-bit
-@item
-8-bit byte
-@item
-2's complement arithmetic
-@end itemize
-
-@code{as} is part of a team of programs that turn a high-level
+@code{_AS__} is part of a team of programs that turn a high-level
 human-readable series of instructions into a low-level
 computer-readable series of instructions.  Different versions of
-@code{as} are used for different kinds of computer.  In paticular,
-at the moment, @code{as} only works for the DEC Vax, the Motorola
-680x0, the Intel 80386, the Sparc, and the National Semiconductor
-32032/32532.
-
-@section Notation
-GNU and @code{as} assume the computer that will run the programs it
-assembles will obey these rules.
-
-A (memory) @dfn{address} is 32 bits. The lowest address is zero.
-
-The @dfn{contents} of any memory address is one @dfn{byte} of
-exactly 8 bits.
-
-A @dfn{word} is 16 bits stored in two bytes of memory. The addresses
-of the bytes differ by exactly 1.  Notice that the interpretation of
-the bits in a word and of how to address a word depends on which
-particular computer you are assembling for.
-
-A @dfn{long word}, or @dfn{long}, is 32 bits composed of four bytes.
-It is stored in 4 bytes of memory; these bytes have contiguous
-addresses.  Again the interpretation and addressing of those bits is
-machine dependent.  National Semiconductor 32x32 computers say
-@i{double word} where we say @i{long}.
-
-Numeric quantities are usually @i{unsigned} or @i{2's complement}.
-Bytes, words and longs may store numbers.  @code{as} manipulates
-integer expressions as 32-bit numbers in 2's complement format.
-When asked to store an integer in a byte or word, the lowest order
-bits are stored.  The order of bytes in a word or long in memory is
-determined by what kind of computer will run the assembled program.
-We won't mention this important @i{caveat} again.
-
-The meaning of these terms has changed over time.  Although @i{byte}
-used to mean any length of contiguous bits, @i{byte} now pervasively
-means exactly 8 contiguous bits.  A @i{word} of 16 bits made sense
-for 16-bit computers.  Even on 32-bit computers, a @i{word} still
-means 16 bits (to machine language programmers).  To many other
-programmers of GNU a @i{word} means 32 bits, so beware.  Similarly
-@i{long} means 32 bits: from ``long word''.  National Semiconductor
-32x32 machine language calls a 32-bit number a ``double word''.
-
-@example
-
-       Names for integers of different sizes: some conventions
-
-
-length   as          vax        32x32        680x0        GNU C
-(bits)
-
-  8    byte         byte         byte         byte         char
- 16    word         word         word         word  short (int)
- 32    long  long(-word)  double-word  long(-word)   long (int)
- 64    quad  quad(-word)
-128    octa    octa-word
-
-@end example
-
-@section as, the GNU Assembler
-@dfn{As} is an assembler; it is one of the team of programs that
-`compile' your programs into the binary numbers that a computer uses
-to `run' your program.  Often @code{as} reads a @i{source} program
-written by a compiler and writes an @dfn{object} program for the
-linker (sometimes referred to as a @dfn{loader}) @code{ld} to read.
-
-The source program consists of @dfn{statements} and comments.  Each
-statement might @dfn{assemble} to one (and only one) machine
-language instruction or to one very simple datum.
-
-Mostly you don't have to think about the assembler because the
-compiler invokes it as needed; in that sense the assembler is just
-another part of the compiler.  If you write your own assembly
-language program, then you must run the assembler yourself to get an
-object file suitable for linking.  You can read below how to do this.
-
-@code{as} is only intended to assemble the output of the C compiler
-@code{cc} for use by the linker @code{ld}.  @code{as} tries to
-assemble correctly everything that the standard assembler would
-assemble, with a few exceptions (described in the machine-dependent
-chapters.)  Note that this doesn't mean @code{as} will use the same
-syntax as the standard assembler.  For example, we know of several
-incompatable syntaxes for the 680x0.
-
-Each version of the assembler knows about just one kind of machine
-language, but much is common between the versions, including object
-file formats, (most) assembler directives (often called
-@dfn{pseudo-ops)} and assembler syntax.
-
-Unlike older assemblers, @code{as} tries to assemble a source program
-in one pass of the source file.  This subtly changes the meaning of
-the @kbd{.org} directive (@xref{Org}.).
-
-If you want to write assembly language programs, you must tell
-@code{as} what numbers should be in a computer's memory, and which
-addresses should contain them, so that the program may be executed
-by the computer.  Using symbols will prevent many bookkeeping
-mistakes that can occur if you use raw numbers.
-
-@section Command Line Synopsis
-@example
-as [ options @dots{} ] [ file1 @dots{} ]
-@end example
+@code{_AS__} are used for different kinds of computer.
+@end ignore
 
-After the program name @code{as}, the command line may contain
+@c There used to be a section "Terminology" here, which defined
+@c "contents", "byte", "word", and "long".  Defining "word" to any
+@c particular size is confusing when the .word directive may generate 16
+@c bits on one machine and 32 bits on another; in general, for the user
+@c version of this manual, none of these terms seem essential to define.
+@c They were used very little even in the former draft of the manual;
+@c this draft makes an effort to avoid them (except in names of
+@c directives).
+
+@node GNU Assembler,,,
+@section _AS__, the GNU Assembler
+GNU @code{as} is really a family of assemblers.  
+_if__(!_ALL_ARCH__)
+This manual describes @samp{_AS__}, a member of that family which is
+configured for the _HOST__ architectures.
+_fi__(!_ALL_ARCH__)
+If you use (or have used) the GNU assembler on another architecture, you
+should find a fairly similar environment.  Each version has much in
+common with the others, including object file formats, most assembler
+directives (often called @dfn{pseudo-ops)} and assembler syntax.@refill
+
+@code{_AS__} is primarily intended to assemble the output of the GNU C
+compiler @code{_GCC__} for use by the linker @code{_LD__}.  Nevertheless,
+we've tried to make @code{_AS__} assemble correctly everything that the native
+assembler would.
+_if__(_VAX__)
+Any exceptions are documented explicitly (@pxref{_MACH_DEP__}).
+_fi__(_VAX__)
+_if__(_ALL_ARCH__||_M680X0__)
+This doesn't mean @code{_AS__} always uses the same syntax as another
+assembler for the same architecture; for example, we know of several
+incompatible versions of 680x0 assembly language syntax.
+_fi__(_ALL_ARCH__||_M680X0__)
+
+Unlike older assemblers, @code{_AS__} is designed to assemble a source
+program in one pass of the source file.  This has a subtle impact on the
+@kbd{.org} directive (@pxref{Org}).
+
+@node Object Formats,,,
+@section Object File Formats
+The GNU assembler can be configured to produce several alternative
+object file formats.  
+_if__(!_ALL_ARCH__)
+_if__(!_I960__)
+@code{_AS__} is configured to produce @code{a.out} format object
+files.@refill
+_fi__(!_I960__)
+_if__(_I960__)
+@code{_AS__} can be configured to produce either @code{b.out} or COFF
+format object files.
+_fi__(_I960__)
+_fi__(!_ALL_ARCH__)
+
+@node Command Line,,,
+@section Command Line
+
+After the program name @code{_AS__}, the command line may contain
 options and file names.  Options may be in any order, and may be
 before, after, or between file names.  The order of file names is
 significant.
 
-@subsection Options
+@file{--} (two hyphens) by itself names the standard input file
+explicitly, as one of the files for @code{_AS__} to assemble.
 
 Except for @samp{--} any command line argument that begins with a
 hyphen (@samp{-}) is an option.  Each option changes the behavior of
-@code{as}.  No option changes the way another option works.  An
-option is a @samp{-} followed by one ore more letters; the case of
-the letter is important.  No option (letter) should be used twice on
-the same command line.  (Nobody has decided what two copies of the
-same option should mean.)  All options are optional.
+@code{_AS__}.  No option changes the way another option works.  An
+option is a @samp{-} followed by one or more letters; the case of
+the letter is important.   All options are optional.
 
 Some options expect exactly one file name to follow them.  The file
 name may either immediately follow the option's letter (compatible
 with older assemblers) or it may be the next command argument (GNU
 standard).  These two command lines are equivalent:
 
-@example
-as -o my-object-file.o mumble
-as -omy-object-file.o mumble
-@end example
-
-Always, @file{--} (that's two hyphens, not one) by itself names the
-standard input file.
+@smallexample
+_AS__ -o my-object-file.o mumble.s
+_AS__ -omy-object-file.o mumble.s
+@end smallexample
 
-@section Input File(s)
+@node Input Files, Object, Command Line, Overview
+@section Input Files
 
-We use the words @dfn{source program}, abbreviated @dfn{source}, to
-describe the program input to one run of @code{as}.  The program may
+We use the phrase @dfn{source program}, abbreviated @dfn{source}, to
+describe the program input to one run of @code{_AS__}.  The program may
 be in one or more files; how the source is partitioned into files
 doesn't change the meaning of the source.
 
-The source text is a catenation of the text in each file.
+@c I added "con" prefix to "catenation" just to prove I can overcome my
+@c APL training...   pesch@cygnus.com
+The source program is a concatenation of the text in all the files, in the
+order specified.
 
-Each time you run @code{as} it assembles exactly one source
-program.  A source program text is made of one or more files.
+Each time you run @code{_AS__} it assembles exactly one source
+program.  The source program is made up of one or more files.
 (The standard input is also a file.)
 
-You give @code{as} a command line that has zero or more input file
+You give @code{_AS__} a command line that has zero or more input file
 names.  The input files are read (from left file name to right).  A
 command line argument (in any position) that has no special meaning
-is taken to be an input file name.  If @code{as} is given no file
-names it attempts to read one input file from @code{as}'s standard
-input.
-
-Use @file{--} if you need to explicitly name the standard input file
-in your command line.
+is taken to be an input file name.
 
-It is OK to assemble an empty source.  @code{as} will produce a
-small, empty object file.
+If @code{_AS__} is given no file names it attempts to read one input file
+from the @code{_AS__} standard input, which is normally your terminal.  You
+may have to type @key{ctl-D} to tell @code{_AS__} there is no more program
+to assemble.
 
-If you try to assemble no files then @code{as} will try to read
-standard input, which is normally your terminal.  You may have to
-type @key{ctl-D} to tell @code{as} there is no more program to
-assemble.
+Use @samp{--} if you need to explicitly name the standard input file
+in your command line.
 
-@subsection Input Filenames and Line-numbers
-A line is text up to and including the next newline.  The first line
-of a file is numbered @b{1}, the next @b{2} and so on.
+If the source is empty, @code{_AS__} will produce a small, empty object
+file.
 
-There are two ways of locating a line in the input file(s) and both
+@node Filenames,  , Input Files, Input Files
+@subsection Filenames and Line-numbers
+There are two ways of locating a line in the input file (or files) and both
 are used in reporting error messages.  One way refers to a line
 number in a physical file; the other refers to a line number in a
-logical file.
+``logical'' file.
 
 @dfn{Physical files} are those files named in the command line given
-to @code{as}.
+to @code{_AS__}.
 
-@dfn{Logical files} are ``pretend'' files which bear no relation to
-physical files.  Logical file names help error messages reflect the
-proper source file.  Often they are used when @code{as}' source is
-itself synthesized from other files.
+@dfn{Logical files} are simply names declared explicitly by assembler
+directives; they bear no relation to physical files.  Logical file names
+help error messages reflect the original source file, when @code{_AS__}
+source is itself synthesized from other files.  @xref{App-File}.
 
+@node Object, Errors, Input Files, Overview
 @section Output (Object) File
-Every time you run @code{as} it produces an output file, which is
+Every time you run @code{_AS__} it produces an output file, which is
 your assembly language program translated into numbers.  This file
-is the object file; named @code{a.out} unless you tell @code{as} to
+is the object file, named @code{a.out} unless you tell @code{_AS__} to
 give it another name by using the @code{-o} option.  Conventionally,
 object file names end with @file{.o}.  The default name of
-@file{a.out} is used for historical reasons.  Older assemblers were
+@file{a.out} is used for historical reasons:  older assemblers were
 capable of assembling self-contained programs directly into a
-runnable program.  This may still work, but hasn't been tested.
+runnable program.
+@c This may still work, but hasn't been tested.
 
-The object file is for input to the linker @code{ld}.  It contains
-assembled program code, information to help @code{ld} to integrate
-the assembled program into a runnable file and (optionally) symbolic
-information for the debugger.  The precise format of object files is
-described elsewhere.
+The object file is meant for input to the linker @code{_LD__}.  It contains
+assembled program code, information to help @code{_LD__} integrate
+the assembled program into a runnable file, and (optionally) symbolic
+information for the debugger.
 
 @comment link above to some info file(s) like the description of a.out.
 @comment don't forget to describe GNU info as well as Unix lossage.
 
+@node Errors, Options, Object, Overview
 @section Error and Warning Messages
 
-@code{as} may write warnings and error messages to the standard
-error file (usually your terminal).  This should not happen when
-@code{as} is run automatically by a compiler.  Error messages are
-useful for those (few) people who still write in assembly language.
-
-Warnings report an assumption made so that @code{as} could keep
-assembling a flawed program.
-
-Errors report a grave problem that stops the assembly.
+@code{_AS__} may write warnings and error messages to the standard error
+file (usually your terminal).  This should not happen when @code{_AS__} is
+run automatically by a compiler.  Warnings report an assumption made so
+that @code{_AS__} could keep assembling a flawed program; errors report a
+grave problem that stops the assembly.
 
 Warning messages have the format
-@example
-file_name:line_number:Warning Message Text
-@end example
-If a logical file name has been given (@xref{File}.) it is used for
-the filename, otherwise the name of the current input file is used.
-If a logical line number was given (@xref{Line}.) then it is used to
-calculate the number printed, otherwise the actual line in the
-current source file is printed.  The message text is intended to be
-self explanatory (In the grand Unix tradition).
+@smallexample
+file_name:@b{NNN}:Warning Message Text
+@end smallexample
+@noindent(where @b{NNN} is a line number).  If a logical file name has
+been given (@pxref{App-File}) it is used for the filename, otherwise the
+name of the current input file is used.  If a logical line number was
+given
+_if__(!_AMD29K__)
+(@pxref{Line})
+_fi__(!_AMD29K__)
+_if__(_AMD29K__)
+(@pxref{Ln})
+_fi__(_AMD29K__)
+then it is used to calculate the number printed,
+otherwise the actual line in the current source file is printed.  The
+message text is intended to be self explanatory (in the grand Unix
+tradition). @refill
 
 Error messages have the format
-@example
-file_name:line_number:FATAL:Error Message Text
-@end example
-The file name and line number are derived the same as for warning
+@smallexample
+file_name:@b{NNN}:FATAL:Error Message Text
+@end smallexample
+The file name and line number are derived as for warning
 messages.  The actual message text may be rather less explanatory
 because many of them aren't supposed to happen.
 
+@node Options,  , Errors, Overview
 @section Options
-@subsection -f Works Faster
+This section describes command-line options available in @emph{all}
+versions of the GNU assembler; @pxref{_MACH_DEP__}, for options specific
+to the _HOST__.
+
+@subsection @code{-D}
+This option has no effect whatsoever, but it is accepted to make it more
+likely that scripts written for other assemblers will also work with
+@code{_AS__}.
+
+@subsection Work Faster: @code{-f}
 @samp{-f} should only be used when assembling programs written by a
-(trusted) compiler.  @samp{-f} causes the assembler to not bother
-pre-processing the input file(s) before assembling them.  Needless
-to say, if the files actually need to be pre-processed (if the
-contain comments, for example), @code{as} will not work correctly if
+(trusted) compiler.  @samp{-f} stops the assembler from pre-processing
+the input file(s) before assembling them.
+@quotation
+@emph{Warning:} if the files actually need to be pre-processed (if they
+contain comments, for example), @code{_AS__} will not work correctly if
 @samp{-f} is used.
-
-@subsection -L Includes Local Labels
-For historical reasons, labels beginning with @samp{L} (upper case
-only) are called @dfn{local labels}.  Normally you don't see such
-labels because they are intended for the use of programs (like
+@end quotation
+
+@subsection @code{.include} search path: @code{-I} @var{path}
+Use this option to add a @var{path} to the list of directories
+@code{_AS__} will search for files specified in @code{.include} directives
+(@pxref{Include}).  You may use @code{-I} as many times as necessary to
+include a variety of paths.  The current working directory is always
+searched first; after that, @code{_AS__} searches any @samp{-I} directories
+in the same order as they were specified (left to right) on the command
+line.
+
+@subsection Difference Tables: @code{-k}
+_if__(_AMD29K__ || _I960__)
+On the _HOST__ family, this option is allowed, but has no effect.  It is
+permitted for compatibility with the GNU assembler on other platforms,
+where it can be used to warn when the assembler alters the machine code
+generated for @samp{.word} directives in difference tables.  The _HOST__
+family does not have the addressing limitations that sometimes lead to this
+alteration on other platforms.
+_fi__(_AMD29K__ || _I960__)
+
+_if__(! (_AMD29K__ || _I960__) )
+@code{_AS__} sometimes alters the code emitted for directives of the form
+@samp{.word @var{sym1}-@var{sym2}}; @pxref{Word}.
+You can use the @samp{-k} option if you want a warning issued when this
+is done.
+_fi__(! (_AMD29K__ || _I960__) )
+
+@subsection Include Local Labels: @code{-L}
+Labels beginning with @samp{L} (upper case only) are called @dfn{local
+labels}. @xref{Symbol Names}.  Normally you don't see such labels when
+debugging, because they are intended for the use of programs (like
 compilers) that compose assembler programs, not for your notice.
-Normally both @code{as} and @code{ld} discard such labels, so you
-don't normally debug with them.
+Normally both @code{_AS__} and @code{_LD__} discard such labels, so you don't
+normally debug with them.
 
-This option tells @code{as} to retain those @samp{L@dots{}} symbols
+This option tells @code{_AS__} to retain those @samp{L@dots{}} symbols
 in the object file.  Usually if you do this you also tell the linker
-@code{ld} to preserve symbols whose names begin with @samp{L}.
+@code{_LD__} to preserve symbols whose names begin with @samp{L}.
 
-@subsection -o Names the Object File
-There is always one object file output when you run @code{as}.  By
+@subsection Name the Object File: @code{-o}
+There is always one object file output when you run @code{_AS__}.  By
 default it has the name @file{a.out}.  You use this option (which
 takes exactly one filename) to give the object file a different name.
 
-Whatever the object file is called, @code{as} will overwrite any
+Whatever the object file is called, @code{_AS__} will overwrite any
 existing file of the same name.
 
-@subsection -R Folds Data Segment into Text Segment
-@code{-R} tells @code{as} to write the object file as if all
+@subsection Join Data and Text Segments: @code{-R}
+@code{-R} tells @code{_AS__} to write the object file as if all
 data-segment data lives in the text segment.  This is only done at
 the very last moment:  your binary data are the same, but data
 segment parts are relocated differently.  The data segment part of
 your object file is zero bytes long because all it bytes are
 appended to the text segment.  (@xref{Segments}.)
 
-When you use @code{-R} it would be nice to generate shorter address
-displacements (possible because we don't have to cross segments)
-between text and data segment.  We don't do this simply for
-compatibility with older versions of @code{as}.  @code{-R} may work
-this way in future.
+When you specify @code{-R} it would be possible to generate shorter
+address displacements (because we don't have to cross between text and
+data segment).  We refrain from doing this simply for compatibility with
+older versions of @code{_AS__}.  In future, @code{-R} may work this way.
 
-@subsection -W Represses Warnings
-@code{as} should never give a warning or error message when
+@subsection Suppress Warnings: @code{-W}
+@code{_AS__} should never give a warning or error message when
 assembling compiler output.  But programs written by people often
-cause @code{as} to give a warning that a particular assumption was
+cause @code{_AS__} to give a warning that a particular assumption was
 made.  All such warnings are directed to the standard error file.
-If you use this option, any warning is repressed.  This option only
-affects warning messages: it cannot change any detail of how
-@code{as} assembles your file.  Errors, which stop the assembly, are
+If you use this option, no warnings are issued.  This option only
+affects the warning messages: it does not change any particular of how
+@code{_AS__} assembles your file.  Errors, which stop the assembly, are
 still reported.
 
-@section Special Features to support Compilers
+@node Syntax, Segments, Overview, Top
+@chapter Syntax
+This chapter describes the machine-independent syntax allowed in a
+source file.  @code{_AS__} syntax is similar to what many other assemblers
+use; it is inspired in BSD 4.2
+_if__(!_VAX__)
+assembler. @refill
+_fi__(!_VAX__)
+_if__(_VAX__)
+assembler, except that @code{_AS__} does not assemble Vax bit-fields.
+_fi__(_VAX__)
+
+@node Pre-processing, Whitespace, Syntax, Syntax
+@section Pre-processing
+
+The pre-processor:
+@itemize @bullet
+@item
+adjusts and removes extra whitespace.  It leaves one space or tab before
+the keywords on a line, and turns any other whitespace on the line into
+a single space.
 
-In order to assemble compiler output into something that will work,
-@code{as} will occasionlly do strange things to @samp{.word}
-directives.  In particular, when @code{gas} assembles a directive of
-the form @samp{.word sym1-sym2}, and the difference between
-@code{sym1} and @code{sym2} does not fit in 16 bits, @code{as} will
-create a @dfn{secondary jump table}, immediately before the next
-label.  This @var{secondary jump table} will be preceeded by a
-short-jump to the first byte after the table.  The short-jump
-prevents the flow-of-control from accidentally falling into the
-table.  Inside the table will be a long-jump to @code{sym2}.  The
-original @samp{.word} will contain @code{sym1} minus (the address of
-the long-jump to sym2) If there were several @samp{.word sym1-sym2}
-before the secondary jump table, all of them will be adjusted.  If
-ther was a @samp{.word sym3-sym4}, that also did not fit in sixteen
-bits, a long-jump to @code{sym4} will be included in the secondary
-jump table, and the @code{.word}(s), will be adjusted to contain
-@code{sym3} minus (the address of the long-jump to sym4), etc.
-
-@emph{This feature may be disabled by compiling @code{as} with the
-@samp{-DWORKING_DOT_WORD} option.} This feature is likely to confuse
-assembly language programmers.
+@item
+removes all comments, replacing them with a single space, or an
+appropriate number of newlines.
 
-@node Syntax, Segments, top, top
-@chapter Syntax
-This chapter informally defines the machine-independent syntax
-allowed in a source file.  @code{as} has ordinary syntax; it tries
-to be upward compatible from BSD 4.2 assembler except @code{as} does
-not assemble Vax bit-fields.
-
-@section The Pre-processor
-The preprocess phase handles several aspects of the syntax.  The
-pre-processor will be disabled by the @samp{-f} option, or if the
-first line of the source file is @code{#NO_APP}.  The option to
-disable the pre-processor was designed to make compiler output
-assemble as fast as possible.
-
-The pre-processor adjusts and removes extra whitespace.  It leaves
-one space or tab before the keywords on a line, and turns any other
-whitespace on the line into a single space.
-
-The pre-processor removes all comments, replacing them with a single
-space (for /* @dots{} */ comments), or an appropriate number of
-newlines.
-
-The pre-processor converts character constants into the appropriate
-numeric values.
-
-This means that excess whitespace, comments, and character constants
+@item
+converts character constants into the appropriate numeric values.
+@end itemize
+
+Excess whitespace, comments, and character constants
 cannot be used in the portions of the input text that are not
 pre-processed.
 
-If the first line of an input file is @code{#NO_APP} or the
-@samp{-f} option is given, the input file will not be
-pre-processed.  Within such an input file, parts of the file can be
-pre-processed by putting a line that says @code{#APP} before the
-text that should be pre-processed, and putting a line that says
-@code{#NO_APP} after them.  This feature is mainly intend to support
-asm statements in compilers whose output normally does not need to
-be pre-processed.
+If the first line of an input file is @code{#NO_APP} or the @samp{-f}
+option is given, the input file will not be pre-processed.  Within such
+an input file, parts of the file can be pre-processed by putting a line
+that says @code{#APP} before the text that should be pre-processed, and
+putting a line that says @code{#NO_APP} after them.  This feature is
+mainly intend to support @code{asm} statements in compilers whose output
+normally does not need to be pre-processed.
 
+@node Whitespace, Comments, Pre-processing, Syntax
 @section Whitespace
 @dfn{Whitespace} is one or more blanks or tabs, in any order.
 Whitespace is used to separate symbols, and to make programs neater
 for people to read.  Unless within character constants
-(@xref{Characters}.), any whitespace means the same as exactly one
+(@pxref{Characters}), any whitespace means the same as exactly one
 space.
 
+@node Comments, Symbol Intro, Whitespace, Syntax
 @section Comments
-There are two ways of rendering comments to @code{as}.  In both
+There are two ways of rendering comments to @code{_AS__}.  In both
 cases the comment is equivalent to one space.
 
 Anything from @samp{/*} through the next @samp{*/} is a comment.
+This means you may not nest these comments.
 
-@example
+@smallexample
 /*
   The only way to include a newline ('\n') in a comment
   is to use this sort of comment.
 */
+
 /* This sort of comment does not nest. */
-@end example
+@end smallexample
 
 Anything from the @dfn{line comment} character to the next newline
-considered a comment and is ignored.  The line comment character is
-@samp{#} on the Vax, and @samp{|} on the 680x0.
-@xref{MachineDependent}.  On some machines there are two different
-line comment characters.  One will only begin a comment if it is the
-first non-whitespace character on a line, while the other will
-always begin a comment.
+is considered a comment and is ignored.  The line comment character is
+_if__(_VAX__ || _I960__)
+@samp{#} on the _HOST__;
+_fi__(_VAX__ || _I960__)
+_if__(_M680X0__)
+@samp{|} on the 680x0;
+_fi__(_M680X0__)
+_if__(_AMD29K__)
+@samp{;} for the AMD 29K family;
+_fi__(_AMD29K__)
+@pxref{_MACH_DEP__}.  @refill
+
+_if__(_ALL_ARCH__)
+On some machines there are two different line comment characters.  One
+will only begin a comment if it is the first non-whitespace character on
+a line, while the other will always begin a comment.
+_fi__(_ALL_ARCH__)
 
 To be compatible with past assemblers a special interpretation is
 given to lines that begin with @samp{#}.  Following the @samp{#} an
@@ -484,97 +644,110 @@ name.  The rest of the line, if any, should be whitespace.
 
 If the first non-whitespace characters on the line are not numeric,
 the line is ignored.  (Just like a comment.)
-@example
+@smallexample
                           # This is an ordinary comment.
 # 42-6 "new_file_name"    # New logical file name
                           # This is logical line # 36.
-@end example
+@end smallexample
 This feature is deprecated, and may disappear from future versions
-of @code{as}.
+of @code{_AS__}.
 
+@node Symbol Intro, Statements, Comments, Syntax
 @section Symbols
 A @dfn{symbol} is one or more characters chosen from the set of all
 letters (both upper and lower case), digits and the three characters
-@samp{_.$}.  No symbol may begin with a digit.  Case is
-significant.  There is no length limit: all characters are
-significant.  Symbols are delimited by characters not in that set,
-or by begin/end-of-file.  (@xref{Symbols}.)
+@samp{_.$}.  No symbol may begin with a digit.  Case is significant.
+There is no length limit: all characters are significant.  Symbols are
+delimited by characters not in that set, or by the beginning of a file
+(since the source program must end with a newline, the end of a file is
+not a possible symbol delimiter).  @xref{Symbols}.
 
+@node Statements, Constants, Symbol Intro, Syntax
 @section Statements
+_if__(!_AMD29K__)
 A @dfn{statement} ends at a newline character (@samp{\n}) or at a
-semicolon (@samp{;}).  The newline or semicolon is considered part
-of the preceding statement.  Newlines and semicolons within
-character constants are an exception:  they don't end statements.
+semicolon (@samp{;}).  The newline or semicolon is considered part of
+the preceding statement.  Newlines and semicolons within character
+constants are an exception: they don't end statements.
+_fi__(!_AMD29K__)
+_if__(_AMD29K__)
+A @dfn{statement} ends at a newline character (@samp{\n}) or an ``at''
+sign (@samp{@@}).  The newline or at sign is considered part of the
+preceding statement.  Newlines and at signs within character constants
+are an exception: they don't end statements.
+_fi__(_AMD29K__)
+
 It is an error to end any statement with end-of-file:  the last
-character of any input file should be a newline.
+character of any input file should be a newline.@refill
 
 You may write a statement on more than one line if you put a
 backslash (@kbd{\}) immediately in front of any newlines within the
-statement.  When @code{as} reads a backslashed newline both
+statement.  When @code{_AS__} reads a backslashed newline both
 characters are ignored.  You can even put backslashed newlines in
 the middle of symbol names without changing the meaning of your
 source program.
 
-An empty statement is OK, and may include whitespace.  It is ignored.
+An empty statement is allowed, and may include whitespace.  It is ignored.
 
-Statements begin with zero or more labels, followed by a @dfn{key
-symbol} which determines what kind of statement it is.  The key
+@c "key symbol" is not used elsewhere in the document; seems pedantic to
+@c @defn{} it in that case, as was done previously...  pesch@cygnus.com,
+@c 13feb91.
+A statement begins with zero or more labels, optionally followed by a
+key symbol which determines what kind of statement it is.  The key
 symbol determines the syntax of the rest of the statement.  If the
-symbol begins with a dot (@t{.}) then the statement is an assembler
-directive: typically valid for any computer.  If the symbol begins
-with a letter the statement is an assembly language
-@dfn{instruction}: it will assemble into a machine language
-instruction.  Different versions of @code{as} for different
-computers will recognize different instructions.  In fact, the same
-symbol may represent a different instruction in a different
-computer's assembly language.
-
-A label is usually a symbol immediately followed by a colon
-(@code{:}).  Whitespace before a label or after a colon is OK.  You
-may not have whitespace between a label's symbol and its colon.
-Labels are explained below.
-@xref{Labels}.
-
-@example
+symbol begins with a dot @samp{.} then the statement is an assembler
+directive: typically valid for any computer.  If the symbol begins with
+a letter the statement is an assembly language @dfn{instruction}: it
+will assemble into a machine language instruction.  
+_if__(_ALL_ARCH__)
+Different versions of @code{_AS__} for different computers will
+recognize different instructions.  In fact, the same symbol may
+represent a different instruction in a different computer's assembly
+language.@refill
+_fi__(_ALL_ARCH__)
+
+A label is a symbol immediately followed by a colon (@code{:}).
+Whitespace before a label or after a colon is permitted, but you may not
+have whitespace between a label's symbol and its colon. @xref{Labels}.
+
+@smallexample
 label:     .directive    followed by something
 another$label:           # This is an empty statement.
            instruction   operand_1, operand_2, @dots{}
-@end example
+@end smallexample
 
+@node Constants,  , Statements, Syntax
 @section Constants
 A constant is a number, written so that its value is known by
 inspection, without knowing any context.  Like this:
-@example
+@smallexample
 .byte  74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.
 .ascii "Ring the bell\7"                  # A string constant.
 .octa  0x123456789abcdef0123456789ABCDEF0 # A bignum.
 .float 0f-314159265358979323846264338327\
 95028841971.693993751E-40                 # - pi, a flonum.
-@end example
+@end smallexample
 
-@node Characters, Strings, , Syntax
+@node Characters, Numbers, Constants, Constants
 @subsection Character Constants
-There are two kinds of character constants.  @dfn{Characters} stand
-for one character in one byte and their values may be used in
+There are two kinds of character constants.  A @dfn{character} stands
+for one character in one byte and its value may be used in
 numeric expressions.  String constants (properly called string
-@i{literals}) are potentially many bytes and their values may not be
+@emph{literals}) are potentially many bytes and their values may not be
 used in arithmetic expressions.
 
-@node Strings, , Characters, Syntax
+@node Strings, Chars, Characters, Characters
 @subsubsection Strings
 A @dfn{string} is written between double-quotes.  It may contain
-double-quotes or null characters.  The way to get weird characters
+double-quotes or null characters.  The way to get special characters
 into a string is to @dfn{escape} these characters: precede them with
-a backslash (@code{\}) character.  For example @samp{\\} represents
+a backslash @samp{\} character.  For example @samp{\\} represents
 one backslash:  the first @code{\} is an escape which tells
-@code{as} to interpret the second character literally as a backslash
-(which prevents @code{as} from recognizing the second @code{\} as an
+@code{_AS__} to interpret the second character literally as a backslash
+(which prevents @code{_AS__} from recognizing the second @code{\} as an
 escape character).  The complete list of escapes follows.
 
 @table @kbd
-@item \EOF
-A @kbd{\} followed by end-of-file erroneous.  It is treated just
-like an end-of-file without a preceding backslash.
 @c     @item \a
 @c     Mnemonic for ACKnowledge; for ASCII this is octal code 007.
 @item \b
@@ -600,8 +773,8 @@ Mnemonic for horizontal Tab; for ASCII this is octal code 011.
 @c     A hexadecimal character code.  The numeric code is 3 hexadecimal digits.
 @item \ @var{digit} @var{digit} @var{digit}
 An octal character code.  The numeric code is 3 octal digits.
-For compatibility with other Unix systems, 8 and 9 are legal digits
-with values 010 and 011 respectively.
+For compatibility with other Unix systems, 8 and 9 are accepted as digits:
+for example, @code{\008} has the value 010, and @code{\009} the value 011.
 @item \\
 Represents one @samp{\} character.
 @c     @item \'
@@ -616,38 +789,50 @@ this character, because an unescaped @samp{"} would end the string.
 Any other character when escaped by @kbd{\} will give a warning, but
 assemble as if the @samp{\} was not present.  The idea is that if
 you used an escape sequence you clearly didn't want the literal
-interpretation of the following character.  However @code{as} has no
-other interpretation, so @code{as} knows it is giving you the wrong
+interpretation of the following character.  However @code{_AS__} has no
+other interpretation, so @code{_AS__} knows it is giving you the wrong
 code and warns you of the fact.
 @end table
 
 Which characters are escapable, and what those escapes represent,
 varies widely among assemblers.  The current set is what we think
-BSD 4.2 @code{as} recognizes, and is a subset of what most C
+the BSD 4.2 assembler recognizes, and is a subset of what most C
 compilers recognize.  If you are in doubt, don't use an escape
 sequence.
 
+@node Chars,  , Strings, Characters
 @subsubsection Characters
 A single character may be written as a single quote immediately
 followed by that character.  The same escapes apply to characters as
 to strings.  So if you want to write the character backslash, you
 must write @kbd{'\\} where the first @code{\} escapes the second
-@code{\}.  As you can see, the quote is an accent acute, not an
-accent grave.  A newline (or semicolon (@samp{;})) immediately
-following an accent acute is taken as a literal character and does
-not count as the end of a statement.  The value of a character
+@code{\}.  As you can see, the quote is an acute accent, not a
+grave accent.  A newline
+_if__(!_AMD29K__)
+(or semicolon @samp{;})
+_fi__(!_AMD29K__)
+_if__(_AMD29K__)
+(or at sign @samp{@@})
+_fi__(_AMD29K__)
+immediately following an acute accent is taken as a literal character
+and does not count as the end of a statement.  The value of a character
 constant in a numeric expression is the machine's byte-wide code for
-that character.  @code{as} assumes your character code is ASCII: @kbd{'A}
-means 65, @kbd{'B} means 66, and so on.
+that character.  @code{_AS__} assumes your character code is ASCII:
+@kbd{'A} means 65, @kbd{'B} means 66, and so on. @refill
 
+@node Numbers,,,
 @subsection Number Constants
-@code{as} distinguishes 3 flavors of numbers according to how they
-are stored in the target machine.  @i{Integers} are numbers that
-would fit into an @code{int} in the C language.  @i{Bignums} are
-integers, but they are stored in a more than 32 bits.  @i{Flonums}
+@code{_AS__} distinguishes three kinds of numbers according to how they
+are stored in the target machine.  @emph{Integers} are numbers that
+would fit into an @code{int} in the C language.  @emph{Bignums} are
+integers, but they are stored in more than 32 bits.  @emph{Flonums}
 are floating point numbers, described below.
 
+@node Integers,,,
 @subsubsection Integers
+A binary integer is @samp{0b} or @samp{0B} followed by zero or more of
+the binary digits @samp{01}.
+
 An octal integer is @samp{0} followed by zero or more of the octal
 digits (@samp{01234567}).
 
@@ -657,49 +842,59 @@ more digits (@samp{0123456789}).
 A hexadecimal integer is @samp{0x} or @samp{0X} followed by one or
 more hexadecimal digits chosen from @samp{0123456789abcdefABCDEF}.
 
-Integers have the obvious values.  To denote a negative integer, use
-the unary operator @samp{-} discussed under expressions
-(@xref{Unops}.).
+Integers have the usual values.  To denote a negative integer, use
+the prefix operator @samp{-} discussed under expressions
+(@pxref{Prefix Ops}).
 
+@node Bignums,,,
 @subsubsection Bignums
 A @dfn{bignum} has the same syntax and semantics as an integer
 except that the number (or its negative) takes more than 32 bits to
 represent in binary.  The distinction is made because in some places
 integers are permitted while bignums are not.
 
+@node Flonums,,,
 @subsubsection Flonums
-A @dfn{flonum} represents a floating point number.  The translation
-is complex: a decimal floating point number from the text is
-converted by @code{as} to a generic binary floating point number of
-more than sufficient precision.  This generic floating point number
-is converted to the particular computer's floating point format(s)
-by a portion of @code{as} specialized to that computer.
+A @dfn{flonum} represents a floating point number.  The translation is
+complex: a decimal floating point number from the text is converted by
+@code{_AS__} to a generic binary floating point number of more than
+sufficient precision.  This generic floating point number is converted
+to a particular computer's floating point format (or formats) by a
+portion of @code{_AS__} specialized to that computer.
 
 A flonum is written by writing (in order)
 @itemize @bullet
 @item
 The digit @samp{0}.
 @item
-A letter, to tell @code{as} the rest of the number is a flonum.
-@kbd{e}
-is recommended.  Case is not important.
-(Any otherwise illegal letter will work here,
-but that might be changed.  Vax BSD 4.2 assembler
-seems to allow any of @samp{defghDEFGH}.)
+_if__(_AMD29K__)
+One of the letters @samp{DFPRSX} (in upper or lower case), to tell
+@code{_AS__} the rest of the number is a flonum.
+_fi__(_AMD29K__)
+_if__(_I960__)
+One of the letters @samp{DFT} (in upper or lower case), to tell
+@code{_AS__} the rest of the number is a flonum.
+_fi__(_I960__)
+_if__(!(_AMD29K__||_I960__))
+A letter, to tell @code{_AS__} the rest of the number is a flonum.  @kbd{e}
+is recommended.  Case is not important.  (Any otherwise illegal letter
+will work here, but that might be changed.  Vax BSD 4.2 assembler seems
+to allow any of @samp{defghDEFGH}.)
+_fi__(!(_AMD29K__||_I960__))
 @item
 An optional sign: either @samp{+} or @samp{-}.
 @item
-An optional integer part: zero or more decimal digits.
+An optional @dfn{integer part}: zero or more decimal digits.
 @item
-An optional fraction part: @samp{.} followed by zero
+An optional @dfn{fraction part}: @samp{.} followed by zero
 or more decimal digits.
 @item
 An optional exponent, consisting of:
 @itemize @bullet
 @item
-A letter; the exact significance varies according to
-the computer that executes the program.  @code{as}
-accepts any letter for now.  Case is not important.
+An @samp{E} or @samp{e}.
+@c I can't find a config where "EXP_CHARS" is other than 'eE', but in
+@c principle this can perfectly well be different on different targets.
 @item
 Optional sign: either @samp{+} or @samp{-}.
 @item
@@ -708,132 +903,185 @@ One or more decimal digits.
 @end itemize
 
 At least one of @var{integer part} or @var{fraction part} must be
-present.  The floating point number has the obvious value.
-
-The computer running @code{as} needs no floating point hardware.
-@code{as} does all processing using integers.
-
-@node Segments, Symbols, Syntax, top
-@chapter (Sub)Segments & Relocation
-Roughly, a @dfn{segment} is a range of addresses, with no gaps, with
-all data ``in'' those addresses being treated the same.  For example
-there may be a ``read only'' segment.
-
-The linker @code{ld} reads many object files (partial programs) and
-combines their contents to form a runnable program.  When @code{as}
-emits an object file, the partial program is assumed to start at
-address 0.  @code{ld} will assign the final addresses the partial
-program occupies, so that different partial programs don't overlap.
-That explanation is too simple, but it will suffice to explain how
-@code{as} works.
-
-@code{ld} moves blocks of bytes of your program to their run-time
+present.  The floating point number has the usual base-10 value.
+
+@code{_AS__} does all processing using integers.  Flonums are computed
+independently of any floating point hardware in the computer running
+@code{_AS__}.
+
+_if__(_I960__)
+@c Bit fields are written as a general facility but are also controlled
+@c by a conditional-compilation flag---which is as of now (21mar91)
+@c turned on only by the i960 config of GAS.
+@node Bit Fields,,,
+@subsubsection Bit Fields
+You can also define numeric constants as @dfn{bit fields}.
+specify two numbers separated by a colon---
+@example
+@var{mask}:@var{value}
+@end example
+@noindent
+the first will act as a mask; @code{_AS__} will bitwise-and it with the
+second value.
+
+The resulting number is then packed
+_if__(_ALL_ARCH__)
+(in host-dependent byte order)
+_fi__(_ALL_ARCH__)
+into a field whose width depends on which assembler directive has the
+bit-field as its argument.  Overflow (a result from the bitwise and
+requiring more binary digits to represent) is not an error; instead,
+more constants are generated, of the specified width, beginning with the
+least significant digits.@refill
+
+The directives @code{.byte}, @code{.hword}, @code{.int}, @code{.long},
+@code{.short}, and @code{.word} accept bit-field arguments.
+_fi__(_I960__)
+
+@node Segments, Symbols, Syntax, Top
+@chapter Segments and Relocation
+
+@node Segs Background, _LD__ Segments, Segments, Segments
+@section Background
+Roughly, a segment is a range of addresses, with no gaps; all data
+``in'' those addresses is treated the same for some particular purpose.
+For example there may be a ``read only'' segment.
+
+The linker @code{_LD__} reads many object files (partial programs) and
+combines their contents to form a runnable program.  When @code{_AS__}
+emits an object file, the partial program is assumed to start at address
+0.  @code{_LD__} will assign the final addresses the partial program
+occupies, so that different partial programs don't overlap.  This is
+actually an over-simplification, but it will suffice to explain how
+@code{_AS__} uses segments.
+
+@code{_LD__} moves blocks of bytes of your program to their run-time
 addresses.  These blocks slide to their run-time addresses as rigid
-units; their length does not change and neither does the order of
-bytes within them.  Such a rigid unit is called a @i{segment}.
-Assigning run-time addresses to segments is called
-@dfn{relocation}.  It includes the task of adjusting mentions of
-object-file addresses so they refer to the proper run-time addresses.
-
-An object file written by @code{as} has three segments, any of which
-may be empty.  These are named @i{text}, @i{data} and @i{bss}
-segments.  Within the object file, the text segment starts at
-address 0, the data segment follows, and the bss segment follows the
-data segment.
-
-To let @code{ld} know which data will change when the segments are
-relocated, and how to change that data, @code{as} also writes to the
+units; their length does not change and neither does the order of bytes
+within them.  Such a rigid unit is called a @emph{segment}.  Assigning
+run-time addresses to segments is called @dfn{relocation}.  It includes
+the task of adjusting mentions of object-file addresses so they refer to
+the proper run-time addresses.
+
+An object file written by @code{_AS__} has three segments, any of which may
+be empty.  These are named @dfn{text}, @dfn{data} and @dfn{bss}
+segments.  
+_if__(_COFF__)
+
+@c Thanks, Rich!
+@quotation
+@emph{Warning:} @code{_AS__} can only assign output to one of these
+three segments, even when configured for COFF output; the
+@code{.section} directive is not supported.
+@end quotation
+_fi__(_COFF__)
+
+Within the object file, the text segment starts at address @code{0}, the
+data segment follows, and the bss segment follows the data segment.
+
+To let @code{_LD__} know which data will change when the segments are
+relocated, and how to change that data, @code{_AS__} also writes to the
 object file details of the relocation needed.  To perform relocation
-@code{ld} must know for each mention of an address in the object
-file:
+@code{_LD__} must know, each time an address in the object
+file is mentioned:
 @itemize @bullet
 @item
-At what address in the object file does this mention of
-an address begin?
+Where in the object file is the beginning of this reference to
+an address?
 @item
-How long (in bytes) is this mention?
+How long (in bytes) is this reference?
 @item
-Which segment does the address refer to?
-What is the numeric value of (@var{address} @t{-}
-@var{start-address of segment})?
+Which segment does the address refer to?  What is the numeric value of
+@display
+(@var{address}) @minus{} (@var{start-address of segment})?
+@end display
 @item
-Is the mention of an address ``Program counter relative''?
+Is the reference to an address ``Program-Counter relative''?
 @end itemize
 
-In fact, every address @code{as} ever thinks about is expressed as
-(@var{segment} @t{+} @var{offset into segment}).  Further, every
-expression @code{as} computes is of this segmented nature.  So
-@dfn{absolute expression} means an expression with segment
-``absolute'' (@xref{LdSegs}.).  A @dfn{pass1 expression} means an
-expression with segment ``pass1'' (@xref{MythSegs}.).  In this
-document ``(segment, offset)'' will be written as @{ segment-name
-(offset into segment) @}.
+In fact, every address @code{_AS__} ever uses is expressed as
+@display
+(@var{segment}) + (@var{offset into segment})
+@end display
+@noindent
+Further, every expression @code{_AS__} computes is of this segmented
+nature.  @dfn{Absolute expression} means an expression with segment
+``absolute'' (@pxref{_LD__ Segments}).  A @dfn{pass1 expression} means
+an expression with segment ``pass1'' (@pxref{_AS__ Segments}).  In this
+manual we use the notation @{@var{segname} @var{N}@} to mean ``offset
+@var{N} into segment @var{segname}''.
 
 Apart from text, data and bss segments you need to know about the
-@dfn{absolute} segment.  When @code{ld} mixes partial programs,
-addresses in the absolute segment remain unchanged.  That is,
-address @{absolute 0@} is ``relocated'' to run-time address 0 by
-@code{ld}.  Although two partial programs' data segments will not
-overlap addresses after linking, @b{by definition} their absolute
-segments will overlap.  Address @{absolute 239@} in one partial
-program will always be the same address when the program is running
-as address @{absolute 239@} in any other partial program.
-
-The idea of segments is extended to the @dfn{undefined} segment.
-Any address whose segment is unknown at assembly time is by
-definition rendered @{undefined (something, unknown yet)@}.  Since
-numbers are always defined, the only way to generate an undefined
+@dfn{absolute} segment.  When @code{_LD__} mixes partial programs,
+addresses in the absolute segment remain unchanged.  That is, address
+@code{@{absolute 0@}} is ``relocated'' to run-time address 0 by @code{_LD__}.
+Although two partial programs' data segments will not overlap addresses
+after linking, @emph{by definition} their absolute segments will overlap.
+Address @code{@{absolute@ 239@}} in one partial program will always be the same
+address when the program is running as address @code{@{absolute@ 239@}} in any
+other partial program.
+
+The idea of segments is extended to the @dfn{undefined} segment.  Any
+address whose segment is unknown at assembly time is by definition
+rendered @{undefined @var{U}@}---where @var{U} will be filled in later.
+Since numbers are always defined, the only way to generate an undefined
 address is to mention an undefined symbol.  A reference to a named
 common block would be such a symbol: its value is unknown at assembly
-time so it has segment @i{undefined}.
+time so it has segment @emph{undefined}.
 
-By analogy the word @i{segment} is to describe groups of segments in
-the linked program.  @code{ld} puts all partial program's text
+By analogy the word @emph{segment} is used to describe groups of segments in
+the linked program.  @code{_LD__} puts all partial programs' text
 segments in contiguous addresses in the linked program.  It is
-customary to refer to the @i{text segment} of a program, meaning all
+customary to refer to the @emph{text segment} of a program, meaning all
 the addresses of all partial program's text segments.  Likewise for
 data and bss segments.
 
-@section Segments
-Some segments are manipulated by @code{ld}; others are invented for
-use of @code{as} and have no meaning except during assembly.
+Some segments are manipulated by @code{_LD__}; others are invented for
+use of @code{_AS__} and have no meaning except during assembly.
+
+@node _LD__ Segments, _AS__ Segments, Segs Background, Segments
+@section _LD__ Segments
+@code{_LD__} deals with just five kinds of segments, summarized below.
+
+@table @strong
 
-@node LdSegs, , ,
-@subsection ld segments
-@code{ld} deals with just 5 kinds of segments, summarized below.
-@table @b
 @item text segment
 @itemx data segment
-These segments hold your program bytes.  @code{as} and @code{ld}
-treat them as separate but equal segments.  Anything you can say of
-one segment is true of the other.  When the program is running
-however it is customary for the text segment to be unalterable:  it
-will contain instructions, constants and the like.  The data segment
-of a running program is usually alterable: for example, C variables
-would be stored in the data segment.
+These segments hold your program.  @code{_AS__} and @code{_LD__} treat them as
+separate but equal segments.  Anything you can say of one segment is
+true of the other.  When the program is running, however, it is
+customary for the text segment to be unalterable.  The
+text segment is often shared among processes: it will contain
+instructions, constants and the like.  The data segment of a running
+program is usually alterable: for example, C variables would be stored
+in the data segment.
+
 @item bss segment
-This segment contains zeroed bytes when your program begins
-running.  It is used to hold unitialized variables or common
-storage.  The length of each partial program's bss segment is
-important, but because it starts out containing zeroed bytes there
-is no need to store explicit zero bytes in the object file.  The Bss
-segment was invented to eliminate those explicit zeros from object
-files.
+This segment contains zeroed bytes when your program begins running.  It
+is used to hold unitialized variables or common storage.  The length of
+each partial program's bss segment is important, but because it starts
+out containing zeroed bytes there is no need to store explicit zero
+bytes in the object file.  The bss segment was invented to eliminate
+those explicit zeros from object files.
+
 @item absolute segment
-Address 0 of this segment is always ``relocated'' to runtime address
-0.  This is useful if you want to refer to an address that @code{ld}
-must not change when relocating.  In this sense we speak of absolute
-addresses being ``unrelocatable'': they don't change during
-relocation.
+Address 0 of this segment is always ``relocated'' to runtime address 0.
+This is useful if you want to refer to an address that @code{_LD__} must
+not change when relocating.  In this sense we speak of absolute
+addresses being ``unrelocatable'': they don't change during relocation.
+
 @item undefined segment
-This ``segment'' is a catch-all for address references to objects
-not in the preceding segments.  See the description of @file{a.out}
-for details.
+This ``segment'' is a catch-all for address references to objects not in
+the preceding segments.
+@c FIXME: ref to some other doc on obj-file formats could go here.
+
 @end table
-An idealized example of the 3 relocatable segments follows.  Memory
+
+An idealized example of the three relocatable segments follows.  Memory
 addresses are on the horizontal axis.
 
-@example
+@ifinfo
+@smallexample
                       +-----+----+--+
 partial program # 1:  |ttttt|dddd|00|
                       +-----+----+--+
@@ -850,83 +1098,131 @@ linked program:       |  |TTT|ttttt|  |dddd|DDD|00000|
                       +--+---+-----+--+----+---+-----+~~
 
     addresses:        0 @dots{}
-@end example
+@end smallexample
+@end ifinfo
+@tex
+
+{\it Partial program \#1: }
+
+\line{\ibox{2.5cm}{\tt text}\ibox{2cm}{\tt data}\ibox{1cm}{\tt bss}\hfil}
+\line{\boxit{2.5cm}{\tt ttttt}\boxit{2cm}{\tt dddd}\boxit{1cm}{\tt 00}\hfil}
+
+{\it Partial program \#2:}
+
+\line{\ibox{1cm}{\tt text}\ibox{1.5cm}{\tt data}\ibox{1cm}{\tt bss}\hfil}
+\line{\boxit{1cm}{\tt TTT}\boxit{1.5cm}{\tt DDDD}\boxit{1cm}{\tt 000}\hfil}
+
+{\it linked program: }
+
+\line{\ibox{.5cm}{}\ibox{1cm}{\tt text}\ibox{2.5cm}{}\ibox{.75cm}{}\ibox{2cm}{\tt data}\ibox{1.5cm}{}\ibox{2cm}{\tt bss}\hfil}
+\line{\boxit{.5cm}{}\boxit{1cm}{\tt TTT}\boxit{2.5cm}{\tt
+ttttt}\boxit{.75cm}{}\boxit{2cm}{\tt dddd}\boxit{1.5cm}{\tt
+DDDD}\boxit{2cm}{\tt 00000}\ \dots\hfil}
+
+{\it addresses:}
+
+\line{0\dots\hfil}
 
-@node MythSegs, , ,
-@subsection Mythical Segments
-These segments are invented for the internal use of @code{as}.  They
+@end tex
+
+@node _AS__ Segments, Sub-Segments, _LD__ Segments, Segments
+@section _AS__ Internal Segments
+These segments are invented for the internal use of @code{_AS__}.  They
 have no meaning at run-time.  You don't need to know about these
-segments except that they might be mentioned in @code{as}' warning
+segments except that they might be mentioned in the @code{_AS__} warning
 messages.  These segments are invented to permit the value of every
 expression in your assembly language program to be a segmented
 address.
 
 @table @b
 @item absent segment
-An expression was expected and none was found.
+An expression was expected and none was
+found.
+
 @item goof segment
-An internal assembler logic error has been found.  This means there
-is a bug in the assembler.
+An internal assembler logic error has been
+found.  This means there is a bug in the assembler.
+
 @item grand segment
-A @dfn{grand number} is a bignum or a flonum, but not an integer.
-If a number can't be written as a C @code{int} constant, it is a
-grand number.  @code{as} has to remember that a flonum or a bignum
-does not fit into 32 bits, and cannot be a primary (@xref{Primary}.)
-in an expression: this is done by making a flonum or bignum be of
-type ``grand''.  This is purely for internal @code{as} convenience;
-grand segment behaves similarly to absolute segment.
+A @dfn{grand number} is a bignum or a flonum, but not an integer.  If a
+number can't be written as a C @code{int} constant, it is a grand
+number.  @code{_AS__} has to remember that a flonum or a bignum does not
+fit into 32 bits, and cannot be an argument (@pxref{Arguments}) in an
+expression: this is done by making a flonum or bignum be in segment
+grand.  This is purely for internal @code{_AS__} convenience; grand
+segment behaves similarly to absolute segment.
+
 @item pass1 segment
 The expression was impossible to evaluate in the first pass.  The
-assembler will attempt a second pass (second reading of the source)
-to evaluate the expression.  Your expression mentioned an undefined
-symbol in a way that defies the one-pass (segment + offset in
-segment) assembly process.  No compiler need emit such an expression.
+assembler will attempt a second pass (second reading of the source) to
+evaluate the expression.  Your expression mentioned an undefined symbol
+in a way that defies the one-pass (segment + offset in segment) assembly
+process.  No compiler need emit such an expression.
+
+@quotation
+@emph{Warning:} the second pass is currently not implemented.  @code{_AS__}
+will abort with an error message if one is required.
+@end quotation
+
 @item difference segment
 As an assist to the C compiler, expressions of the forms
-@itemize @bullet
-@item
-(undefined symbol) @t{-} (expression)
-@item
-(something) @t{-} (undefined symbol)
-@item
-(undefined symbol) @t{-} (undefined symbol)
-@end itemize
-are permitted to belong to the ``difference'' segment.  @code{as}
-re-evaluates such expressions after the source file has been read
-and the symbol table built.  If by that time there are no undefined
-symbols in the expression then the expression assumes a new segment.
-The intention is to permit statements like @samp{.word label -
-base_of_table} to be assembled in one pass where both @code{label}
-and @code{base_of_table} are undefined.  This is useful for
-compiling C and Algol switch statements, Pascal case statements,
-FORTRAN computed goto statements and the like.
+@display
+   (@var{undefined symbol}) @minus{} (@var{expression})
+   @var{something} @minus{} (@var{undefined symbol})
+   (@var{undefined symbol}) @minus{} (@var{undefined symbol})
+@end display
+are permitted, and belong to the difference segment.  @code{_AS__}
+re-evaluates such expressions after the source file has been read and
+the symbol table built.  If by that time there are no undefined symbols
+in the expression then the expression assumes a new segment.  The
+intention is to permit statements like
+@samp{.word label - base_of_table}
+to be assembled in one pass where both @code{label} and
+@code{base_of_table} are undefined.  This is useful for compiling C and
+Algol switch statements, Pascal case statements, FORTRAN computed goto
+statements and the like.
 @end table
 
+@node Sub-Segments, bss, _AS__ Segments, Segments
 @section Sub-Segments
-Assembled bytes fall into two segments: text and data.  Because you
-may have groups of text or data that you want to end up near to each
-other in the object file, @code{as}, allows you to use
+Assembled bytes fall into two segments: text and data.
+Because you may have groups of text or data that you want to end up near
+to each other in the object file, @code{_AS__} allows you to use
 @dfn{subsegments}.  Within each segment, there can be numbered
-subsegments with values from 0 to 8192.  Objects assembled into the
-same subsegment will be grouped with other objects in the same
-subsegment when they are all put into the object file.  For example,
-a compiler might want to store constants in the text segment, but
-might not want to have them intersperced with the program being
-assembled.  In this case, the compiler could issue a @code{text 0}
-before each section of code being output, and a @code{text 1} before
-each group of constants being output.
-
-Subsegments are optional.  If you don't used subsegments, everything
+subsegments with values from 0 to 8192.  Objects assembled into the same
+subsegment will be grouped with other objects in the same subsegment
+when they are all put into the object file.  For example, a compiler
+might want to store constants in the text segment, but might not want to
+have them interspersed with the program being assembled.  In this case,
+the compiler could issue a @code{text 0} before each section of code
+being output, and a @code{text 1} before each group of constants being
+output.
+
+Subsegments are optional.  If you don't use subsegments, everything
 will be stored in subsegment number zero.
 
+_if__(!(_AMD29K__||_I960__))
 Each subsegment is zero-padded up to a multiple of four bytes.
 (Subsegments may be padded a different amount on different flavors
-of @code{as}.)  Subsegments appear in your object file in numeric
-order, lowest numbered to highest.  (All this to be compatible with
-other people's assemblers.)  The object file, @code{ld} @i{etc.}
-have no concept of subsegments.  They just see all your text
-subsegments as a text segment, and all your data subsegments as a
-data segment.
+of @code{_AS__}.)
+_fi__(!(_AMD29K__||_I960__))
+_if__(_I960__)
+@c Rich Pixley says padding here depends on target obj code format; that
+@c doesn't seem particularly useful to say without further elaboration,
+@c so for now I say nothing about it.  If this is a generic BFD issue,
+@c these paragraphs might need to vanish from this manual, and be
+@c discussed in BFD chapter of binutils (or some such).
+_fi__(_I960__)
+_if__(_AMD29K__)
+On the AMD 29K family, no particular padding is added to segment sizes;
+_AS__ forces no alignment on this platform.
+_fi__(_AMD29K__)
+Subsegments appear in your object file in numeric order, lowest numbered
+to highest.  (All this to be compatible with other people's assemblers.)
+The object file contains no representation of subsegments; @code{_LD__} and
+other programs that manipulate object files will see no trace of them.
+They just see all your text subsegments as a text segment, and all your
+data subsegments as a data segment.
 
 To specify which subsegment you want subsequent statements assembled
 into, use a @samp{.text @var{expression}} or a @samp{.data
@@ -935,7 +1231,7 @@ expression.  (@xref{Expressions}.)  If you just say @samp{.text}
 then @samp{.text 0} is assumed.  Likewise @samp{.data} means
 @samp{.data 0}.  Assembly begins in @code{text 0}.
 For instance:
-@example
+@smallexample
 .text 0     # The default subsegment is text 0 anyway.
 .ascii "This lives in the first text subsegment. *"
 .text 1
@@ -946,274 +1242,319 @@ For instance:
 .text 0
 .ascii "This lives in the first text segment,"
 .ascii "immediately following the asterisk (*)."
-@end example
-
-Each segment has a @dfn{location counter} incremented by one for
-every byte assembled into that segment.  Because subsegments are
-merely a convenience restricted to @code{as} there is no concept of
-a subsegment location counter.  There is no way to directly
-manipulate a location counter.  The location counter of the segment
-that statements are being assembled into is said to be the
+@end smallexample
+
+Each segment has a @dfn{location counter} incremented by one for every
+byte assembled into that segment.  Because subsegments are merely a
+convenience restricted to @code{_AS__} there is no concept of a subsegment
+location counter.  There is no way to directly manipulate a location
+counter---but the @code{.align} directive will change it, and any label
+definition will capture its current value.  The location counter of the
+segment that statements are being assembled into is said to be the
 @dfn{active} location counter.
 
-@section Bss Segment
-The @code{bss} segment is used for local common variable storage.
-You may allocate address space in the @code{bss} segment, but you may
+@node bss,  , Sub-Segments, Segments
+@section bss Segment
+The bss segment is used for local common variable storage.
+You may allocate address space in the bss segment, but you may
 not dictate data to load into it before your program executes.  When
-your program starts running, all the contents of the @code{bss}
+your program starts running, all the contents of the bss
 segment are zeroed bytes.
 
-Addresses in the bss segment are allocated with a special statement;
+Addresses in the bss segment are allocated with special directives;
 you may not assemble anything directly into the bss segment.  Hence
-there are no bss subsegments.
+there are no bss subsegments. @xref{Comm}; @pxref{Lcomm}.
 
-@node Symbols, Expressions, Segments, top
+@node Symbols, Expressions, Segments, Top
 @chapter Symbols
-Because the linker uses symbols to link, the debugger uses symbols
-to debug and the programmer uses symbols to name things, symbols are
-a central concept.  Symbols do not appear in the object file in the
-order they are declared.  This may break some debuggers.
+Symbols are a central concept: the programmer uses symbols to name
+things, the linker uses symbols to link, and the debugger uses symbols
+to debug.
 
-@node Labels, , , Symbols
+@quotation
+@emph{Warning:} @code{_AS__} does not place symbols in the object file in
+the same order they were declared.  This may break some debuggers.
+@end quotation
+
+@node Labels, Setting Symbols, Symbols, Symbols
 @section Labels
 A @dfn{label} is written as a symbol immediately followed by a colon
-(@samp{:}).  The symbol then represents the current value of the
+@samp{:}.  The symbol then represents the current value of the
 active location counter, and is, for example, a suitable instruction
 operand.  You are warned if you use the same symbol to represent two
 different locations: the first definition overrides any other
 definitions.
 
+@node Setting Symbols, Symbol Names, Labels, Symbols
 @section Giving Symbols Other Values
-A symbol can be given an arbitrary value by writing a symbol followed
-by an equals sign (@samp{=}) followed by an expression
+A symbol can be given an arbitrary value by writing a symbol, followed
+by an equals sign @samp{=}, followed by an expression
 (@pxref{Expressions}).  This is equivalent to using the @code{.set}
-directive.  (@xref{Set}.)
+directive.  @xref{Set}.
 
+@node Symbol Names, Dot, Setting Symbols, Symbols
 @section Symbol Names
 Symbol names begin with a letter or with one of @samp{$._}.  That
 character may be followed by any string of digits, letters,
 underscores and dollar signs.  Case of letters is significant:
 @code{foo} is a different symbol name than @code{Foo}.
 
-Each symbol has exactly one name. Each name in an assembly program
-refers to exactly one symbol. You may use that symbol name any
-number of times in an assembly program.
+_if__(_AMD29K__)
+For the AMD 29K family, @samp{?} is also allowed in the
+body of a symbol name, though not at its beginning.
+_fi__(_AMD29K__)
+
+Each symbol has exactly one name. Each name in an assembly language
+program refers to exactly one symbol. You may use that symbol name any
+number of times in a program.
 
+@node Local Symbols,  , Symbol Names, Symbol Names
 @subsection Local Symbol Names
 
 Local symbols help compilers and programmers use names temporarily.
-There are ten @dfn{local} symbol names, which are re-used throughout
-the program.  Their names are @samp{0} @samp{1} @dots{} @samp{9}.
-To define a local symbol, write a label of the form
-@var{digit}@t{:}.  To refer to the most recent previous definition
-of that symbol write @var{digit}@t{b}, using the same digit as when
-you defined the label.  To refer to the next definition of a local
-label, write @var{digit}@t{f} where @var{digit} gives you a choice
-of 10 forward references.  The @samp{b} stands for ``backwards'' and
-the @samp{f} stands for ``forwards''.
-
-Local symbols are not used by the current C compiler.
+There are ten local symbol names, which are re-used throughout the
+program.  You may refer to them using the names @samp{0} @samp{1}
+@dots{} @samp{9}.  To define a local symbol, write a label of the form
+@samp{@b{N}:} (where @b{N} represents any digit).  To refer to the most
+recent previous definition of that symbol write @samp{@b{N}b}, using the
+same digit as when you defined the label.  To refer to the next
+definition of a local label, write @samp{@b{N}f}---where @b{N} gives you
+a choice of 10 forward references.  The @samp{b} stands for
+``backwards'' and the @samp{f} stands for ``forwards''.
+
+Local symbols are not emitted by the current GNU C compiler.
 
 There is no restriction on how you can use these labels, but
 remember that at any point in the assembly you can refer to at most
 10 prior local labels and to at most 10 forward local labels.
 
-Local symbol names are only a notation device. They are immediately
+Local symbol names are only a notation device.  They are immediately
 transformed into more conventional symbol names before the assembler
-thinks about them.  The symbol names stored in the symbol table,
-appearing in error messages and optionally emitted to the object
-file have these parts:
-@table @kbd
+uses them.  The symbol names stored in the symbol table, appearing in
+error messages and optionally emitted to the object file have these
+parts:
+
+@table @code
 @item L
-All local labels begin with @samp{L}. Normally both @code{as} and
-@code{ld} forget symbols that start with @samp{L}. These labels are
+All local labels begin with @samp{L}. Normally both @code{_AS__} and
+@code{_LD__} forget symbols that start with @samp{L}. These labels are
 used for symbols you are never intended to see.  If you give the
-@samp{-L} option then @code{as} will retain these symbols in the
-object file. By instructing @code{ld} to also retain these symbols,
+@samp{-L} option then @code{_AS__} will retain these symbols in the
+object file. If you also instruct @code{_LD__} to retain these symbols,
 you may use them in debugging.
-@item @i{a digit}
+
+@item @var{digit}
 If the label is written @samp{0:} then the digit is @samp{0}.
 If the label is written @samp{1:} then the digit is @samp{1}.
 And so on up through @samp{9:}.
-@item @i{control}-A
+
+@item @ctrl{A}
 This unusual character is included so you don't accidentally invent
 a symbol of the same name.  The character has ASCII value
 @samp{\001}.
-@item @i{an ordinal number}
-This is like a serial number to keep the labels distinct.  The first
+
+@item @emph{ordinal number}
+This is a serial number to keep the labels distinct.  The first
 @samp{0:} gets the number @samp{1}; The 15th @samp{0:} gets the
-number @samp{15}; @i{etc.}.  Likewise for the other labels @samp{1:}
+number @samp{15}; @emph{etc.}.  Likewise for the other labels @samp{1:}
 through @samp{9:}.
 @end table
-For instance, the
-first @code{1:} is named @code{L1^A1}, the 44th @code{3:} is named @code{L3^A44}.
 
+For instance, the first @code{1:} is named @code{L1@ctrl{A}1}, the 44th
+@code{3:} is named @code{L3@ctrl{A}44}.
+
+@node Dot, Symbol Attributes, Symbol Names, Symbols
 @section The Special Dot Symbol
 
-The special symbol @code{.} refers to the current address that
-@code{as} is assembling into.  Thus, the expression @samp{melvin:
-.long .} will cause @var{melvin} to contain its own address.
+The special symbol @samp{.} refers to the current address that
+@code{_AS__} is assembling into.  Thus, the expression @samp{melvin:
+.long .} will cause @code{melvin} to contain its own address.
 Assigning a value to @code{.} is treated the same as a @code{.org}
 directive.  Thus, the expression @samp{.=.+4} is the same as saying
+_if__(!_AMD29K__)
 @samp{.space 4}.
+_fi__(!_AMD29K__)
+_if__(_AMD29K__)
+@samp{.block 4}.
+_fi__(_AMD29K__)
 
+@node Symbol Attributes,  , Dot, Symbols
 @section Symbol Attributes
-Every symbol has the attributes discussed below.  The detailed
-definitions are in <a.out.h>.
+Every symbol has, as well as its name, the attributes ``Value'' and
+``Type''.  Depending on output format, symbols also have auxiliary attributes.
+_if__(_INTERNALS__)
+The detailed definitions are in _0__<a.out.h>_1__.
+_fi__(_INTERNALS__)
 
-If you use a symbol without defining it, @code{as} assumes zero for
+If you use a symbol without defining it, @code{_AS__} assumes zero for
 all these attributes, and probably won't warn you.  This makes the
 symbol an externally defined symbol, which is generally what you
 would want.
 
+@node Symbol Value, Symbol Type, Symbol Attributes, Symbol Attributes
 @subsection Value
-The value of a symbol is (usually) 32 bits, the size of one C
-@code{int}.  For a symbol which labels a location in the
-@code{text}, @code{data}, @code{bss} or @code{Absolute} segments the
-value is the number of addresses from the start of that segment to
-the label.  Naturally for @code{text} @code{data} and @code{bss}
-segments the value of a symbol changes as @code{ld} changes segment
-base addresses during linking.  @code{absolute} symbols' values do
-not change during linking: that is why they are called absolute.
-
-The value of an undefined symbol is treated in a special way.  If it
-is 0 then the symbol is not defined in this assembler source
-program, and @code{ld} will try to determine its value from other
-programs it is linked with.  You make this kind of symbol simply by
-mentioning a symbol name without defining it.  A non-zero value
-represents a @code{.comm} common declaration.  The value is how much
-common storage to reserve, in bytes (@i{i.e.} addresses).  The
-symbol refers to the first address of the allocated storage.
-
+The value of a symbol is (usually) 32 bits, the size of one GNU C
+@code{int}.  For a symbol which labels a location in the text, data, bss
+or absolute segments the value is the number of addresses from the start
+of that segment to the label.  Naturally for text, data and bss segments
+the value of a symbol changes as @code{_LD__} changes segment base
+addresses during linking.  Absolute symbols' values do not change during
+linking: that is why they are called absolute.
+
+The value of an undefined symbol is treated in a special way.  If it is
+0 then the symbol is not defined in this assembler source program, and
+@code{_LD__} will try to determine its value from other programs it is
+linked with.  You make this kind of symbol simply by mentioning a symbol
+name without defining it.  A non-zero value represents a @code{.comm}
+common declaration.  The value is how much common storage to reserve, in
+bytes (addresses).  The symbol refers to the first address of the
+allocated storage.
+
+@node Symbol Type, Symbol Desc, Symbol Value, Symbol Attributes
 @subsection Type
-The type attribute of a symbol is 8 bits encoded in a devious way.
-We kept this coding standard for compatibility with older operating
-systems.
-
-@example
-
-        7     6     5     4     3     2     1     0     bit numbers
-     +-----+-----+-----+-----+-----+-----+-----+-----+
-     |                 |                       |     |
-     |   N_STAB bits   |      N_TYPE bits      |N_EXT|
-     |                 |                       | bit |
-     +-----+-----+-----+-----+-----+-----+-----+-----+
-
-                     n_type byte
-@end example
-
-@subsubsection N_EXT bit
-This bit is set if @code{ld} might need to use the symbol's value
-and type bits.  If this bit is re-set then @code{ld} can ignore the
-symbol while linking.  It is set in two cases.  If the symbol is
-undefined, then @code{ld} is expected to find the symbol's value
-elsewhere in another program module.  Otherwise the symbol has the
-value given, but this symbol name and value are revealed to any other
-programs linked in the same executable program.  This second use of
-the @code{N_EXT} bit is most often done by a @code{.globl} statement.
-
-@subsubsection N_TYPE bits
-These establish the symbol's ``type'', which is mainly a relocation
-concept.  Common values are detailed in the manual describing the
-executable file format.
-
-@subsubsection N_STAB bits
-Common values for these bits are described in the manual on the
-executable file format.
-
-@subsection Desc(riptor)
+The type attribute of a symbol contains relocation (segment)
+information, any flag settings indicating that a symbol is external, and
+(optionally), other information for linkers and debuggers.  The exact
+format depends on the object-code output format in use.
+
+_if__(_AOUT__||_BOUT__)
+@node a.out Symbols,,,
+@subsection Symbol Attributes: @code{a.out}, @code{b.out}
+These symbol attributes appear only when @code{_AS__} is configured for
+one of the Berkeley-descended object output formats.
+
+@node Symbol Desc, Symbol Other, Symbol Type, Symbol Attributes
+@subsubsection Descriptor
 This is an arbitrary 16-bit value.  You may establish a symbol's
-descriptor value by using a @code{.desc} statement (@xref{Desc}.).
-A descriptor value means nothing to @code{as}.
-
-@subsection Other
-This is an arbitrary 8-bit value.  It means nothing to @code{as}.
-
-@node Expressions, PseudoOps, Symbols, top
+descriptor value by using a @code{.desc} statement (@pxref{Desc}).
+A descriptor value means nothing to @code{_AS__}.
+
+@node Symbol Other,  , Symbol Desc, Symbol Attributes
+@subsubsection Other
+This is an arbitrary 8-bit value.  It means nothing to @code{_AS__}.
+_fi__(_AOUT__||_BOUT__)
+
+_if__(_COFF__)
+@node COFF Symbols,,,
+@subsection Symbol Attributes for COFF
+The COFF format supports a multitude of auxiliary symbol attributes;
+like the primary symbol attributes, they are set between @code{.def} and
+@code{.endef} directives.  
+
+@subsubsection Primary Attributes
+The symbol name is set with @code{.def}; the value and type,
+respectively, with @code{.val} and @code{.type}.
+
+@subsubsection Auxiliary Attributes
+The @code{_AS__} directives @code{.dim}, @code{.line}, @code{.scl},
+@code{.size}, and @code{.tag} can generate auxiliary symbol table
+information for COFF.
+_fi__(_COFF__)
+
+@node Expressions, Pseudo Ops, Symbols, Top
 @chapter Expressions
 An @dfn{expression} specifies an address or numeric value.
 Whitespace may precede and/or follow an expression.
 
+@node Empty Exprs, Integer Exprs, Expressions, Expressions
 @section Empty Expressions
-An empty expression has no operands: it is just whitespace or null.
+An empty expression has no value: it is just whitespace or null.
 Wherever an absolute expression is required, you may omit the
-expression and @code{as} will assume a value of (absolute) 0.  This
+expression and @code{_AS__} will assume a value of (absolute) 0.  This
 is compatible with other assemblers.
 
+@node Integer Exprs,  , Empty Exprs, Expressions
 @section Integer Expressions
-An @dfn{integer expression} is one or more @i{primaries} delimited
-by @i{operators}.
-
-@node Primary, Unops, , Expressions
-@subsection Primaries
-@dfn{Primaries} are symbols, numbers or subexpressions.  Other
-languages might call primaries ``arithmetic operands'' but we don't
-want them confused with ``instruction operands'' of the machine
-language so we give them a different name.
-
-Symbols are evaluated to yield @{@var{segment} @var{value}@} where
-@var{segment} is one of @b{text}, @b{data}, @b{bss}, @b{absolute},
-or @b{undefined}.  @var{value} is a signed 2's complement 32 bit
+An @dfn{integer expression} is one or more @emph{arguments} delimited
+by @emph{operators}.
+
+@node Arguments, Operators, Integer Exprs, Integer Exprs
+@subsection Arguments
+
+@dfn{Arguments} are symbols, numbers or subexpressions.  In other
+contexts arguments are sometimes called ``arithmetic operands''.  In
+this manual, to avoid confusing them with the ``instruction operands'' of
+the machine language, we use the term ``argument'' to refer to parts of
+expressions only, reserving the word ``operand'' to refer only to machine
+instruction operands.
+
+Symbols are evaluated to yield @{@var{segment} @var{NNN}@} where
+@var{segment} is one of text, data, bss, absolute,
+or undefined.  @var{NNN} is a signed, 2's complement 32 bit
 integer.
 
 Numbers are usually integers.
 
 A number can be a flonum or bignum.  In this case, you are warned
-that only the low order 32 bits are used, and @code{as} pretends
+that only the low order 32 bits are used, and @code{_AS__} pretends
 these 32 bits are an integer.  You may write integer-manipulating
 instructions that act on exotic constants, compatible with other
 assemblers.
 
-Subexpressions are a left parenthesis (@t{(}) followed by an integer
-expression followed by a right parenthesis (@t{)}), or a unary
-operator followed by an primary.
+Subexpressions are a left parenthesis @samp{(} followed by an integer
+expression, followed by a right parenthesis @samp{)}; or a prefix
+operator followed by an argument.
 
+@node Operators, Prefix Ops, Arguments, Integer Exprs
 @subsection Operators
-@dfn{Operators} are arithmetic marks, like @t{+} or @t{%}.  Unary
-operators are followed by an primary.  Binary operators appear
-between primaries.  Operators may be preceded and/or followed by
+@dfn{Operators} are arithmetic functions, like @code{+} or @code{%}.  Prefix
+operators are followed by an argument.  Infix operators appear
+between their arguments.  Operators may be preceded and/or followed by
 whitespace.
 
-@subsection Unary Operators
-@node Unops, , Primary, Expressions
-@code{as} has the following @dfn{unary operators}.  They each take
-one primary, which must be absolute.
-@table @t
+@node Prefix Ops, Infix Ops, Operators, Integer Exprs
+@subsection Prefix Operators
+@code{_AS__} has the following @dfn{prefix operators}.  They each take
+one argument, which must be absolute.
+
+@c the tex/end tex stuff surrounding this small table is meant to make
+@c it align, on the printed page, with the similar table in the next
+@c section (which is inside an enumerate).
+@tex
+\global\advance\leftskip by \itemindent
+@end tex
+
+@table @code
 @item -
-Hyphen.  @dfn{Negation}.  Two's complement negation.
+@dfn{Negation}.  Two's complement negation.
 @item ~
-Tilde.  @dfn{Complementation}.  Bitwise not.
+@dfn{Complementation}.  Bitwise not.
 @end table
 
-@subsection Binary Operators
-@dfn{Binary operators} are infix.  Operators are prioritized, but
-equal priority operators are performed left to right.  Apart from
-@samp{+} or @samp{-}, both primaries must be absolute, and the
-result is absolute, else one primary can be either undefined or
-pass1 and the result is pass1.
+@tex
+\global\advance\leftskip by -\itemindent
+@end tex
+
+@node Infix Ops,  , Prefix Ops, Integer Exprs
+@subsection Infix Operators
+
+@dfn{Infix operators} take two arguments, one on either side.  Operators
+have precedence, but operations with equal precedence are performed left
+to right.  Apart from @code{+} or @code{-}, both arguments must be
+absolute, and the result is absolute.
+
 @enumerate
+
 @item
-Highest Priority
+Highest Precedence
 @table @code
 @item *
 @dfn{Multiplication}.
 @item /
 @dfn{Division}.  Truncation is the same as the C operator @samp{/}
-of the compiler that compiled @code{as}.
 @item %
 @dfn{Remainder}.
-@item <
-@itemx <<
-@dfn{Shift Left}.  Same as the C operator @samp{<<} of
-the compiler that compiled @code{as}.
-@item >
-@itemx >>
-@dfn{Shift Right}.  Same as the C operator @samp{>>} of
-the compiler that compiled @code{as}.
+@item _0__<_1__
+@itemx _0__<<_1__
+@dfn{Shift Left}.  Same as the C operator @samp{_0__<<_1__}
+@item _0__>_1__
+@itemx _0__>>_1__
+@dfn{Shift Right}.  Same as the C operator @samp{_0__>>_1__}
 @end table
+
 @item
-Intermediate priority
-@table @t
+Intermediate precedence
+@table @code
 @item |
 @dfn{Bitwise Inclusive Or}.
 @item &
@@ -1223,145 +1564,241 @@ Intermediate priority
 @item !
 @dfn{Bitwise Or Not}.
 @end table
+
 @item
-Lowest Priority
-@table @t
+Lowest Precedence
+@table @code
 @item +
-@dfn{Addition}.  If either primary is absolute, the result
-has the segment of the other primary.
-If either primary is pass1 or undefined, result is pass1.
-Otherwise @t{+} is illegal.
+@dfn{Addition}.  If either argument is absolute, the result
+has the segment of the other argument.
+If either argument is pass1 or undefined, the result is pass1.
+Otherwise @code{+} is illegal.
 @item -
-@dfn{Subtraction}.  If the right primary is absolute, the
-result has the segment of the left primary.
-If either primary is pass1 the result is pass1.
-If either primary is undefined the result is difference segment.
-If both primaries are in the same segment, the result is absolute; provided
+@dfn{Subtraction}.  If the right argument is absolute, the
+result has the segment of the left argument.
+If either argument is pass1 the result is pass1.
+If either argument is undefined the result is difference segment.
+If both arguments are in the same segment, the result is absolute---provided
 that segment is one of text, data or bss.
-Otherwise @t{-} is illegal.
+Otherwise subtraction is illegal.
 @end table
 @end enumerate
 
-The sense of the rules is that you can't add or subtract quantities
-from two different segments.  If both primaries are in one of these
-segments, they must be in the same segment:  @b{text}, @b{data} or
-@b{bss}, and the operator must be @samp{-}.
+The sense of the rule for addition is that it's only meaningful to add
+the @emph{offsets} in an address; you can only have a defined segment in
+one of the two arguments.
 
-@node PseudoOps, MachineDependent, Expressions, top
+Similarly, you can't subtract quantities from two different segments.
+
+@node Pseudo Ops, _MACH_DEP__, Expressions, Top
 @chapter Assembler Directives
-@menu
-* Abort::      The Abort directive causes as to abort
-* Align::      Pad the location counter to a power of 2
-* Ascii::      Fill memory with bytes of ASCII characters
-* Asciz::      Fill memory with bytes of ASCII characters followed
-                by a null.
-* Byte::       Fill memory with 8-bit integers
-* Comm::       Reserve public space in the BSS segment
-* Data::       Change to the data segment
-* Desc::       Set the n_desc of a symbol
-* Double::     Fill memory with double-precision floating-point numbers
-* File::       Set the logical file name
-* Fill::       Fill memory with repeated values
-* Float::      Fill memory with single-precision floating-point numbers
-* Global::     Make a symbol visible to the linker
-* Int::                Fill memory with 32-bit integers
-* Lcomm::      Reserve private space in the BSS segment
-* Line::       Set the logical line number
-* Long::       Fill memory with 32-bit integers
-* Lsym::       Create a local symbol
-* Octa::       Fill memory with 128-bit integers
-* Org::                Change the location counter
-* Quad::       Fill memory with 64-bit integers
-* Set::                Set the value of a symbol
-* Short::      Fill memory with 16-bit integers
-* Space::      Fill memory with a repeated value
-* Stab::       Store debugging information
-* Text::       Change to the text segment
-* Word::       Fill memory with 16-bit integers
-@end menu
-
-All assembler directives begin with a symbol that begins with a
-period (@samp{.}).  The rest of the symbol is letters: their case
-does not matter.
-
-@node Abort, Align, PseudoOps, PseudoOps
-@section .abort
+
+All assembler directives have names that begin with a period (@samp{.}).
+The rest of the name is letters: their case does not matter.
+
+This chapter discusses directives present regardless of the target
+machine configuration for the GNU assembler; @pxref{_MACH_DEP__} for
+additional directives.
+
+@node Abort,,,
+@section @code{.abort}
 This directive stops the assembly immediately.  It is for
 compatibility with other assemblers.  The original idea was that the
-assembler program would be piped into the assembler.  If the source
-of program wanted to quit, then this directive tells @code{as} to
+assembly language source would be piped into the assembler.  If the sender
+of the source quit, it could use this directive tells @code{_AS__} to
 quit also.  One day @code{.abort} will not be supported.
 
-@node Align, Ascii, Abort, PseudoOps
-@section .align @var{absolute-expression} , @var{absolute-expression}
-Pad the location counter (in the current subsegment) to a word,
-longword or whatever boundary.  The first expression is the number
-of low-order zero bits the location counter will have after
+_if__(_COFF__)
+@node coff-ABORT,,,
+@section @code{.ABORT}
+When producing COFF output, @code{_AS__} accepts this directive as a
+synonym for @samp{.abort}.
+_fi__(_COFF__)
+_if__(_BOUT__)
+_if__(!_COFF__)
+@node bout-ABORT,,,
+@section @code{.ABORT}
+_fi__(!_COFF__)
+
+When producing @code{b.out} output, @code{_AS__} accepts this directive,
+but ignores it.
+_fi__(_BOUT__)
+
+@node Align,,,
+@section @code{.align @var{abs-expr} , @var{abs-expr}}
+Pad the location counter (in the current subsegment) to a particular
+storage boundary.  The first expression (which must be absolute) is the
+number of low-order zero bits the location counter will have after
 advancement.  For example @samp{.align 3} will advance the location
-counter until it a multiple of 8.  If the location counter is
-already a multiple of 8, no change is needed.
-
-The second expression gives the value to be stored in the padding
-bytes.  It (and the comma) may be omitted.  If it is omitted, the
-padding bytes are zeroed.
-
-@node Ascii, Asciz, Align, PseudoOps
-@section .ascii @var{strings}
-This expects zero or more string literals (@xref{Strings}.)
+counter until it a multiple of 8.  If the location counter is already a
+multiple of 8, no change is needed.
+
+The second expression (also absolute) gives the value to be stored in
+the padding bytes.  It (and the comma) may be omitted.  If it is
+omitted, the padding bytes are zero.
+
+@node App-File,,,
+@section @code{.app-file @var{string}}
+@code{.app-file}
+_if__(!_AMD29K__)
+(which may also be spelled @samp{.file})
+_fi__(!_AMD29K__)
+tells @code{_AS__} that we are about to start a new
+logical file.  @var{string} is the new file name.  In general, the
+filename is recognized whether or not it is surrounded by quotes @samp{"};
+but if you wish to specify an empty file name is permitted,
+you must give the quotes--@code{""}.  This statement may go away in
+future: it is only recognized to be compatible with old @code{_AS__}
+programs.@refill
+
+@node Ascii,,,
+@section @code{.ascii "@var{string}"}@dots{}
+@code{.ascii} expects zero or more string literals (@pxref{Strings})
 separated by commas.  It assembles each string (with no automatic
 trailing zero byte) into consecutive addresses.
 
-@node Asciz, Byte, Ascii, PseudoOps
-@section .asciz @var{strings}
-This is just like .ascii, but each string is followed by a zero byte.
-The `z' in `.asciz' stands for `zero'.
+@node Asciz, Byte, Ascii, Pseudo Ops
+@section @code{.asciz "@var{string}"}@dots{}
+@code{.asciz} is just like @code{.ascii}, but each string is followed by
+a zero byte.  The ``z'' in @samp{.asciz} stands for ``zero''.
 
-@node Byte, Comm, Asciz, PseudoOps
-@section .byte @var{expressions}
+@node Byte, Comm, Asciz, Pseudo Ops
+@section @code{.byte @var{expressions}}
 
-This expects zero or more expressions, separated by commas.
+@code{.byte} expects zero or more expressions, separated by commas.
 Each expression is assembled into the next byte.
 
-@node Comm, Data, Byte, PseudoOps
-@section .comm @var{symbol} , @var{length}
-This declares a named common area in the bss segment.  Normally
-@code{ld} reserves memory addresses for it during linking, so no
-partial program defines the location of the symbol.  Tell @code{ld}
-that it must be at least @var{length} bytes long.  @code{ld} will
-allocate space that is at least as long as the longest @code{.comm}
-request in any of the partial programs linked.  @var{length} is an
-absolute expression.
-
-@node Data, Desc, Comm, PseudoOps
-@section .data @var{subsegment}
-This tells @code{as} to assemble the following statements onto the
+@node Comm, Data, Byte, Pseudo Ops
+@section @code{.comm @var{symbol} , @var{length} }
+@code{.comm} declares a named common area in the bss segment.  Normally
+@code{_LD__} reserves memory addresses for it during linking, so no partial
+program defines the location of the symbol.  Use @code{.comm} to tell
+@code{_LD__} that it must be at least @var{length} bytes long.  @code{_LD__}
+will allocate space for each @code{.comm} symbol that is at least as
+long as the longest @code{.comm} request in any of the partial programs
+linked.  @var{length} is an absolute expression.
+
+@node Data, Desc, Comm, Pseudo Ops
+@section @code{.data @var{subsegment}}
+@code{.data} tells @code{_AS__} to assemble the following statements onto the
 end of the data subsegment numbered @var{subsegment} (which is an
 absolute expression).  If @var{subsegment} is omitted, it defaults
 to zero.
 
-@node Desc, Double, Data, PseudoOps
-@section .desc @var{symbol}, @var{absolute-expression}
-This sets @code{n_desc} of the symbol to the low 16 bits of
-@var{absolute-expression}.
-
-@node Double, File, Desc, PseudoOps
-@section .double @var{flonums}
-This expects zero or more flonums, separated by commas.  It assembles
-floating point numbers.  The exact kind of floating point numbers
-emitted depends on what computer @code{as} is assembling for.  See
-the machine-specific part of the manual for the machine the
-assembler is running on for more information.
-
-@node File, Fill, Double, PseudoOps
-@section .file @var{string}
-This tells @code{as} that we are about to start a new logical
-file.  @var{String} is the new file name.  An empty file name
-is OK, but you must still give the quotes: @code{""}.  This
-statement may go away in future: it is only recognized to
-be compatible with old @code{as} programs.
-
-@node Fill, Float, File, PseudoOps
-@section .fill @var{repeat} , @var{size} , @var{value}
+_if__(_COFF__)
+@node Def,,,
+@section @code{.def @var{name}}
+Begin defining debugging information for a symbol @var{name}; the
+definition extends until the @code{.endef} directive is encountered.
+_if__(_BOUT__)
+
+This directive is only observed when @code{_AS__} is configured for COFF
+format output; when producing @code{b.out}, @samp{.def} is recognized,
+but ignored.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+_if__(_AOUT__||_BOUT__)
+@node Desc, Double, Data, Pseudo Ops
+@section @code{.desc @var{symbol}, @var{abs-expression}}
+This directive sets the descriptor of the symbol (@pxref{Symbol Attributes})
+to the low 16 bits of an absolute expression.
+
+_if__(_COFF__)
+The @samp{.desc} directive is not available when @code{_AS__} is
+configured for COFF output; it is only for @code{a.out} or @code{b.out}
+object format.  For the sake of compatibility, @code{_AS__} will accept
+it, but produce no output, when configured for COFF.
+_fi__(_COFF__)
+_fi__(_AOUT__||_BOUT__)
+
+_if__(_COFF__)
+@node Dim,,,
+@section @code{.dim}
+This directive is generated by compilers to include auxiliary debugging
+information in the symbol table.  It is only permitted inside
+@code{.def}/@code{.endef} pairs.
+_if__(_BOUT__)
+
+@samp{.dim} is only meaningful when generating COFF format output; when
+@code{_AS__} is generating @code{b.out}, it accepts this directive but
+ignores it.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+@node Double, Else, Desc, Pseudo Ops
+@section @code{.double @var{flonums}}
+@code{.double} expects zero or more flonums, separated by commas.  It
+assembles floating point numbers.
+_if__(_ALL_ARCH__)
+The exact kind of floating point numbers emitted depends on how
+@code{_AS__} is configured.  @xref{_MACH_DEP__}.
+_fi__(_ALL_ARCH__)
+_if__(_AMD29K__ || _I960__)
+On the _HOST__ family @samp{.double} emits 64-bit floating-point numbers
+in IEEE format.
+_fi__(_AMD29K__ || _I960__)
+
+@node Else,,,
+@section @code{.else}
+@code{.else} is part of the @code{_AS__} support for conditional assembly;
+@pxref{If}.  It marks the beginning of a section of code to be assembled
+if the condition for the preceding @code{.if} was false.
+
+_if__(0)
+@node End,,,
+@section @code{.end}
+This doesn't do anything---but isn't an s_ignore, so I suspect it's
+meant to do something eventually (which is why it isn't documented here
+as "for compatibility with blah").
+_fi__(0)
+
+_if__(_COFF__)
+@node Endef,,,
+@section @code{.endef}
+This directive flags the end of a symbol definition begun with
+@code{.def}. 
+_if__(_BOUT__)
+
+@samp{.endef} is only meaningful when generating COFF format output; if
+@code{_AS__} is configured to generate @code{b.out}, it accepts this
+directive but ignores it.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+@node Endif, Equ, End, Pseudo Ops
+@section @code{.endif}
+@code{.endif} is part of the @code{_AS__} support for conditional assembly;
+it marks the end of a block of code that is only assembled
+conditionally.  @xref{If}.
+
+@node Equ, Extern, Endif, Pseudo Ops
+@section @code{.equ @var{symbol}, @var{expression}}
+
+This directive sets the value of @var{symbol} to @var{expression}.
+It is synonymous with @samp{.set}; @pxref{Set}.
+
+@node Extern,,,
+@section @code{.extern}
+@code{.extern} is accepted in the source program---for compatibility
+with other assemblers---but it is ignored.  @code{_AS__} treats
+all undefined symbols as external.
+
+_if__(!_AMD29K__)
+@node File,,,
+@section @code{.app-file @var{string}}
+@code{.file} (which may also be spelled @samp{.app-file}) tells
+@code{_AS__} that we are about to start a new logical file.
+@var{string} is the new file name.  In general, the filename is
+recognized whether or not it is surrounded by quotes @samp{"}; but if
+you wish to specify an empty file name, you must give the
+quotes--@code{""}.  This statement may go away in future: it is only
+recognized to be compatible with old @code{_AS__} programs.
+_fi__(!_AMD29K__)
+
+
+@node Fill,,,
+@section @code{.fill @var{repeat} , @var{size} , @var{value}}
 @var{result}, @var{size} and @var{value} are absolute expressions.
 This emits @var{repeat} copies of @var{size} bytes.  @var{Repeat}
 may be zero or more.  @var{Size} may be zero or more, but if it is
@@ -1369,221 +1806,535 @@ more than 8, then it is deemed to have the value 8, compatible with
 other people's assemblers.  The contents of each @var{repeat} bytes
 is taken from an 8-byte number.  The highest order 4 bytes are
 zero.  The lowest order 4 bytes are @var{value} rendered in the
-byte-order of an integer on the computer @code{as} is assembling for.
+byte-order of an integer on the computer @code{_AS__} is assembling for.
 Each @var{size} bytes in a repetition is taken from the lowest order
 @var{size} bytes of this number.  Again, this bizarre behavior is
 compatible with other people's assemblers.
 
-@var{Size} and @var{value} are optional.
+@var{size} and @var{value} are optional.
 If the second comma and @var{value} are absent, @var{value} is
 assumed zero.  If the first comma and following tokens are absent,
 @var{size} is assumed to be 1.
 
-@node Float, Global, Fill, PseudoOps
-@section .float @var{flonums}
-This directive assembles zero or more flonums, separated by commas.
-The exact kind of floating point numbers emitted depends on what
-computer @code{as} is assembling for.  See the machine-specific part
-of the manual for the machine the assembler is running on for more
-information.
-
-@node Global, Int, Float, PseudoOps
-@section .global @var{symbol}
-This makes the symbol visible to @code{ld}.  If you define
+@node Float, Global, Fill, Pseudo Ops
+@section @code{.float @var{flonums}}
+This directive assembles zero or more flonums, separated by commas.  It
+has the same effect as @code{.single}.
+_if__(_ALL_ARCH__)
+The exact kind of floating point numbers emitted depends on how
+@code{_AS__} is configured.
+@xref{_MACH_DEP__}.
+_fi__(_ALL_ARCH__)
+_if__(_AMD29K__ || _I960__)
+On the _HOST__ family, @code{.float} emits 32-bit floating point numbers
+in IEEE format.
+_fi__(_AMD29K__ || _I960__)
+
+@node Global, Ident, Float, Pseudo Ops
+@section @code{.global @var{symbol}}, @code{.globl @var{symbol}}
+@code{.global} makes the symbol visible to @code{_LD__}.  If you define
 @var{symbol} in your partial program, its value is made available to
 other partial programs that are linked with it.  Otherwise,
 @var{symbol} will take its attributes from a symbol of the same name
 from another partial program it is linked with.
 
-This is done by setting the @code{N_EXT} bit
-of that symbol's @code{n_type} to 1.
+_if__(!_I960__)
+@c FIXME BFD implications; this is different in COFF.
+This is done by setting the @code{N_EXT} bit of that symbol's type byte
+to 1. @xref{Symbol Attributes}.
+_fi__(!_I960__)
+
+Both spellings (@samp{.globl} and @samp{.global}) are accepted, for
+compatibility with other assemblers.
+
+@node hword, line, file, Machine Directives
+@section @code{.hword @var{expressions}}
+This expects zero or more @var{expressions}, and emits
+a 16 bit number for each.
+
+_if__(_ALL_ARCH__)
+This directive is a synonym for @samp{.short}; depending on the target
+architecture, it may also be a synonym for @samp{.word}.
+_fi__(_ALL_ARCH__)
+_if__( (_AMD29K__ || _I960__) && !_ALL_ARCH__ )
+This directive is a synonym for @samp{.short}.
+_fi__( (_AMD29K__ || _I960__) && !_ALL_ARCH__ )
+
+_if__(_AOUT__||_BOUT__||_COFF__)
+@node Ident, If, Global, Pseudo Ops
+@section @code{.ident}
+This directive is used by some assemblers to place tags in object files.
+@code{_AS__} simply accepts the directive for source-file
+compatibility with such assemblers, but does not actually emit anything
+for it.
+_fi__(_AOUT__||_BOUT__||_COFF__)
+
+@node If, Include, Ident, Pseudo Ops
+@section @code{.if @var{absolute expression}}
+@code{.if} marks the beginning of a section of code which is only
+considered part of the source program being assembled if the argument
+(which must be an @var{absolute expression}) is non-zero.  The end of
+the conditional section of code must be marked by @code{.endif}
+(@pxref{Endif}); optionally, you may include code for the
+alternative condition, flagged by @code{.else} (@pxref{Else}.
+
+The following variants of @code{.if} are also supported:
+@table @code
+@item ifdef @var{symbol}
+Assembles the following section of code if the specified @var{symbol}
+has been defined.
+
+_if__(0)
+@item ifeqs
+Not yet implemented.
+_fi__(0)
+
+@item ifndef @var{symbol}
+@itemx ifnotdef @var{symbol}
+Assembles the following section of code if the specified @var{symbol}
+has not been defined.  Both spelling variants are equivalent.
+
+_if__(0)
+@item ifnes
+Not yet implemented.
+_fi__(0)
+@end table
 
-@node Int, Lcomm, Global, PseudoOps
-@section .int @var{expressions}
+@node Include, Int, If, Pseudo Ops
+@section @code{.include "@var{file}"}
+This directive provides a way to include supporting files at specified
+points in your source program.  The code from @var{file} is assembled as
+if it followed the point of the @code{.include}; when the end of the
+included file is reached, assembly of the original file continues.  You
+can control the search paths used with the @samp{-I} command-line option
+(@pxref{Options}).  Quotation marks are required around @var{file}.
+
+@node Int, Lcomm, Include, Pseudo Ops
+@section @code{.int @var{expressions}}
 Expect zero or more @var{expressions}, of any segment, separated by
 commas.  For each expression, emit a 32-bit number that will, at run
 time, be the value of that expression.  The byte order of the
 expression depends on what kind of computer will run the program.
 
-@node Lcomm, Line, Int, PseudoOps
-@section .lcomm @var{symbol} , @var{length}
+@node Lcomm, Line, Int, Pseudo Ops
+@section @code{.lcomm @var{symbol} , @var{length}}
 Reserve @var{length} (an absolute expression) bytes for a local
-common and denoted by @var{symbol}, whose segment and value are
+common denoted by @var{symbol}.  The segment and value of @var{symbol} are
 those of the new local common.  The addresses are allocated in the
-@code{bss} segment, so at run-time the bytes will start off zeroed.
-@var{Symbol} is not declared global (@xref{Global}.), so is normally
-not visible to @code{ld}.
-
-@node Line, Long, Lcomm, PseudoOps
-@section .line @var{logical line number}
-This tells @code{as} to change the logical line number.
-@var{logical line number} is an absolute expression.  The next line
-will have that logical line number.  So any other statements on the
-current line (after a @code{;}) will be reported as on logical line
-number @var{logical line number} - 1.  One day this directive will
-be unsupported: it is used only for compatibility with existing
-assembler programs.
-
-@node Long, Lsym, Line, PseudoOps
-@section .long @var{expressions}
-This is the same as @samp{.int}, @pxref{Int}.
-
-@node Lsym, Octa, Long, PseudoOps
-@section .lsym @var{symbol}, @var{expression}
-This creates a new symbol named @var{symbol}, but do not put it in
+bss segment, so at run-time the bytes will start off zeroed.
+@var{Symbol} is not declared global (@pxref{Global}), so is normally
+not visible to @code{_LD__}.
+
+_if__(_AOUT__||_BOUT__||_COFF__)
+_if__(!_AMD29K__)
+@node Line,,,
+@section @code{.line @var{line-number}}
+_fi__(!_AMD29K__)
+_if__(_AMD29K__)
+@node Ln,,,
+@section @code{.ln @var{line-number}}
+_fi__(_AMD29K__)
+_fi__(_AOUT__||_BOUT__||_COFF__)
+_if__(_AOUT__||_BOUT__)
+Tell @code{_AS__} to change the logical line number.  @var{line-number} must be
+an absolute expression.  The next line will have that logical line
+number.  So any other statements on the current line (after a statement
+separator character
+_if__(_AMD29K__)
+@samp{@@})
+_fi__(_AMD29K__)
+_if__(!_AMD29K__)
+@code{;})
+_fi__(!_AMD29K__)
+will be reported as on logical line number
+@var{line-number} @minus{} 1.
+One day this directive will be unsupported: it is used only
+for compatibility with existing assembler programs. @refill
+_fi__(_AOUT__||_BOUT__)
+_if__(_COFF__)
+
+Even though this is a directive associated with the @code{a.out} or
+@code{b.out} object-code formats, @code{_AS__} will still recognize it
+when producing COFF output, and will treat @samp{.line} as though it
+were the COFF @samp{.ln} @emph{if} it is found outside a
+@code{.def}/@code{.endef} pair.  
+
+Inside a @code{.def}, @samp{.line} is, instead, one of the directives
+used by compilers to generate auxiliary symbol information for
+debugging.
+_fi__(_COFF__)
+
+_if__(_AOUT__&&!_AMD29K__)
+@node Ln,,,
+@section @code{.ln @var{line-number}}
+@samp{.ln} is a synonym for @samp{.line}.
+_fi__(_AOUT__&&!_AMD29K__)
+
+_if__(_COFF__&&!_AOUT__)
+@node Ln,,,
+@section @code{.ln @var{line-number}}
+Tell @code{_AS__} to change the logical line number.  @var{line-number}
+must be an absolute expression.  The next line will have that logical
+line number.  So any other statements on the current line (after a
+statement separator character @code{;}) will be reported as on logical
+line number @var{line-number} @minus{} 1.
+_if__(_BOUT__)
+
+This directive is accepted, but ignored, when @code{_AS__} is configured for
+@code{b.out}; its effect is only associated with COFF output format.
+_fi__(_BOUT__)
+_fi__(_COFF__&&!_AOUT__)
+
+@node List,,,
+@section @code{.list} and related directives
+@code{_AS__} ignores the directives @code{.list}, @code{.nolist},
+@code{.eject}, @code{.lflags}, @code{.title}, @code{.sbttl}; however,
+they're accepted for compatibility with assemblers that use them.
+
+@node Long, Lsym, List, Pseudo Ops
+@section @code{.long @var{expressions}}
+@code{.long} is the same as @samp{.int}, @pxref{Int}.
+
+@node Lsym, Octa, Long, Pseudo Ops
+@section @code{.lsym @var{symbol}, @var{expression}}
+@code{.lsym} creates a new symbol named @var{symbol}, but does not put it in
 the hash table, ensuring it cannot be referenced by name during the
 rest of the assembly.  This sets the attributes of the symbol to be
-the same as the expression value.  @code{n_other} = @code{n_desc} =
-0.  @code{n_type} = (whatever segment the expression has); the
-@code{N_EXT} bit of @code{n_type} is zero.  @code{n_value} =
-(expression's value).
-
-@node Octa, Org, Lsym, PseudoOps
-@section .octa @var{bignums}
-This expects zero or more bignums, separated by commas.  For each
-bignum, it emits an 16-byte (@b{octa}-word) integer.
-
-@node Org, Quad, Octa, PseudoOps
-@section .org @var{new-lc} , @var{fill}
-This will advance the location counter of the current segment to
+the same as the expression value:
+@smallexample
+@var{other} = @var{descriptor} = 0
+@var{type} = @r{(segment of @var{expression})}
+@var{value} = @var{expression}
+@end smallexample
+@noindent
+The new symbol is not flagged as external.
+
+@c FIXME: double size emitted for "octa" on i960, others?  Or warn?
+@node Octa, Org, Lsym, Pseudo Ops
+@section @code{.octa @var{bignums}}
+This directive expects zero or more bignums, separated by commas.  For each
+bignum, it emits a 16-byte integer.
+
+The term ``octa'' comes from contexts in which a ``word'' is two bytes;
+hence @emph{octa}-word for 16 bytes.
+
+@node Org, Quad, Octa, Pseudo Ops
+@section @code{.org @var{new-lc} , @var{fill}}
+
+@code{.org} will advance the location counter of the current segment to
 @var{new-lc}.  @var{new-lc} is either an absolute expression or an
-expression with the same segment as the current subsegment.  That
-is, you can't use @code{.org} to cross segments.  Because @code{as}
-tries to assemble programs in one pass @var{new-lc} must be defined.
-If you really detest this restriction we eagerly await a chance to
-share your improved assembler.  To be compatible with former
-assemblers, if the segment of @var{new-lc} is absolute then we
-pretend the segment of @var{new-lc} is the same as the current
-subsegment.
+expression with the same segment as the current subsegment.  That is,
+you can't use @code{.org} to cross segments: if @var{new-lc} has the
+wrong segment, the @code{.org} directive is ignored.  To be compatible
+with former assemblers, if the segment of @var{new-lc} is absolute,
+@code{_AS__} will issue a warning, then pretend the segment of @var{new-lc}
+is the same as the current subsegment.
+
+@code{.org} may only increase the location counter, or leave it
+unchanged; you cannot use @code{.org} to move the location counter
+backwards.
+
+@c double negative used below "not undefined" because this is a specific
+@c reference to "undefined" (as SEG_UNKNOWN is called in this manual)
+@c segment. pesch@cygnus.com 18feb91
+Because @code{_AS__} tries to assemble programs in one pass @var{new-lc}
+may not be undefined.  If you really detest this restriction we eagerly await
+a chance to share your improved assembler.
 
 Beware that the origin is relative to the start of the segment, not
 to the start of the subsegment.  This is compatible with other
 people's assemblers.
 
-If the location counter (of the current subsegment) is advanced, the
+When the location counter (of the current subsegment) is advanced, the
 intervening bytes are filled with @var{fill} which should be an
 absolute expression.  If the comma and @var{fill} are omitted,
 @var{fill} defaults to zero.
 
-@node Quad, Set, Org, PseudoOps
-@section .quad @var{bignums}
-This expects zero or more bignums, separated by commas.  For each
-bignum, it emits an 8-byte (@b{quad}-word) integer.  If the bignum
-won't fit in a quad-word, it prints a warning message; and just
-takes the lowest order 8 bytes of the bignum.
-
-@node Set, Short, Quad, PseudoOps
-@section .set @var{symbol}, @var{expression}
-
-This sets the value of @var{symbol} to expression.  This will change
-@code{n_value} and @code{n_type} to conform to the @var{expression}.
-if @code{n_ext} is set, it remains set.
-
-It is OK to @code{.set} a symbol many times in the same assembly.
+@node Quad, Set, Org, Pseudo Ops
+@section @code{.quad @var{bignums}}
+@code{.quad} expects zero or more bignums, separated by commas.  For
+each bignum, it emits
+_if__(!_I960__)
+an 8-byte integer.  If the bignum won't fit in 8
+bytes, it prints a warning message; and just takes the lowest order 8
+bytes of the bignum.@refill
+
+The term ``quad'' comes from contexts in which a ``word'' is two bytes;
+hence @emph{quad}-word for 8 bytes.
+_fi__(!_I960__)
+_if__(_I960__)
+a 16-byte integer.  If the bignum won't fit in 16 bytes, it prints a
+warning message; and just takes the lowest order 16 bytes of the
+bignum.@refill 
+_fi__(_I960__)
+
+_if__(_COFF__)
+@node Scl,,,
+@section @code{.scl @var{class}}
+Set the storage-class value for a symbol.  This directive may only be
+used inside a @code{.def}/@code{.endef} pair.  Storage class may flag
+whether a symbol is static or external, or it may record further
+symbolic debugging information.
+_if__(_BOUT__)
+
+The @samp{.scl} directive is primarily associated with COFF output; when
+configured to generate @code{b.out} output format, @code{_AS__} will
+accept this directive but ignore it.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+
+@node Set,,,
+@section @code{.set @var{symbol}, @var{expression}}
+
+This directive sets the value of @var{symbol} to @var{expression}.  This
+will change @var{symbol}'s value and type to conform to
+@var{expression}.  If @var{symbol} was flagged as external, it remains
+flagged. (@xref{Symbol Attributes}.)
+
+You may @code{.set} a symbol many times in the same assembly.
 If the expression's segment is unknowable during pass 1, a second
 pass over the source program will be forced.  The second pass is
-currently not implemented.  @code{as} will abort with an error
+currently not implemented.  @code{_AS__} will abort with an error
 message if one is required.
 
 If you @code{.set} a global symbol, the value stored in the object
 file is the last value stored into it.
 
-@node Short, Space, Set, PseudoOps
-@section .short @var{expressions}
-Except on the Sparc this is the same as @samp{.word}.  @xref{Word}.
-On the sparc, this expects zero or more @var{expressions}, and emits
+@node Short, Single, Set, Pseudo Ops
+@section @code{.short @var{expressions}}
+_if__(! (_SPARC__ || _AMD29K__ || _I960__) )
+@code{.short} is the same as @samp{.word}.  @xref{Word}.
+_fi__(! (_SPARC__ || _AMD29K__ || _I960__) )
+_if__(_SPARC__ || _AMD29K__ || _I960__)
+This expects zero or more @var{expressions}, and emits
 a 16 bit number for each.
-
-@node Space, Stab, Short, PseudoOps
-@section .space @var{size} , @var{fill}
-This emits @var{size} bytes, each of value @var{fill}.  Both
+_fi__(_SPARC__ || _AMD29K__ || _I960__)
+
+@node Single,,,
+@section @code{.single @var{flonums}}
+This directive assembles zero or more flonums, separated by commas.  It
+has the same effect as @code{.float}.
+_if__(_ALL_ARCH__)
+The exact kind of floating point numbers emitted depends on how
+@code{_AS__} is configured.  @xref{_MACH_DEP__}.
+_fi__(_ALL_ARCH__)
+_if__(_AMD29K__ || _I960__)
+On the _HOST__ family, @code{.single} emits 32-bit floating point
+numbers in IEEE format.
+_fi__(_AMD29K__ || _I960__)
+
+_if__(_COFF__)
+@node Size,,,
+@section @code{.size}
+This directive is generated by compilers to include auxiliary debugging
+information in the symbol table.  It is only permitted inside
+@code{.def}/@code{.endef} pairs.
+_if__(_BOUT__)
+
+@samp{.size} is only meaningful when generating COFF format output; when
+@code{_AS__} is generating @code{b.out}, it accepts this directive but
+ignores it.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+@node Space,,,
+_if__(!_AMD29K__)
+@section @code{.space @var{size} , @var{fill}}
+This directive emits @var{size} bytes, each of value @var{fill}.  Both
 @var{size} and @var{fill} are absolute expressions.  If the comma
 and @var{fill} are omitted, @var{fill} is assumed to be zero.
-
-@node Stab, Text, Space, PseudoOps
-@section .stabd, .stabn, .stabs
-There are three directives that begin @code{.stab@dots{}}.
-All emit symbols, for use by symbolic debuggers.
-The symbols are not entered in @code{as}' hash table: they
+_fi__(!_AMD29K__)
+
+_if__(_AMD29K__)
+@section @code{.space}
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@quotation
+@emph{Warning:} In other versions of the GNU assembler, the directive
+@code{.space} has the effect of @code{.block}  @xref{Machine Directives}.
+@end quotation
+_fi__(_AMD29K__)
+
+_if__(_AOUT__||_BOUT__||_COFF__)
+@node Stab, Text, Space, Pseudo Ops
+@section @code{.stabd, .stabn, .stabs}
+There are three directives that begin @samp{.stab}.
+All emit symbols (@pxref{Symbols}), for use by symbolic debuggers.
+The symbols are not entered in the @code{_AS__} hash table: they
 cannot be referenced elsewhere in the source file.
 Up to five fields are required:
 @table @var
 @item string
 This is the symbol's name.  It may contain any character except @samp{\000},
 so is more general than ordinary symbol names.  Some debuggers used to
-code arbitrarily complex structures into symbol names using this technique.
+code arbitrarily complex structures into symbol names using this field.
 @item type
-An absolute expression.  The symbol's @code{n_type} is set to the low 8
+An absolute expression.  The symbol's type is set to the low 8
 bits of this expression.
-Any bit pattern is permitted, but @code{ld} and debuggers will choke on
+Any bit pattern is permitted, but @code{_LD__} and debuggers will choke on
 silly bit patterns.
 @item other
 An absolute expression.
-The symbol's @code{n_other} is set to the low 8 bits of this expression.
+The symbol's ``other'' attribute is set to the low 8 bits of this expression.
 @item desc
 An absolute expression.
-The symbol's @code{n_desc} is set to the low 16 bits of this expression.
+The symbol's descriptor is set to the low 16 bits of this expression.
 @item value
-An absolute expression which becomes the symbol's @code{n_value}.
+An absolute expression which becomes the symbol's value.
 @end table
 
-If a warning is detected while reading the @code{.stab@dots{}}
-statement the symbol has probably already been created and you will
-get a half-formed symbol in your object file.  This is compatible
-with earlier assemblers (!)
+If a warning is detected while reading a @code{.stabd}, @code{.stabn},
+or @code{.stabs} statement, the symbol has probably already been created
+and you will get a half-formed symbol in your object file.  This is
+compatible with earlier assemblers!
 
-.stabd @var{type} , @var{other} , @var{desc}
+@table @code
+@item .stabd @var{type} , @var{other} , @var{desc}
 
 The ``name'' of the symbol generated is not even an empty string.
 It is a null pointer, for compatibility.  Older assemblers used a
 null pointer so they didn't waste space in object files with empty
 strings.
 
-The symbol's @code{n_value} is set to the location counter,
+The symbol's value is set to the location counter,
 relocatably.  When your program is linked, the value of this symbol
 will be where the location counter was when the @code{.stabd} was
 assembled.
 
-.stabn @var{type} , @var{other} , @var{desc} , @var{value}
+@item .stabn @var{type} , @var{other} , @var{desc} , @var{value}
 
 The name of the symbol is set to the empty string @code{""}.
 
-.stabs @var{string} ,  @var{type} , @var{other} , @var{desc} , @var{value}
+@item .stabs @var{string} ,  @var{type} , @var{other} , @var{desc} , @var{value}
 
-@node Text, Word, Stab, PseudoOps
-@section .text @var{subsegment}
-Tells @code{as} to assemble the following statements onto the end of
+All five fields are specified.
+@end table
+_fi__(_AOUT__||_BOUT__||_COFF__)
+
+_if__(_COFF__)
+@node Tag,,,
+@section @code{.tag @var{structname}}
+This directive is generated by compilers to include auxiliary debugging
+information in the symbol table.  It is only permitted inside
+@code{.def}/@code{.endef} pairs.  Tags are used to link structure
+definitions in the symbol table with instances of those structures.
+_if__(_BOUT__)
+
+@samp{.tag} is only used when generating COFF format output; when
+@code{_AS__} is generating @code{b.out}, it accepts this directive but
+ignores it.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+@node Text,,,
+@section @code{.text @var{subsegment}}
+Tells @code{_AS__} to assemble the following statements onto the end of
 the text subsegment numbered @var{subsegment}, which is an absolute
 expression.  If @var{subsegment} is omitted, subsegment number zero
 is used.
 
-@node Word, , Text, PseudoOps
-@section .word @var{expressions}
-On the Sparc, this produces 32-bit numbers instead of 16-bit ones.
-This expect zero or more @var{expressions}, of any segment,
-separated by commas.  For each expression, emit a 16-bit number that
-will, at run time, be the value of that expression.  The byte order
-of the expression depends on what kind of computer will run the
-program.
+_if__(_COFF__)
+@node Type,,,
+@section @code{.type @var{int}}
+This directive, permitted only within @code{.def}/@code{.endef} pairs,
+records the integer @var{int} as the type attribute of a symbol table entry.
+_if__(_BOUT__)
+
+@samp{.type} is associated only with COFF format output; when
+@code{_AS__} is configured for @code{b.out} output, it accepts this
+directive but ignores it.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+_if__(_COFF__)
+@node Val,,,
+@section @code{.val @var{addr}}
+This directive, permitted only within @code{.def}/@code{.endef} pairs,
+records the address @var{addr} as the value attribute of a symbol table
+entry.
+_if__(_BOUT__)
+
+@samp{.val} is used only for COFF output; when @code{_AS__} is
+configured for @code{b.out}, it accepts this directive but ignores it.
+_fi__(_BOUT__)
+_fi__(_COFF__)
+
+@node Word,,,
+@section @code{.word @var{expressions}}
+This directive expects zero or more @var{expressions}, of any segment,
+separated by commas.
+_if__(_SPARC__ || _AMD29K__ || _I960__)
+For each expression, @code{_AS__} emits a 32-bit number.
+_fi__(_SPARC__ || _AMD29K__ || _I960__)
+_if__(! (_SPARC__ || _AMD29K__ || _I960__) )
+For each expression, @code{_AS__} emits a 16-bit number.
+_fi__(! (_SPARC__ || _AMD29K__ || _I960__) )
+
+_if__(_ALL_ARCH__)
+The byte order of the expression depends on what kind of computer will
+run the program.
+_fi__(_ALL_ARCH__)
+
+@c on these boxes the "special treatment to support compilers" doesn't
+@c happen---32-bit addressability, period; no long/short jumps.
+_if__(! (_AMD29K__ || _I960__) )
+@subsection Special Treatment to support Compilers
 
+In order to assemble compiler output into something that will work,
+@code{_AS__} will occasionlly do strange things to @samp{.word} directives.
+Directives of the form @samp{.word sym1-sym2} are often emitted by
+compilers as part of jump tables.  Therefore, when @code{_AS__} assembles a
+directive of the form @samp{.word sym1-sym2}, and the difference between
+@code{sym1} and @code{sym2} does not fit in 16 bits, @code{_AS__} will
+create a @dfn{secondary jump table}, immediately before the next label.
+This @var{secondary jump table} will be preceded by a short-jump to the
+first byte after the secondary table.  This short-jump prevents the flow
+of control from accidentally falling into the new table.  Inside the
+table will be a long-jump to @code{sym2}.  The original @samp{.word}
+will contain @code{sym1} minus the address of the long-jump to
+@code{sym2}.
+
+If there were several occurrences of @samp{.word sym1-sym2} before the
+secondary jump table, all of them will be adjusted.  If there was a
+@samp{.word sym3-sym4}, that also did not fit in sixteen bits, a
+long-jump to @code{sym4} will be included in the secondary jump table,
+and the @code{.word} directives will be adjusted to contain @code{sym3}
+minus the address of the long-jump to @code{sym4}; and so on, for as many
+entries in the original jump table as necessary.
+
+_if__(_INTERNALS__)
+@emph{This feature may be disabled by compiling @code{_AS__} with the
+@samp{-DWORKING_DOT_WORD} option.} This feature is likely to confuse
+assembly language programmers.
+_fi__(_INTERNALS__)
+_fi__(! (_AMD29K__ || _I960__) )
+
+@node Deprecated, _MACH_DEP__, Word, Pseudo Ops
 @section Deprecated Directives
 One day these directives won't work.
 They are included for compatibility with older assemblers.
 @table @t
 @item .abort
-@item .file
+@item .app-file
 @item .line
 @end table
 
-@node MachineDependent, Maintenance, PseudoOps, top
+@node _MACH_DEP__,,,
+_if__(_ALL_ARCH__)
 @chapter Machine Dependent Features
-@section Vax
-@subsection Options
+_fi__(_ALL_ARCH__)
+_if__(_VAX__)
+@group
+_CHAPSEC__(0+_ALL_ARCH__) VAX Dependent Features
+_CHAPSEC__(1+_ALL_ARCH__) Options
 
-The Vax version of @code{as} accepts any of the following options,
+The Vax version of @code{_AS__} accepts any of the following options,
 gives a warning message that the option was ignored and proceeds.
 These options are for compatibility with scripts designed for other
 people's assemblers.
+@end group
 
 @table @asis
 @item @kbd{-D} (Debug)
@@ -1600,7 +2351,7 @@ argument that follows @kbd{-d} (GNU standard).
 @item @kbd{-V} (Virtualize Interpass Temporary File)
 Some other assemblers use a temporary file.  This option
 commanded them to keep the information in active memory rather
-than in a disk file.  @code{as} always does this, so this
+than in a disk file.  @code{_AS__} always does this, so this
 option is redundant.
 
 @item @kbd{-J} (JUMPify Longer Branches)
@@ -1615,23 +2366,23 @@ this option to emit short and long branches.
 @item @kbd{-t} (Temporary File Directory)
 Some other assemblers may use a temporary file, and this option
 takes a filename being the directory to site the temporary
-file.  @code{as} does not use a temporary disk file, so this
+file.  @code{_AS__} does not use a temporary disk file, so this
 option makes no difference.  @kbd{-t} needs exactly one
 filename.
 @end table
 
 The Vax version of the assembler accepts two options when
 compiled for VMS.  They are @kbd{-h}, and @kbd{-+}.  The
-@kbd{-h} option prevents @code{as} from modifying the
+@kbd{-h} option prevents @code{_AS__} from modifying the
 symbol-table entries for symbols that contain lowercase
-characters (I think).  The @kbd{-+} option causes @code{as} to
+characters (I think).  The @kbd{-+} option causes @code{_AS__} to
 print warning messages if the FILENAME part of the object file,
 or any symbol name is larger than 31 characters.  The @kbd{-+}
 option also insertes some code following the @samp{_main}
-symbol so that the object file will be compatable with Vax-11
+symbol so that the object file will be compatible with Vax-11
 "C".
 
-@subsection Floating Point
+_CHAPSEC__(1+_ALL_ARCH__) Floating Point
 Conversion of flonums to floating point is correct, and
 compatible with previous assemblers.  Rounding is
 towards zero if the remainder is exactly half the least significant bit.
@@ -1639,14 +2390,14 @@ towards zero if the remainder is exactly half the least significant bit.
 @code{D}, @code{F}, @code{G} and @code{H} floating point formats
 are understood.
 
-Immediate floating literals (@i{e.g.} @samp{S`$6.9})
+Immediate floating literals (@emph{e.g.} @samp{S`$6.9})
 are rendered correctly.  Again, rounding is towards zero in the
 boundary case.
 
 The @code{.float} directive produces @code{f} format numbers.
 The @code{.double} directive produces @code{d} format numbers.
 
-@subsection Machine Directives
+_CHAPSEC__(1+_ALL_ARCH__) Machine Directives
 The Vax version of the assembler supports four directives for
 generating Vax floating point constants.  They are described in the
 table below.
@@ -1670,14 +2421,14 @@ assembles Vax @code{h} format 128-bit floating point constants.
 
 @end table
 
-@subsection Opcodes
+_CHAPSEC__(1+_ALL_ARCH__) Opcodes
 All DEC mnemonics are supported.  Beware that @code{case@dots{}}
 instructions have exactly 3 operands.  The dispatch table that
 follows the @code{case@dots{}} instruction should be made with
 @code{.word} statements.  This is compatible with all unix
 assemblers we know of.
 
-@subsection Branch Improvement
+_CHAPSEC__(1+_ALL_ARCH__) Branch Improvement
 Certain pseudo opcodes are permitted.  They are for branch
 instructions.  They expand to the shortest branch instruction that
 will reach the target.  Generally these mnemonics are made by
@@ -1756,7 +2507,7 @@ Unconditional branch.
 @end table
 @end table
 
-@subsection operands
+_CHAPSEC__(1+_ALL_ARCH__) operands
 The immediate character is @samp{$} for Unix compatibility, not
 @samp{#} as DEC writes it.
 
@@ -1772,9 +2523,9 @@ Register names understood are @code{r0 r1 r2 @dots{} r15 ap fp sp
 pc}.  Any case of letters will do.
 
 For instance
-@example
+@smallexample
 tstb *w`$4(r5)
-@end example
+@end smallexample
 
 Any expression is permitted in an operand.  Operands are comma
 separated.
@@ -1783,52 +2534,409 @@ separated.
 @c in operands, but I forget what it is.  It is
 @c a syntax clash because () is used as an address mode
 @c and to encapsulate sub-expressions.
-@subsection Not Supported
-Vax bit fields can not be assembled with @code{as}.  Someone
+_CHAPSEC__(1+_ALL_ARCH__) Not Supported
+Vax bit fields can not be assembled with @code{_AS__}.  Someone
 can add the required code if they really need it.
+_fi__(_VAX__)
+_if__(_AMD29K__)
+@group
+_CHAPSEC__(0+_ALL_ARCH__) AMD 29K Dependent Features
+@node AMD29K Options, AMD29K Syntax, _MACH_DEP__, _MACH_DEP__
+_CHAPSEC__(1+_ALL_ARCH__) Options
+@code{_AS__} has no additional command-line options for the AMD
+29K family.
+@end group
+
+@node AMD29K Syntax, AMD29K Floating Point, AMD29K Options, _MACH_DEP__
+@group
+_CHAPSEC__(1+_ALL_ARCH__) Syntax
+_CHAPSEC__(2+_ALL_ARCH__) Special Characters
+@samp{;} is the line comment character.
+
+@samp{@@} can be used instead of a newline to separate statements.
+
+The character @samp{?} is permitted in identifiers (but may not begin
+an identifier).
+@end group
+
+_CHAPSEC__(2+_ALL_ARCH__) Register Names
+General-purpose registers are represented by predefined symbols of the
+form @samp{GR@var{nnn}} (for global registers) or @samp{LR@var{nnn}}
+(for local registers), where @var{nnn} represents a number between
+@code{0} and @code{127}, written with no leading zeros.  The leading
+letters may be in either upper or lower case; for example, @samp{gr13}
+and @samp{LR7} are both valid register names.
+
+You may also refer to general-purpose registers by specifying the
+register number as the result of an expression (prefixed with @samp{%%}
+to flag the expression as a register number):
+@smallexample
+%%@var{expression}
+@end smallexample
+@noindent---where @var{expression} must be an absolute expression
+evaluating to a number between @code{0} and @code{255}.  The range
+[0, 127] refers to global registers, and the range [128, 255] to local
+registers.
+
+In addition, @code{_AS__} understands the following protected
+special-purpose register names for the AMD 29K family:
+
+@smallexample
+  vab    chd    pc0
+  ops    chc    pc1
+  cps    rbp    pc2
+  cfg    tmc    mmu
+  cha    tmr    lru
+@end smallexample
+
+These unprotected special-purpose register names are also recognized:
+@smallexample
+  ipc    alu    fpe
+  ipa    bp     inte
+  ipb    fc     fps
+  q      cr     exop
+@end smallexample
+
+@node AMD29K Floating Point, AMD29K Directives, AMD29K Syntax, _MACH_DEP__
+_CHAPSEC__(1+_ALL_ARCH__) Floating Point
+The AMD 29K family uses IEEE floating-point numbers.
+
+@group
+@node AMD29K Directives, AMD29K Opcodes, AMD29K Floating Point, _MACH_DEP__
+_CHAPSEC__(1+_ALL_ARCH__) Machine Directives
+
+@node block, cputype, AMD29K Directives, AMD29K Directives
+_CHAPSEC__(2+_ALL_ARCH__) @code{.block @var{size} , @var{fill}}
+This directive emits @var{size} bytes, each of value @var{fill}.  Both
+@var{size} and @var{fill} are absolute expressions.  If the comma
+and @var{fill} are omitted, @var{fill} is assumed to be zero.
 
-@section 680x0
-@subsection Options
-The 680x0 version of @code{as} has two machine dependent options.
-One shortens undefined references from 32 to 16 bits, while the
-other is used to tell @code{as} what kind of machine it is
-assembling for.
+In other versions of the GNU assembler, this directive is called
+@samp{.space}.
+@end group
+
+@node cputype, file, block, Machine Directives
+_CHAPSEC__(2+_ALL_ARCH__) @code{.cputype}
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@node file, hword, cputype, Machine Directives
+_CHAPSEC__(2+_ALL_ARCH__) @code{.file}
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@quotation
+@emph{Warning:} in other versions of the GNU assembler, @code{.file} is
+used for the directive called @code{.app-file} in the AMD 29K support.
+@end quotation
+
+@node line, reg, hword, Machine Directives
+_CHAPSEC__(2+_ALL_ARCH__) @code{.line}
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@node reg, sect, line, Machine Directives
+_CHAPSEC__(2+_ALL_ARCH__) @code{.reg @var{symbol}, @var{expression}}
+@code{.reg} has the same effect as @code{.lsym}; @pxref{Lsym}.
+
+@node sect, use, reg, Machine Directives
+_CHAPSEC__(2+_ALL_ARCH__) @code{.sect}
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@node use,  , sect, Machine Directives
+_CHAPSEC__(2+_ALL_ARCH__) @code{.use @var{segment name}}
+Establishes the segment and subsegment for the following code;
+@var{segment name} may be one of @code{.text}, @code{.data},
+@code{.data1}, or @code{.lit}.  With one of the first three @var{segment
+name} options, @samp{.use} is equivalent to the machine directive
+@var{segment name}; the remaining case, @samp{.use .lit}, is the same as
+@samp{.data 200}.
+
+
+@node AMD29K Opcodes, , AMD29K Directives, _MACH_DEP__
+@section Opcodes
+@code{_AS__} implements all the standard AMD 29K opcodes.  No
+additional pseudo-instructions are needed on this family.
+
+For information on the 29K machine instruction set, see @cite{Am29000
+User's Manual}, Advanced Micro Devices, Inc.
+
+_fi__(_AMD29K__)
+_if__(_I960__)
+_CHAPSEC__(0+_ALL_ARCH__) Intel 80960 Dependent Features
+@node Options-i960,,,
+_CHAPSEC__(1+_ALL_ARCH__) Command-line Options
+@table @code
 
-You can use the @kbd{-l} option to shorten the size of references to
-undefined symbols.  If the @kbd{-l} option is not given, references
-to undefined symbols will be a full long (32 bits) wide.  (Since
-@code{as} cannot know where these symbols will end up being,
-@code{as} can only allocate space for the linker to fill in later.
-Since @code{as} doesn't know how far away these symbols will be, it
-allocates as much space as it can.) If this option is given, the
-references will only be one word wide (16 bits).  This may be useful
-if you want the object file to be as small as possible, and you know
-that the relevant symbols will be less than 17 bits away.
-
-The 680x0 version of @code{as} is usually used to assemble programs
-for the Motorola MC68020 microprocessor.  Occasionally it is used to
-assemble programs for the mostly-similar-but-slightly-different
-MC68000 or MC68010 microprocessors.  You can give @code{as} the
-options @samp{-m68000}, @samp{-mc68000}, @samp{-m68010},
-@samp{-mc68010}, @samp{-m68020}, and @samp{-mc68020} to tell it what
-processor it should be assembling for.  Unfortunately, these options
-are almost entirely unused and untried.  They make work, but nobody
-has tested them much.
+@item -ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC
+Select the 80960 architecture.  Instructions or features not supported
+by the selected architecture cause fatal errors.
+
+@samp{-ACA} is equivalent to @samp{-ACA_A}; @samp{-AKC} is equivalent to
+@samp{-AMC}.  Synonyms are provided for compatibility with other tools.
+
+If none of these options is specified, @code{_AS__} will generate code for any
+instruction or feature that is supported by @emph{some} version of the
+960 (even if this means mixing architectures!).  In principle,
+@code{_AS__} will attempt to deduce the minimal sufficient processor
+type if none is specified; depending on the object code format, the
+processor type may be recorded in the object file.  If it is critical
+that the @code{_AS__} output match a specific architecture, specify that
+architecture explicitly.
+
+
+@item -b
+Add code to collect information about conditional branches taken, for
+later optimization using branch prediction bits.  (The conditional branch
+instructions have branch prediction bits in the CA, CB, and CC
+architectures.)  If @var{BR} represents a conditional branch instruction,
+the following represents the code generated by the assembler when
+@samp{-b} is specified:
+
+@smallexample
+        call    @var{increment routine}
+        .word   0       # pre-counter
+Label:  @var{BR}
+        call    @var{increment routine}
+        .word   0       # post-counter
+@end smallexample
+
+The counter following a branch records the number of times that branch
+was @emph{not} taken; the differenc between the two counters is the
+number of times the branch @emph{was} taken.
+
+A table of all such @code{Label}s is also generated, so that the
+external postprocessor @samp{gbr960} (supplied by Intel) can locate all
+the counters.  This table is always labelled @samp{__BRANCH_TABLE__};
+this is a local symbol to permit collecting statistics for many separate
+object files.  The table is word aligned, and begins with a two-word
+header.  The first word, initialized to 0, is used in maintaining linked
+lists of branch tables.  The second word is a count of the number of
+entries in the table, which follow immediately: each is a word, pointing
+to one of the labels illustrated above.
+
+@ifinfo
+@example
+ +------------+------------+------------+ ... +------------+
+ |            |            |            |     |            |
+ |  *NEXT     |  COUNT: N  | *BRLAB 1   |     | *BRLAB N   |
+ |            |            |            |     |            |
+ +------------+------------+------------+ ... +------------+
 
-@subsection Syntax
+               __BRANCH_TABLE__ layout
+@end example
+@end ifinfo
+@tex
+\vskip 1pc
+\line{\leftskip=0pt\hskip\tableindent
+\boxit{2cm}{\tt *NEXT}\boxit{2cm}{\tt COUNT: \it N}\boxit{2cm}{\tt
+*BRLAB 1}\ibox{1cm}{\quad\dots}\boxit{2cm}{\tt *BRLAB \it N}\hfil}
+\centerline{\it {\tt \_\_BRANCH\_TABLE\_\_} layout}
+@end tex
 
-The 680x0 version of @code{as} uses syntax similar to the Sun
-assembler.  Size modifieres are appended directly to the end of the
-opcode without an intervening period.  Thus, @samp{move.l} is
-written @samp{movl}, etc.
+The first word of the header is used to locate multiple branch tables,
+since each object file may contain one. Normally the links are
+maintained with a call to an initialization routine, placed at the
+beginning of each function in the file.  The GNU C compiler will
+generate these calls automatically when you give it a @samp{-b} option.
+For further details, see the documentation of @samp{gbr960}.
+
+@item -norelax
+Normally, Compare-and-Branch instructions with targets that require
+displacements greater than 13 bits (or that have external targets) are
+replaced with the corresponding compare (or @samp{chkbit}) and branch
+instructions.  You can use the @samp{-norelax} option to specify that
+@code{_AS__} should generate errors instead, if the target displacement
+is larger than 13 bits.
+
+This option does not affect the Compare-and-Jump instructions; the code
+emitted for them is @emph{always} adjusted when necessary (depending on
+displacement size), regardless of whether you use @samp{-norelax}.
+@end table
+
+@node Floating Point-i960,,,
+_CHAPSEC__(1+_ALL_ARCH__) Floating Point
+@code{_AS__} generates IEEE floating-point numbers for the directives
+@samp{.float}, @samp{.double}, @samp{extended}, and @samp{.single}.
+
+@group
+@node Directives-i960,,,
+_CHAPSEC__(1+_ALL_ARCH__) Machine Directives
+
+@node bss-i960,,,
+_CHAPSEC__(2+_ALL_ARCH__) @code{.bss @var{symbol}, @var{length}, @var{align}}
+Reserve @var{length} bytes in the bss segment for a local @var{symbol},
+aligned to the power of two specified by @var{align}.  @var{length} and
+@var{align} must be positive absolute expressions.  This directive
+differs from @samp{.lcomm} only in that it permits you to specify
+an alignment.  @xref{Lcomm}.
+@end group
+
+@node extended-i960,,,
+_CHAPSEC__(2+_ALL_ARCH__) @code{.extended @var{flonums}}
+@code{.extended} expects zero or more flonums, separated by commas; for
+each flonum, @samp{.extended} emits an IEEE extended-format (80-bit)
+floating-point number.
+
+@node leafproc-i960,,,
+_CHAPSEC__(2+_ALL_ARCH__) @code{.leafproc @var{call-lab}, @var{bal-lab}}
+You can use the @samp{.leafproc} directive in conjunction with the
+optimized @code{callj} instruction to enable faster calls of leaf
+procedures.  If a procedure is known to call no other procedures, you
+may define an entry point that skips procedure prolog code (and that does
+not depend on system-supplied saved context), and declare it as the
+@var{bal-lab} using @samp{.leafproc}.  If the procedure also has an
+entry point that goes through the normal prolog, you can specify that
+entry point as @var{call-lab}.
+
+A @samp{.leafproc} declaration is meant for use in conjunction with the
+optimized call instruction @samp{callj}; the directive records the data
+needed later to choose between converting the @samp{callj} into a
+@code{bal} or a @code{call}.
+
+@var{call-lab} is optional; if only one argument is present, or if the
+two arguments are identical, the single argument is assumed to be the
+@code{bal} entry point.
+
+@node sysproc-i960,,,
+_CHAPSEC__(2+_ALL_ARCH__) @code{.sysproc @var{name}, @var{index}}
+The @samp{.sysproc} directive defines a name for a system procedure.
+After you define it using @samp{.sysproc}, you can use @var{name} to
+refer to the system procedure identified by @var{index} when calling
+procedures with the optimized call instruction @samp{callj}.
+
+Both arguments are required; @var{index} must be between 0 and 31
+(inclusive).
+
+@node Opcodes for i960,,,
+_CHAPSEC__(1+_ALL_ARCH__) i960 Opcodes
+All Intel 960 machine instructions are supported; @pxref{Options-i960}
+for a discussion of selecting the instruction subset for a particular
+960 architecture.@refill
+
+Some opcodes are processed beyond simply emitting a single corresponding
+instruction: @samp{callj}, and Compare-and-Branch or Compare-and-Jump
+instructions with target displacements larger than 13 bits.
+
+@node callj-i960
+_CHAPSEC__(2+_ALL_ARCH__) @code{callj}
+You can write @code{callj} to have the assembler or the linker determine
+the most appropriate form of subroutine call: @samp{call},
+@samp{bal}, or @samp{calls}.  If the assembly source contains
+enough information---a @samp{.leafproc} or @samp{.sysproc} directive
+defining the operand---then @code{_AS__} will translate the
+@code{callj}; if not, it will simply emit the @code{callj}, leaving it
+for the linker to resolve.
+
+@node Compare-and-branch-i960
+_CHAPSEC__(2+_ALL_ARCH__) Compare-and-Branch
+
+The 960 architectures provide combined Compare-and-Branch instructions
+that permit you to store the branch target in the lower 13 bits of the
+instruction word itself.  However, if you specify a branch target far
+enough away that its address won't fit in 13 bits, the assembler can
+either issue an error, or convert your Compare-and-Branch instruction
+into separate instructions to do the compare and the branch.
+
+Whether @code{_AS__} gives an error or expands the instruction depends
+on two choices you can make: whether you use the @samp{-norelax} option,
+and whether you use a ``Compare and Branch'' instruction or a ``Compare
+and Jump'' instruction.  The ``Jump'' instructions are @emph{always}
+expanded if necessary; the ``Branch'' instructions are expanded when
+necessary @emph{unless} you specify @code{-norelax}---in which case
+@code{_AS__} gives an error instead.
+
+These are the Compare-and-Branch instructions, their ``Jump'' variants,
+and the instruction pairs they may expand into:
+
+@ifinfo
+@example
+        Compare and
+     Branch      Jump       Expanded to
+     ------    ------       ------------
+        bbc                 chkbit; bno
+        bbs                 chkbit; bo
+     cmpibe    cmpije       cmpi; be
+     cmpibg    cmpijg       cmpi; bg
+    cmpibge   cmpijge       cmpi; bge
+     cmpibl    cmpijl       cmpi; bl
+    cmpible   cmpijle       cmpi; ble
+    cmpibno   cmpijno       cmpi; bno
+    cmpibne   cmpijne       cmpi; bne
+     cmpibo    cmpijo       cmpi; bo
+     cmpobe    cmpoje       cmpo; be
+     cmpobg    cmpojg       cmpo; bg
+    cmpobge   cmpojge       cmpo; bge
+     cmpobl    cmpojl       cmpo; bl
+    cmpoble   cmpojle       cmpo; ble
+    cmpobne   cmpojne       cmpo; bne
+@end example
+@end ifinfo
+@tex
+\hskip\tableindent
+\halign{\hfil {\tt #}\quad&\hfil {\tt #}\qquad&{\tt #}\hfil\cr
+\omit{\hfil\it Compare and\hfil}\span\omit&\cr
+{\it Branch}&{\it Jump}&{\it Expanded to}\cr
+        bbc&                 & chkbit; bno\cr
+        bbs&                 & chkbit; bo\cr
+     cmpibe&    cmpije&       cmpi; be\cr
+     cmpibg&    cmpijg&       cmpi; bg\cr
+    cmpibge&   cmpijge&       cmpi; bge\cr
+     cmpibl&    cmpijl&       cmpi; bl\cr
+    cmpible&   cmpijle&       cmpi; ble\cr
+    cmpibno&   cmpijno&       cmpi; bno\cr
+    cmpibne&   cmpijne&       cmpi; bne\cr
+     cmpibo&    cmpijo&       cmpi; bo\cr
+     cmpobe&    cmpoje&       cmpo; be\cr
+     cmpobg&    cmpojg&       cmpo; bg\cr
+    cmpobge&   cmpojge&       cmpo; bge\cr
+     cmpobl&    cmpojl&       cmpo; bl\cr
+    cmpoble&   cmpojle&       cmpo; ble\cr
+    cmpobne&   cmpojne&       cmpo; bne\cr}
+@end tex
 
-@c   This is no longer true
-@c Explicit size modifiers for branch instructions are ignored; @code{as}
-@c automatically picks the smallest size that will reach the
-destination.
+_fi__(_I960__)
+_if__(_M680X0__)
+@group
+_CHAPSEC__(0+_ALL_ARCH__) M680x0 Dependent Features
+_CHAPSEC__(1+_ALL_ARCH__) M680x0 Options
+The Motorola 680x0 version of @code{_AS__} has two machine dependent options.
+One shortens undefined references from 32 to 16 bits, while the
+other is used to tell @code{_AS__} what kind of machine it is
+assembling for.
+@end group
 
-If @code{as} is compiled with SUN_ASM_SYNTAX defined, it will also
-allow Sun-style local labels of the form @samp{1$} through @samp{$9}.
+You can use the @kbd{-l} option to shorten the size of references to
+undefined symbols.  If the @kbd{-l} option is not given, references to
+undefined symbols will be a full long (32 bits) wide.  (Since @code{_AS__}
+cannot know where these symbols will end up, @code{_AS__} can only allocate
+space for the linker to fill in later.  Since @code{_AS__} doesn't know how
+far away these symbols will be, it allocates as much space as it can.)
+If this option is given, the references will only be one word wide (16
+bits).  This may be useful if you want the object file to be as small as
+possible, and you know that the relevant symbols will be less than 17
+bits away.
+
+The 680x0 version of @code{_AS__} is most frequently used to assemble
+programs for the Motorola MC68020 microprocessor.  Occasionally it is
+used to assemble programs for the mostly similar, but slightly different
+MC68000 or MC68010 microprocessors.  You can give @code{_AS__} the options
+@samp{-m68000}, @samp{-mc68000}, @samp{-m68010}, @samp{-mc68010},
+@samp{-m68020}, and @samp{-mc68020} to tell it what processor is the
+target.
+
+_CHAPSEC__(1+_ALL_ARCH__) Syntax
+
+The 680x0 version of @code{_AS__} uses syntax similar to the Sun assembler.
+Size modifiers are appended directly to the end of the opcode without an
+intervening period.  For example, write @samp{movl} rather than
+@samp{move.l}.
+
+_if__(_INTERNALS__)
+If @code{_AS__} is compiled with SUN_ASM_SYNTAX defined, it will also allow
+Sun-style local labels of the form @samp{1$} through @samp{$9}.
+_fi__(_INTERNALS__)
 
 In the following table @dfn{apc} stands for any of the address
 registers (@samp{a0} through @samp{a7}), nothing, (@samp{}), the
@@ -1874,16 +2982,21 @@ or @samp{@var{apc}@@(@var{register}:@var{size}:@var{scale})@@(@var{digits})}
 @samp{@var{apc}@@(@var{digits})@@(@var{digits})}
 
 @item Absolute
-@samp{@var{symbol}}, or @samp{@var{digits}}, or either of the above followed
+@samp{@var{symbol}}, or @samp{@var{digits}}
+@ignore
+@c pesch@cygnus.com: gnu, rich concur the following needs careful
+@c                             research before documenting.
+                                           , or either of the above followed
 by @samp{:b}, @samp{:w}, or @samp{:l}.
+@end ignore
 @end table
 
-@subsection Floating Point
+_CHAPSEC__(1+_ALL_ARCH__) Floating Point
 The floating point code is not too well tested, and may have
 subtle bugs in it.
 
 Packed decimal (P) format floating literals are not supported.
-Feel free to add the code yourself.
+Feel free to add the code!
 
 The floating point formats generated by directives are these.
 @table @code
@@ -1897,9 +3010,9 @@ There is no directive to produce regions of memory holding
 extended precision numbers, however they can be used as
 immediate operands to floating-point instructions.  Adding a
 directive to create extended precision numbers would not be
-hard.  Nobody has felt any burning need to do it.
+hard, but it has not yet seemed necessary.
 
-@subsection Machine Directives
+_CHAPSEC__(1+_ALL_ARCH__) Machine Directives
 In order to be compatible with the Sun assembler the 680x0 assembler
 understands the following directives.
 @table @code
@@ -1914,25 +3027,121 @@ This directive is identical to a @code{.align 1} directive.
 This directive is identical to a @code{.space} directive.
 @end table
 
-@subsection Opcodes
+_CHAPSEC__(1+_ALL_ARCH__) Opcodes
+@c pesch@cygnus.com: I don't see any point in the following
+@c                   paragraph.  Bugs are bugs; how does saying this
+@c                   help anyone?
+@ignore
 Danger:  Several bugs have been found in the opcode table (and
 fixed).  More bugs may exist.  Be careful when using obscure
 instructions.
+@end ignore
+
+_CHAPSEC__(2+_ALL_ARCH__) Branch Improvement
+
+Certain pseudo opcodes are permitted for branch instructions.
+They expand to the shortest branch instruction that will reach the
+target.  Generally these mnemonics are made by substituting @samp{j} for
+@samp{b} at the start of a Motorola mnemonic.
+
+The following table summarizes the pseudo-operations.  A @code{*} flags
+cases that are more fully described after the table:
 
-The assembler automatically chooses the proper size for branch
-instructions.  However, most attempts to force a short displacement
-will be honored.  Branches that are forced to use a short
-displacement will not be adjusted if the target is out of range.
-Let The User Beware.
+@smallexample
+          Displacement
+          +---------------------------------------------------------
+          |                68020   68000/10
+Pseudo-Op |BYTE    WORD    LONG    LONG      non-PC relative
+          +---------------------------------------------------------
+     jbsr |bsrs    bsr     bsrl    jsr       jsr
+      jra |bras    bra     bral    jmp       jmp
+*     jXX |bXXs    bXX     bXXl    bNXs;jmpl bNXs;jmp
+*    dbXX |dbXX    dbXX        dbXX; bra; jmpl
+*    fjXX |fbXXw   fbXXw   fbXXl             fbNXw;jmp
 
+XX: condition
+NX: negative of condition XX
+
+@end smallexample
+@center{@code{*}---see full description below}
+
+@table @code
+@item jbsr
+@itemx jra
+These are the simplest jump pseudo-operations; they always map to one
+particular machine instruction, depending on the displacement to the
+branch target.
+
+@item j@var{XX}
+Here, @samp{j@var{XX}} stands for an entire family of pseudo-operations,
+where @var{XX} is a conditional branch or condition-code test.  The full
+list of pseudo-ops in this family is:
+@smallexample
+ jhi   jls   jcc   jcs   jne   jeq   jvc
+ jvs   jpl   jmi   jge   jlt   jgt   jle
+@end smallexample
+
+For the cases of non-PC relative displacements and long displacements on
+the 68000 or 68010, @code{_AS__} will issue a longer code fragment in terms of
+@var{NX}, the opposite condition to @var{XX}:
+@smallexample
+    j@var{XX} foo
+@end smallexample
+gives
+@smallexample
+     b@var{NX}s oof
+     jmp foo
+ oof:
+@end smallexample
+
+@item db@var{XX}
+The full family of pseudo-operations covered here is
+@smallexample
+ dbhi   dbls   dbcc   dbcs   dbne   dbeq   dbvc
+ dbvs   dbpl   dbmi   dbge   dblt   dbgt   dble
+ dbf    dbra   dbt
+@end smallexample
+
+Other than for word and byte displacements, when the source reads
+@samp{db@var{XX} foo}, @code{_AS__} will emit
+@smallexample
+     db@var{XX} oo1
+     bra oo2
+ oo1:jmpl foo
+ oo2:
+@end smallexample
+
+@item fj@var{XX}
+This family includes
+@smallexample
+ fjne   fjeq   fjge   fjlt   fjgt   fjle   fjf
+ fjt    fjgl   fjgle  fjnge  fjngl  fjngle fjngt
+ fjnle  fjnlt  fjoge  fjogl  fjogt  fjole  fjolt
+ fjor   fjseq  fjsf   fjsne  fjst   fjueq  fjuge
+ fjugt  fjule  fjult  fjun
+@end smallexample
+
+For branch targets that are not PC relative, @code{_AS__} emits
+@smallexample
+     fb@var{NX} oof
+     jmp foo
+ oof:
+@end smallexample
+when it encounters @samp{fj@var{XX} foo}.
+
+@end table
+
+_CHAPSEC__(2+_ALL_ARCH__) Special Characters
 The immediate character is @samp{#} for Sun compatibility.  The
 line-comment character is @samp{|}.  If a @samp{#} appears at the
 beginning of a line, it is treated as a comment unless it looks like
 @samp{# line file}, in which case it is treated normally.
-
+_fi__(_M680X0__)
+@c pesch@cygnus.com: conditionalize on something other than 0 when filled in.
+_if__(0)
 @section 32x32
-@subsection Options
-The 32x32 version of @code{as} accepts a @kbd{-m32032} option to
+@section Options
+The 32x32 version of @code{_AS__} accepts a @kbd{-m32032} option to
 specify thiat it is compiling for a 32032 processor, or a
 @kbd{-m32532} to specify that it is compiling for a 32532 option.
 The default (if neither is specified) is chosen when the assembler
@@ -1940,17 +3149,20 @@ is compiled.
 
 @subsection Syntax
 I don't know anything about the 32x32 syntax assembled by
-@code{as}.  Someone who undersands the processor (I've never seen
+@code{_AS__}.  Someone who undersands the processor (I've never seen
 one) and the possible syntaxes should write this section.
 
 @subsection Floating Point
-The 32x32 uses IEEE floating point numbers, but @code{as} will only
+The 32x32 uses IEEE floating point numbers, but @code{_AS__} will only
 create single or double precision values.  I don't know if the 32x32
 understands extended precision numbers.
 
 @subsection Machine Directives
 The 32x32 has no machine dependent directives.
-
+_fi__(0)
+_if__(_SPARC__)
+@c fixme (sparc): Fill in "syntax" section!
+_CHAPSEC__(0+_ALL_ARCH__) SPARC Dependent Features
 @section Sparc
 @subsection Options
 The sparc has no machine dependent options.
@@ -1963,7 +3175,7 @@ will have to write this section.
 The Sparc uses ieee floating-point numbers.
 
 @subsection Machine Directives
-The Sparc version of @code{as} supports the following additional
+The Sparc version of @code{_AS__} supports the following additional
 machine directives:
 
 @table @code
@@ -2000,14 +3212,15 @@ On the Sparc, the .word directive produces 32 bit values,
 instead of the 16 bit values it produces on every other machine.
 
 @end table
-
-@section Intel 80386
-@subsection Options
+_fi__(_SPARC__)
+_if__(_I80386__)
+_CHAPSEC__(0+_ALL_ARCH__) 80386 Dependent Features
+_CHAPSEC__(1+_ALL_ARCH__) Options
 The 80386 has no machine dependent options.
 
-@subsection AT&T Syntax versus Intel Syntax
-In order to maintain compatibility with the output of @code{GCC},
-@code{as} supports AT&T System V/386 assembler syntax.  This is quite
+_CHAPSEC__(1+_ALL_ARCH__) AT&T Syntax versus Intel Syntax
+In order to maintain compatibility with the output of @code{_GCC__},
+@code{_AS__} supports AT&T System V/386 assembler syntax.  This is quite
 different from Intel syntax.  We mention these differences because
 almost all 80386 documents used only Intel syntax.  Notable differences
 between the two syntaxes are:
@@ -2039,7 +3252,7 @@ Immediate form long jumps and calls are
 @samp{lcall/ljmp $@var{segment}, $@var{offset}} in AT&T syntax; the
 Intel syntax is
 @samp{call/jmp far @var{segment}:@var{offset}}.  Also, the far return
-instruction 
+instruction
 is @samp{lret $@var{stack-adjust}} in AT&T syntax; Intel syntax is
 @samp{ret far @var{stack-adjust}}.
 
@@ -2048,11 +3261,11 @@ The AT&T assembler does not provide support for multiple segment
 programs.  Unix style systems expect all programs to be single segments.
 @end itemize
 
-@subsection Opcode Naming
+_CHAPSEC__(1+_ALL_ARCH__) Opcode Naming
 Opcode names are suffixed with one character modifiers which specify the
 size of operands.  The letters @samp{b}, @samp{w}, and @samp{l} specify
 byte, word, and long operands.  If no suffix is specified by an
-instruction and it contains no memory operands then @code{as} tries to
+instruction and it contains no memory operands then @code{_AS__} tries to
 fill in the missing suffix based on the destination register operand
 (the last one by convention).  Thus, @samp{mov %ax, %bx} is equivalent
 to @samp{movw %ax, %bx}; also, @samp{mov $1, %bx} is equivalent to
@@ -2086,13 +3299,13 @@ The Intel syntax conversion instructions
 @samp{cdq} --- sign-extend dword in @samp{%eax} to quad in @samp{%edx:%eax},
 @end itemize
 are called @samp{cbtw}, @samp{cwtl}, @samp{cwtd}, and @samp{cltd} in
-AT&T naming.  @code{as} accepts either naming for these instructions.
+AT&T naming.  @code{_AS__} accepts either naming for these instructions.
 
 Far call/jump instructions are @samp{lcall} and @samp{ljmp} in
 AT&T syntax, but are @samp{call far} and @samp{jump far} in Intel
-convention.  
+convention.
 
-@subsection Register Naming
+_CHAPSEC__(1+_ALL_ARCH__) Register Naming
 Register operands are always prefixes with @samp{%}.  The 80386 registers
 consist of
 @itemize @bullet
@@ -2133,7 +3346,7 @@ the 8 floating point register stack @samp{%st} or equivalently
 @samp{%st(4)}, @samp{%st(5)}, @samp{%st(6)}, and @samp{%st(7)}.
 @end itemize
 
-@subsection Opcode Prefixes
+_CHAPSEC__(1+_ALL_ARCH__) Opcode Prefixes
 Opcode prefixes are used to modify the following opcode.  They are used
 to repeat string instructions, to provide segment overrides, to perform
 bus lock operations, and to give operand and address size (16-bit
@@ -2142,10 +3355,10 @@ normally be 32-bit operands with a ``operand size'' opcode prefix).
 Opcode prefixes are usually given as single-line instructions with no
 operands, and must directly precede the instruction they act upon.  For
 example, the @samp{scas} (scan string) instruction is repeated with:
-@example
+@smallexample
        repne
        scas
-@end example
+@end smallexample
 
 Here is a list of opcode prefixes:
 @itemize @bullet
@@ -2175,15 +3388,15 @@ The @samp{rep}, @samp{repe}, and @samp{repne} prefixes are added
 to string instructions to make them repeat @samp{%ecx} times.
 @end itemize
 
-@subsection Memory References
+_CHAPSEC__(1+_ALL_ARCH__) Memory References
 An Intel syntax indirect memory reference of the form
-@example
+@smallexample
 @var{segment}:[@var{base} + @var{index}*@var{scale} + @var{disp}]
-@end example
+@end smallexample
 is translated into the AT&T syntax
-@example
+@smallexample
 @var{segment}:@var{disp}(@var{base}, @var{index}, @var{scale})
-@end example
+@end smallexample
 where @var{base} and @var{index} are the optional 32-bit base and
 index registers, @var{disp} is the optional displacement, and
 @var{scale}, taking the values 1, 2, 4, and 8, multiplies @var{index}
@@ -2193,7 +3406,7 @@ optional segment register for the memory operand, and may override the
 default segment register (see a 80386 manual for segment register
 defaults). Note that segment overrides in AT&T syntax @emph{must} have
 be preceded by a @samp{%}.  If you specify a segment override which
-coincides with the default segment register, @code{as} will @emph{not}
+coincides with the default segment register, @code{_AS__} will @emph{not}
 output any segment register override prefixes to assemble the given
 instruction.  Thus, segment overrides can be specified to emphasize which
 segment register is used for a given memory operand.
@@ -2219,18 +3432,18 @@ Note that @var{base} and @var{index} are both missing, but there is only
 @item AT&T: @samp{%gs:foo}; Intel @samp{gs:foo}
 This selects the contents of the variable @samp{foo} with segment
 register @var{segment} being @samp{%gs}.
-       
+
 @end table
 
 Absolute (as opposed to PC relative) call and jump operands must be
-prefixed with @samp{*}.  If no @samp{*} is specified, @code{as} will
-always choose PC relative addressing for jump/call labels.  
+prefixed with @samp{*}.  If no @samp{*} is specified, @code{_AS__} will
+always choose PC relative addressing for jump/call labels.
 
 Any instruction that has a memory operand @emph{must} specify its size (byte,
 word, or long) with an opcode suffix (@samp{b}, @samp{w}, or @samp{l},
 respectively).
 
-@subsection Handling of Jump Instructions
+_CHAPSEC__(1+_ALL_ARCH__) Handling of Jump Instructions
 Jump instructions are always optimized to use the smallest possible
 displacements.  This is accomplished by using byte (8-bit) displacement
 jumps whenever the target is sufficiently close.  If a byte displacement
@@ -2242,17 +3455,17 @@ with the @samp{addr16} opcode prefix), since the 80386 insists upon masking
 Note that the @samp{jcxz}, @samp{jecxz}, @samp{loop}, @samp{loopz},
 @samp{loope}, @samp{loopnz} and @samp{loopne} instructions only come in
 byte displacements, so that it is possible that use of these
-instructions (@code{GCC} does not use them) will cause the assembler to
+instructions (@code{_GCC__} does not use them) will cause the assembler to
 print an error message (and generate incorrect code).  The AT&T 80386
 assembler tries to get around this problem by expanding @samp{jcxz foo} to
-@example
+@smallexample
          jcxz cx_zero
          jmp cx_nonzero
 cx_zero: jmp foo
 cx_nonzero:
-@end example
+@end smallexample
 
-@subsection Floating Point
+_CHAPSEC__(1+_ALL_ARCH__) Floating Point
 All 80387 floating point types except packed BCD are supported.
 (BCD support may be added without much difficulty).  These data
 types are 16-, 32-, and 64- bit integers, and single (32-bit),
@@ -2284,21 +3497,21 @@ so that @samp{fst %st, %st(1)} is equivalent to @samp{fstl %st, %st(1)}.
 
 Since the 80387 automatically synchronizes with the 80386 @samp{fwait}
 instructions are almost never needed (this is not the case for the
-80286/80287 and 8086/8087 combinations).  Therefore, @code{as} supresses
+80286/80287 and 8086/8087 combinations).  Therefore, @code{_AS__} suppresses
 the @samp{fwait} instruction whenever it is implicitly selected by one
 of the @samp{fn@dots{}} instructions.  For example, @samp{fsave} and
 @samp{fnsave} are treated identically.  In general, all the @samp{fn@dots{}}
 instructions are made equivalent to @samp{f@dots{}} instructions.  If
 @samp{fwait} is desired it must be explicitly coded.
 
-@subsection Notes
+_CHAPSEC__(1+_ALL_ARCH__) Notes
 There is some trickery concerning the @samp{mul} and @samp{imul}
 instructions that deserves mention.  The 16-, 32-, and 64-bit expanding
 multiplies (base opcode @samp{0xf6}; extension 4 for @samp{mul} and 5
 for @samp{imul}) can be output only in the one operand form.  Thus,
 @samp{imul %ebx, %eax} does @emph{not} select the expanding multiply;
 the expanding multiply would clobber the @samp{%edx} register, and this
-would confuse @code{GCC} output.  Use @samp{imul %ebx} to get the
+would confuse @code{_GCC__} output.  Use @samp{imul %ebx} to get the
 64-bit product in @samp{%edx:%eax}.
 
 We have added a two operand form of @samp{imul} when the first operand
@@ -2306,8 +3519,13 @@ is an immediate mode expression and the second operand is a register.
 This is just a shorthand, so that, multiplying @samp{%eax} by 69, for
 example, can be done with @samp{imul $69, %eax} rather than @samp{imul
 $69, %eax, %eax}.
-
-@node Maintenance, Retargeting, MachineDependent, top
+_fi__(_I80386__)
+_if__(0)
+@c pesch@cygnus.com: we ignore the following chapters, since internals are
+@c                   changing rapidly.  These may need to be moved to another
+@c                   book anyhow, if we adopt the model of user/modifier
+@c                   books.
+@node Maintenance, Retargeting, _MACH_DEP__, Top
 @chapter Maintaining the Assembler
 [[this chapter is still being built]]
 
@@ -2315,13 +3533,13 @@ $69, %eax, %eax}.
 We had these goals, in descending priority:
 @table @b
 @item Accuracy.
-For every program composed by a compiler, @code{as} should emit
+For every program composed by a compiler, @code{_AS__} should emit
 ``correct'' code.  This leaves some latitude in choosing addressing
 modes, order of @code{relocation_info} structures in the object
-file, @i{etc}.
+file, @emph{etc}.
 
 @item Speed, for usual case.
-By far the most common use of @code{as} will be assembling compiler
+By far the most common use of @code{_AS__} will be assembling compiler
 emissions.
 
 @item Upward compatibility for existing assembler code.
@@ -2356,7 +3574,7 @@ large buffers.
 
 RMS suggested a one-pass algorithm which seems to work well.  By not
 parsing text during a second pass considerable time is saved on
-large programs (@i{e.g.} the sort of C program @code{yacc} would
+large programs (@emph{e.g.} the sort of C program @code{yacc} would
 emit).
 
 It happened that the data structures needed to emit relocation
@@ -2367,7 +3585,7 @@ Many of the functions began life as re-usable modules, loosely
 connected.  RMS changed this to gain speed.  For example, input
 parsing routines which used to work on pre-sanitized strings now
 must parse raw data.  Hence they have to import knowledge of the
-assemblers' comment conventions @i{etc}.
+assemblers' comment conventions @emph{etc}.
 
 @section Deprecated Feature(?)s
 We have stopped supporting some features:
@@ -2396,22 +3614,22 @@ interpret binary gobbledygook from a compiler's tables than to
 ask the compiler to write out human-readable code just so the
 assembler can parse it back to binary.
 
-Assuming you use @code{as} for human written programs: here are
+Assuming you use @code{_AS__} for human written programs: here are
 some ideas:
 @itemize @bullet
 @item
 Document (here) @code{APP}.
 @item
 Take advantage of knowing no spaces except after opcode
-to speed up @code{as}.  (Modify @code{app.c} to flush useless spaces:
+to speed up @code{_AS__}.  (Modify @code{app.c} to flush useless spaces:
 only keep space/tabs at begin of line or between 2
 symbols.)
 @item
 Put pointers in this documentation to @file{a.out} documentation.
 @item
 Split the assembler into parts so it can gobble direct binary
-from @i{e.g.} @code{cc}.  It is silly for@code{cc} to compose text
-just so @code{as} can parse it back to binary.
+from @emph{e.g.} @code{cc}.  It is silly for@code{cc} to compose text
+just so @code{_AS__} can parse it back to binary.
 @item
 Rewrite hash functions: I want a more modular, faster library.
 @item
@@ -2424,7 +3642,7 @@ Document flonums.
 Implement flonum short literals.
 @item
 Change all talk of expression operands to expression quantities,
-or perhaps to expression primaries.
+or perhaps to expression arguments.
 @item
 Implement pass 2.
 @item
@@ -2440,7 +3658,7 @@ relaxable addresses, which is common).
 @end itemize
 
 @section Sources
-@c The following files in the @file{as} directory
+@c The following files in the @file{_AS__} directory
 @c are symbolic links to other files, of
 @c the same name, in a different directory.
 @c @itemize @bullet
@@ -2462,7 +3680,7 @@ relaxable addresses, which is common).
 @c @file{flonum_print.c}
 @c @end itemize
 
-Here is a list of the source files in the @file{as} directory.
+Here is a list of the source files in the @file{_AS__} directory.
 
 @table @file
 @item app.c
@@ -2476,14 +3694,14 @@ pointer just after the last @code{char} appended.  (JF:  All these
 little routines should probably all be put in one file.)
 
 @item as.c
-Here you will find the main program of the assembler @code{as}.
+Here you will find the main program of the assembler @code{_AS__}.
 
 @item expr.c
 This is a branch office of @file{read.c}.  This understands
-expressions, primaries.  Inside @code{as}, primaries are called
-(expression) @i{operands}.  This is confusing, because we also talk
-(elsewhere) about instruction @i{operands}.  Also, expression
-operands are called @i{quantities} explicitly to avoid confusion
+expressions, arguments.  Inside @code{_AS__}, arguments are called
+(expression) @emph{operands}.  This is confusing, because we also talk
+(elsewhere) about instruction @emph{operands}.  Also, expression
+operands are called @emph{quantities} explicitly to avoid confusion
 with instruction operands.  What a mess.
 
 @item frags.c
@@ -2491,7 +3709,7 @@ This implements the @b{frag} concept.  Without frags, finding the
 right size for branch instructions would be a lot harder.
 
 @item hash.c
-This contains the symbol table, opcode table @i{etc.} hashing
+This contains the symbol table, opcode table @emph{etc.} hashing
 functions.
 
 @item hex_value.c
@@ -2502,7 +3720,7 @@ something similar.
 @item input-file.c
 This contains Operating system dependent source file reading
 routines.  Since error messages often say where we are in reading
-the source file, they live here too.  Since @code{as} is intended to
+the source file, they live here too.  Since @code{_AS__} is intended to
 run under GNU and Unix only, this might be worth flushing.  Anyway,
 almost all C compilers support stdio.
 
@@ -2516,10 +3734,10 @@ warning message reporting.  See @file{append.c} above.
 
 @item output-file.c
 This contains operating system dependent functions that write an
-object file for @code{as}.  See @file{input-file.c} above.
+object file for @code{_AS__}.  See @file{input-file.c} above.
 
 @item read.c
-This implements all the directives of @code{as}.  This also deals
+This implements all the directives of @code{_AS__}.  This also deals
 with passing input lines to the machine dependent part of the
 assembler.
 
@@ -2577,7 +3795,7 @@ be identical to the one used by GDB (which uses it for disassembly.)
 
 @item atof-ieee.c
 This contains code to turn a flonum into a ieee literal constant.
-This is used by tye 680x0, 32x32, sparc, and i386 versions of @code{as}.
+This is used by tye 680x0, 32x32, sparc, and i386 versions of @code{_AS__}.
 
 @item i386-opcode.h
 This is the opcode-table for the i386 version of the assembler.
@@ -2634,7 +3852,7 @@ Vax specific file for describing Vax operands and other Vax-ish things.
 Vax opcode table.
 
 @item vax.c
-Vax specific parts of @code{as}.  Also includes the former files
+Vax specific parts of @code{_AS__}.  Also includes the former files
 @file{vax-ins-parse.c}, @file{vax-reg-parse.c} and @file{vip-op.c}.
 
 @item atof-vax.c
@@ -2660,8 +3878,8 @@ inside the object file.  Perhaps we should use the one in
 @file{/usr/include}?
 
 @item as.h
-This defines all the globally useful things, and pulls in <stdio.h>
-and <assert.h>.
+This defines all the globally useful things, and pulls in _0__<stdio.h>_1__
+and _0__<assert.h>_1__.
 
 @item bignum.h
 This defines macros useful for dealing with bignums.
@@ -2694,7 +3912,7 @@ Since nobody is running under real GNU yet, we include this file.
 Macros and function headers for reading in source files.
 
 @item struct-symbol.h
-Structure definition and macros for dealing with the gas
+Structure definition and macros for dealing with the _AS__
 internal form of a symbol.
 
 @item subsegs.h
@@ -2712,40 +3930,40 @@ Structure for doing segment fixups.
 @comment (Note:  The test directory seems to have disappeared somewhere
 @comment along the line.  If you want it, you'll probably have to find a
 @comment REALLY OLD dump tape~dots{})
-@comment 
+@comment
 @comment The ~file{test/} directory is used for regression testing.
-@comment After you modify ~code{as}, you can get a quick go/nogo
-@comment confidence test by running the new ~code{as} over the source
+@comment After you modify ~@code{_AS__}, you can get a quick go/nogo
+@comment confidence test by running the new ~@code{_AS__} over the source
 @comment files in this directory.  You use a shell script ~file{test/do}.
-@comment 
+@comment
 @comment The tests in this suite are evolving.  They are not comprehensive.
 @comment They have, however, caught hundreds of bugs early in the debugging
-@comment cycle of ~code{as}.  Most test statements in this suite were naturally
-@comment selected: they were used to demonstrate actual ~code{as} bugs rather
+@comment cycle of ~@code{_AS__}.  Most test statements in this suite were naturally
+@comment selected: they were used to demonstrate actual ~@code{_AS__} bugs rather
 @comment than being written ~i{a prioi}.
-@comment 
+@comment
 @comment Another testing suggestion: over 30 bugs have been found simply by
-@comment running examples from this manual through ~code{as}.
+@comment running examples from this manual through ~@code{_AS__}.
 @comment Some examples in this manual are selected
-@comment to distinguish boundary conditions; they are good for testing ~code{as}.
-@comment 
+@comment to distinguish boundary conditions; they are good for testing ~@code{_AS__}.
+@comment
 @comment ~subsubsection Regression Testing
 @comment Each regression test involves assembling a file and comparing the
-@comment actual output of ~code{as} to ``known good'' output files.  Both
+@comment actual output of ~@code{_AS__} to ``known good'' output files.  Both
 @comment the object file and the error/warning message file (stderr) are
-@comment inspected.  Optionally ~code{as}' exit status may be checked.
+@comment inspected.  Optionally the ~@code{_AS__} exit status may be checked.
 @comment Discrepencies are reported.  Each discrepency means either that
-@comment you broke some part of ~code{as} or that the ``known good'' files
+@comment you broke some part of ~@code{_AS__} or that the ``known good'' files
 @comment are now out of date and should be changed to reflect the new
 @comment definition of ``good''.
-@comment 
+@comment
 @comment Each regression test lives in its own directory, in a tree
 @comment rooted in the directory ~file{test/}.  Each such directory
 @comment has a name ending in ~file{.ret}, where `ret' stands for
 @comment REgression Test.  The ~file{.ret} ending allows ~code{find
 @comment (1)} to find all regression tests in the tree, without
 @comment needing to list them explicitly.
-@comment 
+@comment
 @comment Any ~file{.ret} directory must contain a file called
 @comment ~file{input} which is the source file to assemble.  During
 @comment testing an object file ~file{output} is created, as well as
@@ -2756,17 +3974,17 @@ Structure for doing segment fixups.
 @comment deleted.  Likewise ~file{stdouterr} is removed if it exactly
 @comment matches a file ~file{stdouterr.good}.  If file
 @comment ~file{status.good} is present, containing a decimal number
-@comment before a newline, the exit status of ~code{as} is compared
+@comment before a newline, the exit status of ~@code{_AS__} is compared
 @comment to this number.  If the status numbers are not equal, a file
 @comment ~file{status} is written to the directory, containing the
 @comment actual status as a decimal number followed by newline.
-@comment 
+@comment
 @comment Should any of the ~file{*.good} files fail to match their corresponding
 @comment actual files, this is noted by a 1-line message on the screen during
-@comment the regression test, and you can use ~code{find (1)} to find any
+@comment the regression test, and you can use ~@code{find (1)} to find any
 @comment files named ~file{status}, ~file {output} or ~file{stdouterr}.
-@comment 
-@node Retargeting, , Maintenance, top
+@comment
+@node Retargeting, License, Maintenance, Top
 @chapter Teaching the Assembler about a New Machine
 
 This chapter describes the steps required in order to make the
@@ -2782,16 +4000,16 @@ you can compile your new version of the assembler.  This should
 be straighforward; simply add lines similar to the ones there
 for the four current versions of the assembler.
 
-If you want to be compatable with GDB, (and the current
+If you want to be compatible with GDB, (and the current
 machine-dependent versions of the assembler), you should create
 a file called @file{@var{machine}-opcode.h} which should
 contain all the information about the names of the machine
 instructions, their opcodes, and what addressing modes they
 support.  If you do this right, the assembler and GDB can share
 this file, and you'll only have to write it once.  Note that
-while you're writing @code{as}, you may want to use an
+while you're writing @code{_AS__}, you may want to use an
 independent program (if you have access to one), to make sure
-that @code{as} is emitting the correct bytes.  Since @code{as}
+that @code{_AS__} is emitting the correct bytes.  Since @code{_AS__}
 and @code{GDB} share the opcode table, an incorrect opcode
 table entry may make invalid bytes look OK when you disassemble
 them with @code{GDB}.
@@ -2818,7 +4036,7 @@ start a comment anywhere in a line.  Comments are stripped off
 automatically by the machine independent part of the
 assembler.  Note that the @samp{/*} will always start a
 comment, and that only @samp{*/} will end a comment started by
-@samp{*/}.  
+@samp{*/}.
 
 @item char line_comment_chars[];
 This character array holds the values of the chars that start a
@@ -2855,7 +4073,7 @@ any of your other routines.
 
 @item int md_parse_option(char **optionPTR, int *argcPTR, char ***argvPTR)
 This routine is called once for each option on the command line
-that the machine-independent part of @code{as} does not
+that the machine-independent part of @code{_AS__} does not
 understand.  This function should return non-zero if the option
 pointed to by @var{optionPTR} is a valid option.  If it is not
 a valid option, this routine should return zero.  The variables
@@ -3055,7 +4273,7 @@ This function stores a relocation fixup to be acted on later.
 @var{size} is the size of the relocation, and is usually 1 (a single byte),
   2 (sixteen bits), or 4 (a longword).
 The value @var{add_symbol} @minus{} @var{sub_symbol} + @var{offset}, is added to the byte(s)
-at @var{frag->literal[where]}.  If @var{pcrel} is non-zero, the address of the
+at _0__@var{frag->literal[where]}_1__.  If @var{pcrel} is non-zero, the address of the
 location is subtracted from the result.  A relocation entry is also added
 to the @file{a.out} file.  @var{add_symbol}, @var{sub_symbol}, and/or
 @var{offset} may be NULL.@refill
@@ -3098,8 +4316,8 @@ line number, then uses @code{fprintf} to print the
 @var{message} and any arguments it was passed.
 
 @item as_bad(char *message,@dots{})
-This function should be called when @code{as} encounters
-conditions that are bad enough that @code{as} should not
+This function should be called when @code{_AS__} encounters
+conditions that are bad enough that @code{_AS__} should not
 produce an object file, but should continue reading input and
 printing warning and bad error messages.
 
@@ -3138,10 +4356,10 @@ modes.  (e.g. branch instructions) This means the size of many
 pieces of object code cannot be determined until after assembly
 is finished.  (This means that the addresses of symbols cannot be
 determined until assembly is finished.)  In order to do this,
-@code{as} stores the output bytes as @dfn{frags}.
+@code{_AS__} stores the output bytes as @dfn{frags}.
 
 Here is the definition of a frag (from @file{as.h})
-@example
+@smallexample
 struct frag
 @{
         long int fr_fix;
@@ -3155,7 +4373,7 @@ struct frag
         struct frag *fr_next;
         char fr_literal[];
 @}
-@end example
+@end smallexample
 
 @table @var
 @item fr_fix
@@ -3209,19 +4427,315 @@ actual object bytes.  A frag consists of a fixed size piece of
 object data, (which may be zero bytes long), followed by a
 piece of object data whose size may not have been determined
 yet.  Other information includes the type of the frag (which
-controls how it is relaxed), 
+controls how it is relaxed),
 
 @item fr_next
 This is the next frag in the singly-linked list.  This is
 usually only needed by the machine-independent part of
-@code{as}.
+@code{_AS__}.
 
 @end table
+_fi__(0)
+
+@node License,  , Retargeting, Top
+@unnumbered GNU GENERAL PUBLIC LICENSE
+@center Version 1, February 1989
+
+@display
+Copyright @copyright{} 1989 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software---to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS
+@end ifinfo
+
+@enumerate
+@item
+This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+``Program'', below, refers to any such program or work, and a ``work based
+on the Program'' means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as ``you''.
+
+@item
+You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+@item
+You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+@itemize @bullet
+@item
+cause the modified files to carry prominent notices stating that
+you changed the files and the date of any change; and
+
+@item
+cause the whole of any work that you distribute or publish, that
+in whole or in part contains the Program or any part thereof, either
+with or without modifications, to be licensed at no charge to all
+third parties under the terms of this General Public License (except
+that you may choose to grant warranty protection to some or all
+third parties, at your option).
+
+@item
+If the modified program normally reads commands interactively when
+run, you must cause it, when started running for such interactive use
+in the simplest and most usual way, to print or display an
+announcement including an appropriate copyright notice and a notice
+that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these
+conditions, and telling the user how to view a copy of this General
+Public License.
+
+@item
+You may charge a fee for the physical act of transferring a
+copy, and you may at your option offer warranty protection in
+exchange for a fee.
+@end itemize
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+@item
+You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+@itemize @bullet
+@item
+accompany it with the complete corresponding machine-readable
+source code, which must be distributed under the terms of
+Paragraphs 1 and 2 above; or,
+
+@item
+accompany it with a written offer, valid for at least three
+years, to give any third party free (except for a nominal charge
+for the cost of distribution) a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of
+Paragraphs 1 and 2 above; or,
+
+@item
+accompany it with the information you received as to where the
+corresponding source code may be obtained.  (This alternative is
+allowed only for noncommercial distribution and only if you
+received the program in object code or executable form alone.)
+@end itemize
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+@item
+You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+@item
+By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+@item
+Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+@item
+The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and ``any
+later version'', you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+@item
+If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+@item
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
+LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES
+SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
+WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+@end enumerate
 
-@c Is this really a good idea?
 @iftex
-@center [end of manual]
+@heading END OF TERMS AND CONDITIONS
 @end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+@page
+@unnumberedsec Applying These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+``copyright'' line and a pointer to where the full notice is found.
+
+@smallexample
+@var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) 19@var{yy}  @var{name of author}
+
+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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+@end smallexample
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items---whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a ``copyright disclaimer'' for the program, if
+necessary.  Here is a sample; alter the names:
+
+@smallexample
+Yoyodyne, Inc., hereby disclaims all copyright interest in the
+program `Gnomovision' (a program to direct compilers to make passes
+at assemblers) written by James Hacker.
+
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end smallexample
+
+That's all there is to it!
+
+
 @summarycontents
 @contents
 @bye
diff --git a/gas/doc/i80386.m4 b/gas/doc/i80386.m4
new file mode 100644 (file)
index 0000000..d8293d1
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_I80386__>,<1>)
+_define__(<_HOST__>,<Intel 80386>)
+_define__(<_MACH_DEP__>,<80386 Dependent>
+_divert__<>
\ No newline at end of file
diff --git a/gas/doc/i960.m4 b/gas/doc/i960.m4
new file mode 100644 (file)
index 0000000..e98155d
--- /dev/null
@@ -0,0 +1,12 @@
+_divert__(-1)
+_define__(<_I960__>,<1>)
+_define__(<_AOUT__>,<0>)
+_define__(<_BOUT__>,<1>)
+_define__(<_COFF__>,<1>)
+_define__(<_AS__>,<gas960>)
+_define__(<_GCC__>,<gcc960>)
+_define__(<_LD__>,<gld960>)
+_define__(<_GDB__>,<gdb960>)
+_define__(<_HOST__>,<Intel 960>)
+_define__(<_MACH_DEP__>,<i960 Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gas/doc/m680x0.m4 b/gas/doc/m680x0.m4
new file mode 100644 (file)
index 0000000..e5f83b6
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_M680X0__>,<1>)
+_define__(<_HOST__>,<Motorola 680x0>)
+_define__(<_MACH_DEP__>,<M680x0 Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gas/doc/none.m4 b/gas/doc/none.m4
new file mode 100644 (file)
index 0000000..327ef3e
--- /dev/null
@@ -0,0 +1,36 @@
+_divert__(-1)
+
+Switches:
+
+_define__(<_ALL_ARCH__>,<0>)
+_define__(<_INTERNALS__>,<0>)
+
+_define__(<_AOUT__>,<1>)
+_define__(<_BOUT__>,<0>)
+_define__(<_COFF__>,<0>)
+_define__(<_ELF__>,<0>)
+
+_define__(<_AMD29K__>,<0>)
+_define__(<_I80386__>,<0>)
+_define__(<_I960__>,<0>)
+_define__(<_M680X0__>,<0>)
+_define__(<_SPARC__>,<0>)
+_define__(<_VAX__>,<0>)
+
+Text:
+
+Default names for assembler, compiler, linker, debugger; 
+       individual configs may override
+_define__(<_AS__>,<as>)
+_define__(<_GCC__>,<gcc>)
+_define__(<_LD__>,<ld>)
+_define__(<_GDB__>,<gdb>)
+
+Text for host; individual configs *should* override, but this may
+catch some flubs
+_define__(<_HOST__>,<machine specific>)
+
+"Machine Dependent" nodename
+_define__(<_MACH_DEP__>,<Machine Dependent>)
+
+_divert__<>
\ No newline at end of file
diff --git a/gas/doc/pretex.m4 b/gas/doc/pretex.m4
new file mode 100644 (file)
index 0000000..3fe9e05
--- /dev/null
@@ -0,0 +1,252 @@
+divert(-1)                             -*-Text-*-
+
+I. INTRODUCTION
+
+This collection of M4 macros is meant to help in pre-processing texinfo
+files to allow configuring them by hosts; for example, the reader of an
+as manual who only has access to a 386 may not really want to see crud about 
+VAXen. 
+
+A preprocessor is used, rather than extending texinfo, because this
+way we can hack the conditionals in only one place; otherwise we would
+have to write TeX macros, update makeinfo, and update the Emacs
+info-formatting functions.
+
+II. COMPATIBILITY
+
+These macros should work with GNU m4 and System V m4; they do not work
+with Sun or Berkeley M4.
+
+III. USAGE
+
+A. M4 INVOCATION
+Assume this file is called "pretex.m4".  Then, to preprocess a
+document "mybook.texinfo" you might do something like the following:
+
+       m4 pretex.m4 none.m4 PARTIC.m4 mybook.texinfo >mybook-PARTIC.texinfo
+
+---where your path is set to find GNU or SysV "m4", and the other m4
+files mentioned are as follows:
+
+       none.m4: A file that defines, as 0, all the options you might
+               want to turn on using the conditionals defined below.
+               Unlike the C preprocessor, m4 does not default
+               undefined macros to 0.  For example, here is a "none.m4"
+               I have been using:
+           _divert__(-1)
+
+           _define__(<_ALL_ARCH__>,<0>)
+           _define__(<_INTERNALS__>,<0>)
+
+           _define__(<_AMD29K__>,<0>)
+           _define__(<_I80386__>,<0>)
+           _define__(<_I960__>,<0>)
+           _define__(<_M680X0__>,<0>)
+           _define__(<_SPARC__>,<0>)
+           _define__(<_VAX__>,<0>)
+
+           _divert__<>
+
+       PARTIC.m4: A file that turns on whichever options you actually
+               want the manual configured for, in this particular
+               instance.  Its contents are similar to one or more of
+               the lines in "none.m4", but of course the second
+               argument to _define__ is <1> rather than <0>.
+
+               This is also a convenient place to define any macros
+               that you want to expand to different text for
+               different configurations---for example, the name of
+               the program being described.
+
+Naturally, these are just suggested conventions; you could put your macro
+definitions in any files or combinations of files you like.
+
+These macros use the characters < and > as m4 quotes; if you need
+these characters in your text, you will also want to use the macros
+_0__ and _1__ from this package---see the description of "Quote
+Handling" in the "Implementation" section below.
+
+B. WHAT GOES IN THE PRE-TEXINFO SOURCE
+
+For the most part, the text of your book.  In addition, you can
+include text that is included only conditionally, using the macros
+_if__ and _fi__ defined below.  They BOTH take an argument!  This is
+primarily meant for readability (so a human can more easily see what
+conditional end matches what conditional beginning), but the argument
+is actually used in the _fi__ as well as the _if__ implementation.
+You should always give a _fi__ the same argument as its matching
+_if__.  Other arguments may appear to work for a while, but are almost
+certain to produce the wrong output for some configurations.
+
+For example, here is an excerpt from the very beginning of the
+documentation for GNU as, to name the info file appropriately for
+different configurations:
+    _if__(_ALL_ARCH__)
+    @setfilename as.info
+    _fi__(_ALL_ARCH__)
+    _if__(_M680X0__ && !_ALL_ARCH__)
+    @setfilename as-m680x0.info
+    _fi__(_M680X0__ && !_ALL_ARCH__)
+    _if__(_AMD29K__ && !_ALL_ARCH__)
+    @setfilename as-29k.info
+    _fi__(_AMD29K__ && !_ALL_ARCH__) 
+
+Note that you can use Boolean expressions in the arguments; the
+expression language is that of the builtin m4 macro "eval", described
+in the m4 manual.
+
+IV. IMPLEMENTATION
+
+A.PRIMITIVE RENAMING
+First, we redefine m4's built-ins to avoid conflict with plain text.
+The naming convention used is that our macros all begin with a single
+underbar and end with two underbars.  The asymmetry is meant to avoid
+conflict with some other conventions (which we may want to document) that
+are intended to avoid conflict, like ANSI C predefined macros.
+
+define(`_undefine__',defn(`undefine'))
+define(`_define__',defn(`define'))
+define(`_defn__',defn(`defn'))
+define(`_ppf__',`_define__(`_$1__',_defn__(`$1'))_undefine__(`$1')')
+_ppf__(`builtin')
+_ppf__(`changecom')
+_ppf__(`changequote')
+_ppf__(`decr')
+_ppf__(`define')
+_ppf__(`defn')
+_ppf__(`divert')
+_ppf__(`dnl')
+_ppf__(`dumpdef')
+_ppf__(`errprint')
+_ppf__(`eval')
+_ppf__(`ifdef')
+_ppf__(`ifelse')
+_ppf__(`include')
+_ppf__(`incr')
+_ppf__(`index')
+_ppf__(`len')
+_ppf__(`m4exit')
+_ppf__(`m4wrap')
+_ppf__(`maketemp')
+_ppf__(`popdef')
+_ppf__(`pushdef')
+_ppf__(`shift')
+_ppf__(`sinclude')
+_ppf__(`substr')
+_ppf__(`syscmd')
+_ppf__(`sysval')
+_ppf__(`traceoff')
+_ppf__(`traceon')
+_ppf__(`translit')
+_ppf__(`undefine')
+_ppf__(`undivert')
+
+B. QUOTE HANDLING.
+
+The characters used as quotes by M4, by default, are unfortunately
+quite likely to occur in ordinary text.  To avoid surprises, we will
+use the characters <> ---which are just as suggestive (more so to
+Francophones, perhaps) but a little less common in text (save for
+those poor Francophones.  You win some, you lose some).  Still, we
+expect also to have to set < and > occasionally in text; to do that,
+we define a macro to turn off quote handling (_0__) and a macro to
+turn it back on (_1__), according to our convention.  
+
+       BEWARE: This seems to make < and > unusable as relational operations
+               in calls to the builtin "eval".  So far I've gotten
+               along without; but a better choice may be possible.
+
+Note that we postponed this for a while, for convenience in discussing
+the issue and in the primitive renaming---not to mention in defining
+_0__ and _1__ themselves!  However, the quote redefinitions MUST
+precede the _if__ / _fi__ definitions, because M4 will expand the text
+as given---if we use the wrong quotes here, we will get the wrong
+quotes when we use the conditionals.
+
+_define__(_0__,`_changequote__(\ 1,\ 2)')_define__(_1__,`_changequote__(<,>)')
+_1__
+
+C. CONDITIONALS
+
+We define two macros, _if__ and _fi__.  BOTH take arguments!  This is
+meant both to help the human reader match up a _fi__ with its
+corresponding _if__ and to aid in the implementation.  You may use the
+full expression syntax supported by M4 (see docn of `eval' builtin in
+the m4 manual).
+
+The conditional macros are carefully defined to avoid introducing
+extra whitespace (i.e., blank lines or blank characters).  One side
+effect exists---
+
+       BEWARE: text following an `_if__' on the same line is
+               DISCARDED even if the condition is true; text
+               following a `_fi__' on the same line is also 
+               always discarded.
+
+The recommended convention is to always place _if__ and _fi__ on a
+line by themselves.  This will also aid the human reader.  TeX won't
+care about the line breaks; as for info, you may want to insert calls
+to `@refill' at the end of paragraphs containing conditionalized text,
+where you don't want line breaks separating unconditional from
+conditional text.  info formatting will then give you nice looking
+paragraphs in the info file.
+
+Nesting: conditionals are designed to nest, in the following way:
+*nothing* is output between an outer pair of false conditionals, even
+if there are true conditionals inside.  A false conditional "defeats"
+all conditionals within it.  The counter _IF_FS__ is used to
+implement this; kindly avoid redefining it directly.
+
+_define__(<_IF_FS__>,<0>)
+_define__(
+       <_pushf__>,
+       <_define__(<_IF_FS__>,
+               _incr__(_IF_FS__))>)
+_define__(
+       <_popf__>,
+       <_ifelse__(0,_IF_FS__,
+                       <<>_dnl__<>>,
+                       <_define__(<_IF_FS__>,_decr__(_IF_FS__))>)>)
+
+_define__(
+       <_if__>,
+       <_ifelse__(1,_eval__( ($1) ),
+                       <<>_dnl__<>>,
+                       <_pushf__<>_divert__(-1)>)>)
+_define__(
+       <_fi__>,
+       <_ifelse__(1,_eval__( ($1) ),
+               <<>_dnl__<>>,
+               <_popf__<>_ifelse__(0,_IF_FS__,
+                       <_divert__<>_dnl__<>>,<>)>)>)
+
+D. CHAPTER/SECTION MACRO
+In a parametrized manual, the heading level may need to be calculated;
+for example, a manual that has a chapter on machine dependencies
+should be conditionally structured as follows:
+       - IF the manual is configured for a SINGLE machine type,  use
+the chapter heading for that machine type, and run headings down
+from there (top level for a particular machine is chapter, then within
+that we have section, subsection etc);
+       - ELSE, if MANY machine types are described in the chapter,
+use a generic chapter heading such as "@chapter Machine Dependencies",
+use "section" for the top level description of EACH machine, and run
+headings down from there (top level for a particular machine is
+section, then within that we have subsection, subsubsection etc).
+
+The macro <_CHAPSEC__> is for this purpose: its argument is evaluated (so
+you can construct expressions to express choices such as above), then
+expands as follows:
+   0: @chapter
+   1: @section
+   2: @subsection
+   3: @subsubsection
+ ...and so on.
+
+_define__(<_CHAPSEC__>,<@_cs__(_eval__($1))>)
+_define__(<_cs__>,<_ifelse__(
+                       0, $1, <chapter>,
+                       1, $1, <section>,
+                               <sub<>_cs__(_eval__($1 - 1))>)>)
+
+_divert__<>_dnl__<>
diff --git a/gas/doc/sparc.m4 b/gas/doc/sparc.m4
new file mode 100644 (file)
index 0000000..8cc6a3e
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_SPARC__>,<1>)
+_define__(<_HOST__>,<SPARC>)
+_define__(<_MACH_DEP__>,<SPARC Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gas/doc/vax.m4 b/gas/doc/vax.m4
new file mode 100644 (file)
index 0000000..59cb2ab
--- /dev/null
@@ -0,0 +1,5 @@
+_divert__(-1)
+_define__(<_VAX__>,<1>)
+_define__(<_HOST__>,<VAX>)
+_define__(<_MACH_DEP__>,<VAX Dependent>)
+_divert__<>
\ No newline at end of file
diff --git a/gas/flonum-const.c b/gas/flonum-const.c
new file mode 100755 (executable)
index 0000000..25e7baf
--- /dev/null
@@ -0,0 +1,159 @@
+/* flonum_const.c - Useful Flonum constants
+   Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* static const char rcsid[] = "$Id$"; */
+
+#include "flonum.h"
+/* JF:  I added the last entry to this table, and I'm not
+   sure if its right or not.  Could go either way.  I wish
+   I really understood this stuff. */
+
+
+const int table_size_of_flonum_powers_of_ten = 11;
+
+static const LITTLENUM_TYPE zero[] = {     1 };
+
+/***********************************************************************\
+*                                                                      *
+*      Warning: the low order bits may be WRONG here.                  *
+*      I took this from a suspect bc(1) script.                        *
+*      "minus_X"[] is supposed to be 10^(2^-X) expressed in base 2^16. *
+*      The radix point is just AFTER the highest element of the []     *
+*                                                                      *
+*      Because bc rounds DOWN for printing (I think), the lowest       *
+*      significance littlenums should probably have 1 added to them.   *
+*                                                                      *
+\***********************************************************************/
+
+/* JF:  If this equals 6553/(2^16)+39321/(2^32)+...  it approaches .1 */
+static const LITTLENUM_TYPE minus_1 [] = {
+ 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321,
+ 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321,  6553 };
+static const LITTLENUM_TYPE plus_1 [] = {    10                             };
+
+/* JF:  If this equals 655/(2^16) + 23592/(2^32) + ... it approaches .01 */
+static const LITTLENUM_TYPE minus_2 [] = {
+ 10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 49807,
+ 10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592,   655 };
+static const LITTLENUM_TYPE plus_2 [] = {   100                             };
+
+/* This approaches .0001 */
+static const LITTLENUM_TYPE minus_3 [] = {
+ 52533, 20027, 37329, 65116, 64067, 60397, 14784, 18979, 33659, 19503,
+  2726,  9542,   629,  2202, 40475, 10590,  4299, 47815, 36280,     6 };
+static const LITTLENUM_TYPE plus_3 [] = { 10000                             };
+
+/* JF: this approaches 1e-8 */
+static const LITTLENUM_TYPE minus_4 [] = {
+ 22516, 49501, 54293, 19424, 60699,  6716, 24348, 22618, 23904, 21327,
+  3919, 44703, 19149, 28803, 48959,  6259, 50273, 62237,    42        };
+/* This equals 1525 * 2^16 + 57600 */
+static const LITTLENUM_TYPE plus_4 [] = { 57600,  1525                      };
+
+/* This approaches 1e-16 */
+static const LITTLENUM_TYPE minus_5 [] = {
+ 22199, 45957, 17005, 26266, 10526, 16260, 55017, 35680, 40443, 19789,
+ 17356, 30195, 55905, 28426, 63010, 44197,  1844                      };
+static const LITTLENUM_TYPE plus_5 [] = { 28609, 34546,    35               };
+
+static const LITTLENUM_TYPE minus_6 [] = {
+ 30926, 26518, 13110, 43018, 54982, 48258, 24658, 15209, 63366, 11929,
+ 20069, 43857, 60487,    51                                           };
+static const LITTLENUM_TYPE plus_6 [] = { 61313, 34220, 16731, 11629,  1262 };
+
+static const LITTLENUM_TYPE minus_7 [] = {
+ 29819, 14733, 21490, 40602, 31315, 65186,  2695                      };
+static const LITTLENUM_TYPE plus_7 [] = {
+  7937, 49002, 60772, 28216, 38893, 55975, 63988, 59711, 20227,    24 };
+
+static const LITTLENUM_TYPE minus_8 [] = {
+ 45849, 19069, 18068, 36324, 37948, 48745, 10873, 64360, 15961, 20566,
+ 24178, 15922, 59427,   110                                           };
+static const LITTLENUM_TYPE plus_8 [] = {
+ 15873, 11925, 39177,   991, 14589, 19735, 25347, 65086, 53853,  938,
+ 37209, 47086, 33626, 23253, 32586, 42547,  9731, 59679,  590         };
+
+static const LITTLENUM_TYPE minus_9 [] = {
+ 63601, 55221, 43562, 33661, 29067, 28203, 65417, 64352, 22462, 41110,
+ 12570, 28635, 23199, 50572, 28471, 27074, 46375, 64028, 13106, 63700,
+ 32698, 17493, 32420, 34382, 22750, 20681, 12300                      };
+static const LITTLENUM_TYPE plus_9 [] = {
+ 63564, 61556, 29377, 54467, 18621, 28141, 36415, 61241, 47119, 30026,
+ 19740, 46002, 13541, 61413, 30480, 38664, 32205, 50593, 51112, 48904,
+ 48263, 43814,   286, 30826, 52813, 62575, 61390, 24540, 21495,     5 };
+
+static const LITTLENUM_TYPE minus_10 [] = {
+ 50313, 34681,  1464, 25889, 19575, 41125, 17635,  4598, 49708, 13427,
+ 17287, 56115, 53783, 38255, 32415, 17778, 31596,  7557, 20951, 18477,
+ 40353,  1178, 44405, 11837, 11571, 50963, 15649, 11698, 40675,  2308,  };
+static const LITTLENUM_TYPE plus_10[] = {
+18520, 53764, 54535, 61910, 61962, 59843, 46270, 58053, 12473, 63785,
+ 2449, 43230, 50044, 47595, 10403, 35766, 32607,  1124, 24966, 35044,
+25524, 23631, 18826, 14518, 58448, 14562, 49618,  5588, 25396,    28 };
+
+static const LITTLENUM_TYPE minus_11 [] = {
+  6223, 59909, 62437, 59960, 14652, 45336, 48800,  7647, 51962, 37982,
+ 60436, 58176, 26767,  8440,  9831, 48556, 20994, 14148,  6757, 17221,
+ 60624, 46129, 53210, 44085, 54016, 24259, 11232, 21229, 21313,    81,  };
+static const LITTLENUM_TYPE plus_11 [] = {
+ 36159,  2055, 33615, 61362, 23581, 62454,  9748, 15275, 39284, 58636,
+ 16269, 42793, 47240, 45774, 50861, 48400,  9413, 40281,  4030,  9572,
+  7984, 33038, 59522, 19450, 40593, 24486, 54320,  6661, 55766,   805,  };
+
+/* Shut up complaints about differing pointer types.  They only differ
+   in the const attribute, but there isn't any easy way to do this
+ */
+#define X (LITTLENUM_TYPE *)
+
+const FLONUM_TYPE flonum_negative_powers_of_ten [] = {
+  {X zero,     X zero,         X zero,           0, '+'},
+  {X minus_1,  X minus_1 +19,  X minus_1  + 19, -20, '+'},
+  {X minus_2,  X minus_2 +19,  X minus_2  + 19, -20, '+'},
+  {X minus_3,  X minus_3 +19,  X minus_3  + 19, -20, '+'},
+  {X minus_4,  X minus_4 +18,  X minus_4  + 18, -20, '+'},
+  {X minus_5,  X minus_5 +16,  X minus_5  + 16, -20, '+'},
+  {X minus_6,  X minus_6 +13,  X minus_6  + 13, -20, '+'},
+  {X minus_7,  X minus_7 + 6,  X minus_7  +  6, -20, '+'},
+  {X minus_8,  X minus_8 +13,  X minus_8  + 13, -40, '+'},
+  {X minus_9,  X minus_9 +26,  X minus_9  + 26, -80, '+'},
+  {X minus_10, X minus_10+29,  X minus_10 + 29,-136, '+'},
+  {X minus_11, X minus_11+29,  X minus_11 + 29,-242, '+'},
+};
+
+const FLONUM_TYPE flonum_positive_powers_of_ten [] = {
+  {X zero,     X zero,         X zero,           0, '+'},
+  {X plus_1,   X plus_1  +  0, X plus_1  +  0,   0, '+'},
+  {X plus_2,   X plus_2  +  0, X plus_2  +  0,   0, '+'},
+  {X plus_3,   X plus_3  +  0, X plus_3  +  0,   0, '+'},
+  {X plus_4,   X plus_4  +  1, X plus_4  +  1,   0, '+'},
+  {X plus_5,   X plus_5  +  2, X plus_5  +  2,   1, '+'},
+  {X plus_6,   X plus_6  +  4, X plus_6  +  4,   2, '+'},
+  {X plus_7,   X plus_7  +  9, X plus_7  +  9,   4, '+'},
+  {X plus_8,   X plus_8  + 18, X plus_8  + 18,   8, '+'},
+  {X plus_9,   X plus_9  + 29, X plus_9  + 29,  24, '+'},
+  {X plus_10,  X plus_10 + 29, X plus_10 + 29,  77, '+'},
+  {X plus_11,  X plus_11 + 29, X plus_11 + 29, 183, '+'},
+};
+
+#ifdef VMS
+dummy1()
+{
+}
+#endif
+/* end: flonum_const.c */
diff --git a/gas/hex-value.c b/gas/hex-value.c
new file mode 100644 (file)
index 0000000..64420f5
--- /dev/null
@@ -0,0 +1,57 @@
+/* hex_value.c - char=>radix-value -
+   Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* static const char rcsid[] = "$Id$"; */
+
+/*
+ * Export: Hex_value[]. Converts digits to their radix-values.
+ *     As distributed assumes 8 bits per char (256 entries) and ASCII.
+ */
+
+#define __ (42)                        /* blatently illegal digit value */
+                               /* exceeds any normal radix */
+#if !defined(__STDC__) && !defined(const)
+#define const /* empty */
+#endif
+const char
+hex_value [256] = {            /* for fast ASCII -> binary */
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, __, __, __, __, __, __,
+  __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
+  };
+
+#ifdef VMS
+dummy2()
+{
+}
+#endif
+/* end:hex_value.c */
diff --git a/gas/strstr.c b/gas/strstr.c
new file mode 100644 (file)
index 0000000..9823249
--- /dev/null
@@ -0,0 +1,55 @@
+/* strstr - find first occurrence of wanted in s
+   Copyright (C) 1989, 1990, 1991 Free Software Foundation.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* static const char rcsid[] = "$Id$"; */
+
+ /* If your compiler is really ansi, then you don't need this. */
+#ifndef __STDC__
+
+#define SIZET int
+
+#define        NULL    0
+
+#include <string.h>
+
+char *                         /* found string, or NULL if none */
+strstr(s, wanted)
+char *s;
+char *wanted;
+{
+       register char *scan;
+       register SIZET len;
+       register char firstc;
+
+       /*
+        * The odd placement of the two tests is so "" is findable.
+        * Also, we inline the first char for speed.
+        * The ++ on scan has been moved down for optimization.
+        */
+       firstc = *wanted;
+       len = strlen(wanted);
+       for (scan = s; *scan != firstc || strncmp(scan, wanted, len) != 0; )
+               if (*scan++ == '\0')
+                       return(NULL);
+       return(scan);
+} /* strstr() */
+
+#endif /* __STDC__ */
+
+/* end of strstr.c */
diff --git a/gas/testscripts/doboth b/gas/testscripts/doboth
new file mode 100755 (executable)
index 0000000..a8c3358
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+# $Id$
+
+x=$1 ; shift
+y=$1 ; shift
+
+rm tmp.0 > /dev/null 2>&1
+ln -s $x tmp.0
+$* tmp.0 > tmp.1
+
+rm tmp.0
+ln -s $y tmp.0
+$* tmp.0 > tmp.2
+
+rm tmp.0
+
+diff -c tmp.1 tmp.2
+exit
+
+#eof
diff --git a/gas/testscripts/doobjcmp b/gas/testscripts/doobjcmp
new file mode 100755 (executable)
index 0000000..9fbe46b
--- /dev/null
@@ -0,0 +1,89 @@
+#!/bin/sh
+# $Id$
+# compare two object files, in depth.
+
+x=$1
+y=$2
+BOTH="$1 $2"
+
+
+# if they cmp, we're fine.
+if (cmp $BOTH > /dev/null)
+then
+       exit 0
+fi
+
+# otherwise, we must look closer.
+if (doboth $BOTH size)
+then
+       echo Sizes ok.
+else
+       echo Sizes differ:
+       size $BOTH
+#      exit 1
+fi
+
+if (doboth $BOTH objdump +header)
+then
+       echo Headers ok.
+else
+       echo Header differences.
+#      exit 1
+fi
+
+if (doboth $BOTH objdump +text > /dev/null)
+then
+       echo Text ok.
+else
+       echo Text differences.
+#      doboth $BOTH objdump +text
+#      exit 1
+fi
+
+if (doboth $BOTH objdump +data > /dev/null)
+then
+       echo Data ok.
+else
+       echo Data differences.
+#      doboth $BOTH objdump +data
+#      exit 1
+fi
+
+if (doboth $BOTH objdump +symbols > /dev/null)
+then
+       echo Symbols ok.
+else
+       echo -n Symbol differences...
+
+       if (doboth $BOTH dounsortsymbols)
+       then
+               echo but symbols are simply ordered differently.
+#              echo Now what to do about relocs'?'
+#              exit 1
+       else
+               echo and symbols differ in content.
+               exit 1
+       fi
+fi
+
+# of course, if there were symbol diffs, then the reloc symbol indexes
+# will be off.
+
+if (doboth $BOTH objdump -r > /dev/null)
+then
+       echo Reloc ok.
+else
+       echo -n Reloc differences...
+
+       if (doboth $BOTH dounsortreloc)
+       then
+               echo but relocs are simply ordered differently.
+       else
+               echo and relocs differ in content.
+               exit 1
+       fi
+fi
+
+exit
+
+# eof
diff --git a/gas/testscripts/dostriptest b/gas/testscripts/dostriptest
new file mode 100755 (executable)
index 0000000..4b89df8
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+# $Id$
+
+x=striptest.xx.$$
+y=striptest.yy.$$
+
+cp $1 $x
+strip $x
+cp $2 $y
+strip $y
+
+doobjcmp $x $y
+exit
+
+#eof
diff --git a/gas/testscripts/dotest b/gas/testscripts/dotest
new file mode 100755 (executable)
index 0000000..8c7a28c
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh
+# ad hoc debug tool
+# $Id$
+
+x=$1
+y=$2
+
+xout=`basename $x`.xxx.$$
+yout=`basename $x`.yyy.$$
+
+mkdir $xout
+mkdir $yout
+
+for i in *.s
+do
+       echo Testing $i...
+       object=`basename $i .s`.o
+       $x $i -o $xout/$object
+       $y $i -o $yout/$object
+
+# if they cmp, we're ok.  Otherwise we have to look closer.
+
+       if (cmp $xout/$object $yout/$object)
+       then
+               echo $i is ok.
+       else
+               if (doobjcmp $xout/$object $yout/$object)
+               then
+                       echo Not the same but objcmp ok.
+               else
+                       exit 1
+               fi
+       fi
+
+       echo
+done
+
+rm -rf $xout $yout
+
+exit 0
+
+# EOF
+
+
diff --git a/gas/testscripts/dounsortreloc b/gas/testscripts/dounsortreloc
new file mode 100755 (executable)
index 0000000..d8da0a9
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+# $Id$
+# objdump the reloc table, but strip off the headings and reloc
+# numbers and sort the result.  Intended for use in comparing reloc
+# tables that may not be in the same order.
+
+objdump +reloc +omit-relocation-numbers +omit-symbol-numbers $1 \
+       | sort
+#eof
diff --git a/gas/testscripts/dounsortsymbols b/gas/testscripts/dounsortsymbols
new file mode 100755 (executable)
index 0000000..8fb6db3
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+# $Id$
+# objdump the symbol table, but strip off the headings and symbol
+# numbers and sort the result.  Intended for use in comparing symbol
+# tables that may not be in the same order.
+
+objdump +symbols +omit-symbol-numbers $1 \
+       | sort
+#eof
diff --git a/gas/xmalloc.c b/gas/xmalloc.c
new file mode 100644 (file)
index 0000000..6602987
--- /dev/null
@@ -0,0 +1,71 @@
+/* xmalloc.c - get memory or bust
+   Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* static const char rcsid[] = "$Id$"; */
+
+/*
+NAME
+       xmalloc() - get memory or bust
+INDEX
+       xmalloc() uses malloc()
+
+SYNOPSIS
+       char *  my_memory;
+
+       my_memory = xmalloc(42); / * my_memory gets address of 42 chars * /
+
+DESCRIPTION
+
+       Use xmalloc() as an "error-free" malloc(). It does almost the same job.
+       When it cannot honour your request for memory it BOMBS your program
+       with a "virtual memory exceeded" message. Malloc() returns NULL and
+       does not bomb your program.
+
+SEE ALSO
+       malloc()
+
+*/
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#ifdef USG
+#include <malloc.h>
+#else
+  char *       malloc();
+#endif /* USG */
+#endif /* __STDC__ */
+
+#define error as_fatal
+
+char * xmalloc(n)
+     long n;
+{
+  char *       retval;
+  void error();
+
+  if ((retval = malloc ((unsigned)n)) == NULL)
+    {
+      error("virtual memory exceeded");
+    }
+  return (retval);
+}
+
+/* end: xmalloc.c */
diff --git a/gas/xrealloc.c b/gas/xrealloc.c
new file mode 100644 (file)
index 0000000..83d3ce6
--- /dev/null
@@ -0,0 +1,70 @@
+/* xrealloc.c -new memory or bust-
+   Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* static const char rcsid[] = "$Id$"; */
+
+/* 
+
+NAME
+       xrealloc () - get more memory or bust
+INDEX
+       xrealloc () uses realloc ()
+SYNOPSIS
+       char   *my_memory;
+
+       my_memory = xrealloc (my_memory, 42);
+       / * my_memory gets (perhaps new) address of 42 chars * /
+
+DESCRIPTION
+
+       Use xrealloc () as an "error-free" realloc ().It does almost the same
+       job.  When it cannot honour your request for memory it BOMBS your
+       program with a "virtual memory exceeded" message.  Realloc() returns
+       NULL and does not bomb your program.
+
+SEE ALSO
+       realloc ()
+*/
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#ifdef USG
+#include <malloc.h>
+#else
+    char   *realloc ();
+#endif /* USG */
+#endif /* __STDC__ */
+
+#define error as_fatal
+
+char   *
+xrealloc (ptr, n)
+register char  *ptr;
+long    n;
+{
+    void       error();
+
+    if ((ptr = realloc (ptr, (unsigned)n)) == 0)
+       error ("virtual memory exceeded");
+    return (ptr);
+}
+
+/* end: xrealloc.c */
diff --git a/gdb/.gdbinit b/gdb/.gdbinit
new file mode 100644 (file)
index 0000000..bcacd5d
--- /dev/null
@@ -0,0 +1,15 @@
+echo Setting up the environment for debugging gdb.\n
+
+b fatal
+
+b info_command
+commands
+       silent
+       return
+end
+
+define rr
+    run
+end
+
+set prompt (top-gdb)
diff --git a/gdb/COPYING b/gdb/COPYING
new file mode 100644 (file)
index 0000000..9a17037
--- /dev/null
@@ -0,0 +1,249 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
new file mode 100644 (file)
index 0000000..12ec9cc
--- /dev/null
@@ -0,0 +1,4297 @@
+Sat Mar 23 10:02:21 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Cleanup for release 3.94.2:
+
+       * Makefile.dist: Pull REMOTE_OBS.  Fix saber includes for BFD
+       include files.  Roll version to 3.94.2.
+       
+       * coffread.c (init_stringtab):  Read length into unsigned char
+       array before swapping; don't assume 32-bit longs.
+
+       * target.c (target_info): Don't bother with get_sym_file, just use
+       the symfile global variable.
+       * symtab.h, symfile.c (get_sym_file):  Delete it.
+
+       * dbxread.c (dbx_symfile_init):  Don't depend on long == 4 bytes.
+       (define_symbol):  Set symbol line number to 0 if not gcc-compiled.
+       (read_type):  Replace one more error() with complain().
+
+       * mipsread.c (parse_partial_symbols):  Replace printf with complain.
+
+       * i960-tdep.c:  Fix copyright attribution.
+
+       * config.gdb:  Quote all backquotes in doublequotes.  You can
+       quote me on that.  BSD 4.4 shell found this one.
+
+       * infptrace.c (throughout):  The third argument to ptrace is an
+       int *, not an int.
+
+       * infrun.c (wait_for_inferior):  When program has terminated, we
+       have to call target_terminal_ours before we pop that target off
+       the stack (e.g. before a call to target_kill or
+       target_mourn_inferior).  This fixes problem where a program
+       terminates, then GDB stops for (tty output) and you have to type
+       "fg" to the shell to resume it.  FIXME:  This code for what to
+       do after termination really should be in normal_stop instead.
+
+       * gdbcore.h (read_memory_check):  Change declaration; it changed
+       names months ago.
+
+       * terminal.h:  Include <sgtty.h> before <sys/ioctl.h>, since in BSD
+       4.4 prereleases, this avoids a bug in their sgtty compatability
+       support.
+       * remote.c:  Use terminal.h rather than hand-rolling the same.
+
+       * signame.c, signame.h (psignal):  Arg is unsigned, not int.
+       * utils.c (strsave, strstr):  Fix arg types.
+       * valprint.c (val_print):  lint
+
+       MIPS symbol table support from Per Bothner:
+
+       * symfile.c (symtab_fns):  Remove initializer table that needs to
+       be hacked for each new symbol file format supported.
+       (add_symtab_fns):  New function, chains symbol table
+       handlers into the global list.
+       (symfile_init):  Search this list.
+       * symfile.h:  Add next pointer, declare add_symtab_fns.
+       * coffread.c (_initialize_coffread): Call add_symtab_fns.
+       * dbxread.c (_initialize_dbxread):  Call add_symtab_fns.
+
+       * mipsread.c (psymtab_to_symtab_1): return void instead of (struct
+       symbol *).  Thus, we no longer need the hack to trash
+       pst->filename.  Good, since that hack confused code in symfile.c!
+
+       (reorder_symtabs, destroy_all_symtabs):  Removed static
+       all_symtabs, which was used to qsort symtabs in reorder_symtabs.
+       Instead, the latter now uses a temporary array (stack-allocated
+       from an obstack, and then freed).
+
+       (parse_symbol):  Added a hack to fix up BLOCK_{START,END} if they
+       haven't been set in the outermost stBlock of a procedure. This was
+       a problem with f77 binaries on Ultrix 4.?.
+
+       (new_symtab, new_symbol, new_type):  Continue changing code to use
+       obstacks more and otherwise conform to dbxread internal style.
+       Made the free_code of symtabs be free_linetable (as in dbxread)
+       instead of free_contents.  This implies memory leaks when reading
+       a new symbol table, until the conversion is finished. Did change
+       (struct symbol) and (struct type) to be allocated on the
+       symbol_obstack.  Blocks and blockvectors are among the things
+       still "leaking."
+
+       * mipsread.c (parse_partial_symbols, parse_fdr):  It hasn't been
+       tested much, but it solved one problem (reported by Meissner), and
+       cleans up some other things.  The problem happened when an
+       included file contains actual code (functions) and not just
+       definitions. The mips coff is a little inconvenient there, since
+       it may cause a procedure to be mapped to the wrong psymtab.
+
+       * mips-tdep.c (heuristic_proc_desc):  Minor cleanup.
+       * mips-xdep.c (fetch_core_registers):  Minor cleanup.  FIXME,
+       this will need work for the new core paradigm.
+
+       Opcode patches from the net:
+
+       * mips-opcode.h: fix incorrect disassembly of the mfc1, cfc1, and
+       ctc1 instructions. Also, the cvt.d.w and cvt.s.w instructions were
+       missing altogether - they are added here.  From Bruce Bauman.
+       * mips-opcode.h:  The low mask for C0 instructions was too small.
+       From Garrett Lau.  I modified the fix to check the entire 32-bit
+       opcode.
+
+       * ns32k-opcode.h:  Fix opcodes for deiw and deid.  From Bruce
+       Bauman.
+
+Thu Mar 21 12:56:46 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Roll in changes from Per Bothner (Tue, 25 Sep 90 11:11:04):
+
+       * dbxread.c (read_type): Pointer subtraction (value_sub in
+       valarith.c) sometimes failed because the types of the
+        pointers being subtracted were not identical.
+       These differed because dbxread.c was allocating pointer types
+       using dbx_alloc_type+smash_to_pointer_type instead of
+       lookup_pointer_type. I failed to find a justification for the
+       former, so I changed it to use the latter. Similarly, I
+       replaced smash_to_function_type by lookup_function_type,
+       and smash_to_reference_type by lookup_reference_type.
+
+       * mipsread.c (parse_symbol, upgrade_type, parse_procedure, 
+       _initialize_mipsread):  corresponding changes.
+
+       * symtab.c (smash_to_{pointer,reference,function}_type): eliminate.
+
+       * source.c (mod_path): Do tilde_expand on each component of the path,
+       rather than on the (list of) paths as a whole.
+       (print_source_lines):  Set first_line_listed in addition to
+       current_source_symtab and current_source_line.  If the source was
+       not findable, after a "dir" command to fix the problem,
+       a "list" would get the wrong lines.
+
+       While I was there... (gnu):
+
+       * dbxread.c (read_type):  Change error to complaint.
+
+Thu Mar 21 12:56:46 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       First attempt at detailed understanding of symbol table memory alloc.
+
+       * dbxread.c (dbx_symfile_read):  Free our string table if we
+       aren't the mainline.  Free the "info" struct since we're done with
+       it. 
+       (init_psymbol_list):  Free any previously allocated psymbol lists.
+       (): FIXME: Should realloc-down the psymbol lists when done reading
+       the main symbol file?
+
+       * symmisc.c (free_symtab):  Free fullname field too.
+
+       * xm-hp300hpux.h (USG):  #undef then #define so Makefile can -D.
+       (REGISTER_ADDR):  Make result type unsigned int.
+
+       * xconfig/{i386*,hp300hpux,altosgas,altos}:  All config files that
+       define REGEX must also define REGEX1 (its dependency).
+
+Tue Mar 19 21:28:57 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * tconfig/i960:  No longer works, points you at vxworks960 or
+       nindy960.
+
+       * xgdb.c, XGDB-README:  Remove file.  Users can get the much
+       better xxgdb.
+       * Makefile.dist:  Remove all trace of xgdb.
+
+       * breakpoint.c (breakpoint_1):  Pass demangle arg to
+       print_address_symbolic.
+       (clear_breakpoints):  Remove unused function.
+       (breakpoint_re_set_one):  Guts of breakpoint_re_set.
+       (breakpoint_re_set):  Use catch_errors to do them all anyway.
+
+       * gdb-int.texinfo (Host versus Target):  Add section on what is
+       a "host" feature versus what is a "target" feature.
+
+       * infcmd.c (path_command, path_info):  Handle the PATH variable
+       (object search path) as conveniently as the source search path.
+       * environ.c (set_in_environ):  Set some vars in GDB's environment,
+       in addition to the child's.  PATH, G960BASE, G960BIN for starters.
+       * source.c (mod_path):  New function, from guts of
+       directory_command, modifies a path.  Used by path_command.
+       (directory_command):  Call it.
+       * defs.h (strsave):  Declare.
+
+       * utils.c (sevenbit_strings):  Add new printing option.
+       (printchar):  Use it.
+       (strsave):  Provide this handy helper routine.
+       (set_width_command):  Rename set_screen_width_command.
+       (_initialize_utils):  "set screen-width" => "set width";
+       "set screen-height" => "set height"; add sevenbit-strings.
+
+       * infcmd.c (do_registers_info):  Print floating point registers
+       in raw hex as well as float format, regardless of whether it is
+       a "virtual" convertible register.
+       * tm-sparc.h (PRINT_REGISTER_HOOK):  Print every pair of float
+       regs as a double, just in case it's being used that way.        
+       * values.c (unpack_long):  Comment on array/function coercion.
+       (unpack_double):  Argument is in target byte order now.  For
+       integer arguments, just call unpack_long and float the result.
+       * m68k-tdep.c: include defs.h for "const" handling.
+       * remote-nindy.c:  Use ieee-float stuff.
+       (nindy_fetch_registers):  Unpack double regs to host double, then
+       to extended.
+       (nindy_store_registers):  Pack extendeds to host double, flip
+       around by misusing unpack_double, send as target double.
+
+       * tm-vxworks68.h (FRAME_CHAIN):  Handle current frame pointer of
+       zero, as when stopped at the first instruction of a process.
+
+       * blockframe.c:  Fix filename in comment (param.h => tm.h).
+       * sparc-tdep.c (skip_prologue):  More explicit nudging comments.
+       * tm-68k.h:  Fix typos.
+
+Fri Mar 15 01:09:34 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Changes from a bringup on the DEC Vax under Ultrix 4.0.
+
+       * coredep.c (fetch_core_registers):  Pass end-address of register
+       section to register_addr as expected.  Don't call supply_register
+       if we'd just pass it garbage.
+
+       * dbxread.c (read_dbx_symtab):  Skip N_NSYMS on Ultrix.
+
+       * exec.c (xfer_memory):  Use boolean xfer_fn result, not int.
+
+       * target.c (push_target, target_info):  Cast enums to int for < or
+       > comparison.
+
+       * stack.c (print_frame_info):  Identify source file & line
+       even if we can't print it.
+
+       * xm-vax.h (MISSING_VPRINTF):  No longer missing in Ultrix V4.0.
+
+Sat Mar  9 10:08:20 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Clean up IEEE floating point support.
+
+       * ieee-float.h:  New file.
+       * ieee-float.c:  Write real routines to convert between host
+       doubles and various target IEEE extendeds.
+       * m68k-xdep.c:  Eliminate assembler code for extended floats.
+       * xconfig/{3b1,altos,altosgas,hp300bsd,isi,news,news1000,sun2os3,
+       sun2os4,sun3,sun3os3,sun3os4}:  Eliminate use of m68k-xdep.o.
+       * tm-i960.h, tm-68k.h (REGISTER_CONVERT_TO_VIRTUAL,
+       REGISTER_CONVERT_TO_RAW):  Use ieee_extended_to_double and
+       double_to_ieee_extended.
+       * i960-tdep.c:  Define ext_format_i960.
+       * m68k-tdep.c:  Define ext_format_68881.
+       * sparc-tdep.c:  Define ext_format_sparc, though unused.
+       * Makefile.dist (HFILES):  Add ieee-float.h.
+       * inftarg.c: #include "ieee-float.h" for the REGISTER_CONVERT
+       macros.
+
+       Obsolete the "coffstrip" program in favor of using BFD's strip.
+
+       * nindy-share/coffstrip.c:  Remove file.
+       * nindy-share/nindy.c (coffstrip):  Routine to run bfd_strip.
+       * Makefile.dist:  Remove references to nindy-share/coffstrip.c.
+       * tconfig/nindy960:  Remove reference to coffstrip.o.
+
+       * Makefile.dist:  Roll version number to 3.94.1 (not yet final).
+
+Wed Mar  6 09:56:45 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * symfile.h:  Add symfile_bfd, common between dbxread and coffread.
+       * dbxread.c:  Remove static symfile_bfd.
+       * infcmd.c (do_registers_info):  Add PRINT_REGISTER_HOOK, though
+       it is not used yet.
+       * inftarg.c (child_detach):  Pop the child_ops vector if the
+       detach is successful.
+       * remote-nindy.c (nindy_create_inferior):  Don't push a new
+       nindy_ops since nindy uses the same one for execution and memory
+       examination anyway.
+       * core.c (core_ops):  Use child_attach and child_create_inferior
+       rather than default attach and create_inferior functions.
+
+       Handle floating point registers in core files.
+
+       * sparc-xdep.c (fetch_core_registers):  Rewrite for float support.
+       * sun3-xdep.c (fetch_core_registers):  Rewrite for float support.
+       This version untested since BFD doesn't yet support sun3 core
+       files.
+       * hp300hpux-xdep.c:  Rewrite fetch_core_registers to new calling
+       conventions.  Fix comments and style.  This version has not
+       been compiled yet, since we have no HP inhouse.
+       * core.c (get_core_registers):  Look for two sections, ".reg"
+       and ".reg2", and pass both to fetch_core_registers sequentially.
+
+       Revise directory path yet again.
+
+       * source.c (forget_cached_source_info):  Not static any more.
+       (init_source_path):  New default source path is "$cdir:$cwd".
+       (dir_command):  Handle variable arguments ($cdir, $cwd).
+       (source_info):  Print "Compilation directory" rather than
+       "Originally compiled in" to remind people of $cdir.
+       (openp):  If the path contains $cwd, use current directory.
+       (open_source_file):  If compilation directory is known, replace
+       first $cdir in path with the compilation directory.
+       (print_source_lines):  Even if we can't print the lines, set the
+       current symtab and line for future commands like "info source" or
+       "breakpoint".  Also, error message now contains the file name,
+       line number, and file access error message.
+       (_initialize_source):  Fix help text to describe changes.
+       * main.c (cd_command):  Forget cached source info when we chdir.
+       * utils.c (strstr):  Add simple implementation.
+
+Tue Mar  5 01:41:40 1991  John Gilmore  (gnu at fowanton.cygnus.com)
+
+       * coffread.c (read_one_sym, init_linetable, init_stringtab):
+       Byte-swap COFF symbol tables if necessary when reading them in.
+       Use complain() to replace error message in one spot.  Needs
+       corresponding change in bfd/coff-code.h to make some symbol
+       swapping routines non-static.
+
+Mon Mar  4 00:53:40 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Merge changes from Eirik Fuller, for UTek.
+
+       * defs.h (errno):  Add declaration.
+       * altos-xdep.c, arm-xdep.c, convex-xdep.c, gould-xdep.c,
+       hp300hpux-xdep.c, infrun.c, inflow.c, infptrace.c, i386-tdep.c,
+       i386-xdep.c, pyr-xdep.c, mips-xdep.c, remote-eb.c, remote-nindy.c,
+       remote-vx.c, source.c, standalone.c, stuff.c, sun386-xdep.c,
+       symmetry-tdep.c, symmetry-xdep.c, umax-xdep.c, utils.c:  Eliminate
+       declarations of errno.
+
+       * remote-eb.c:  Define B19200 and B38400 as EXTA and EXTB.
+
+       * remote-vx.c:  Include <sys/time.h> for UTek; Sun gets it via
+       <rpc/rpc.h> and <rpc/types.h>.
+
+Sat Mar  2 15:47:55 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * i960-tdep.c (examine_prologue):  Add new argument limit,
+       which stops the scan at the end of the prologue, or at the PC.
+       This fixes a problem where it walks down into the code for the
+       user's statements if that code looks like function prologues.
+       Mark Fox and I have been bouncing this code back and forth, making
+       small changes to it.  Callers changed to match.
+
+Tue Feb 26 01:47:07 1991  Cygnus John Gilmore  (cygnus at yuba)
+
+       Cleanup for gdb-3.94 release final:
+
+       * Makefile.dist:  Remove remote-vx.c, remote-nindy.c, and all
+       the .c files from vx-share and nindy-share, from the various 
+       macros, since they are not found via ALLDEPFILES.
+       (SFILES):  Add tm-i960.h.
+       (alldeps.mak rule):  Break out ALLDEPFILES_MAINDIR and
+       ALLDEPFILES_SUBDIR.  List all the nindy and vxworks subdir files
+       in the SUBDIR list.
+       (TAGFILES_MAINDIR):  Change ALLDEPFILES to ALLDEPFILES_MAINDIR.
+       (gdb.tar.Z):  Use ALLDEPFILES_SUBDIR as well as SFILES_SUBDIR.
+
+Mon Feb 25 16:02:35 1991  Cygnus John Gilmore  (cygnus at oldman)
+
+       * am29k-tdep.c:  Add contribution line.
+       (examine_prologue):  Cache information about function prologues in
+       the misc-function-vector to avoid lots of references over the
+       serial line while examining instructions.
+
+       * core.c (core_close):  New function made from cleanup_core.
+
+       * core.c, exec.c, inftarg.c, remote-eb.c, remote-nindy.c,
+       remote-vx.c, remote.c, target.c, target.h, 
+       Update target_ops vector to add attach, close, and load entries.
+       Use add_syms_addr_command, not add_file_addr_command, for
+       add_file.  Break out close routine from existing code.
+
+       * dbxread.c (really_free_pendings):  Don't free pending_blocks;
+       they are in an obstack.
+       (read_dbx_symtab):  Relocate end_of_text_addr in the psymtab.
+       Lint.
+       (define_symbol):  Add symbol type parameter; change callers;
+       pass type parameter to DBX_PARM_SYMBOL_CLASS macro to allow
+       it to influence the symbol class on the i960.
+       (define_symbol):  Swap LOC_CONST's into target byte order.
+
+       * exec.c (exec_close):  New function.
+       (exec_file_command):  Call it.
+
+       * findvar.c (read_relative_register_raw_bytes):  Doc byte order,
+       Fix byte order of frame pointer.
+       (read_var_value):  Result of 0 if var's value can't be found,
+       e.g. missing FRAME_ARGS_ADDRESS.  Byte-swap LOC_CONST and
+       LOC_LABEL values to target order.  Add LOC_LOCAL_ARG.
+       (locate_var_value):  Use read_var_value and use its lazy address
+       as the location of the var's value.  Lint.
+
+       * i960-pinsn.c (next_insn):  Add routine from vxgdb for scanning
+       instructions.       
+
+       * i960-tdep.c (arg_address, i960_frame_find_saved_regs):  Remove
+       obsolete Intel versions in favor of vxgdb versions.
+       (check_host, byteswap, byteswap_val, reorder_val):  Eliminate
+       code dealing with byte order of values, which Intel did in host byte
+       order rather than gdb-4's target byte order.
+       (i960_frame_chain_valid):  Move to nindy-tdep.c.
+       (examine_prologue, skip_prologue, frame_find_saved_regs,
+       frame_args_address, leafproc_return, saved_pc_after_call,
+       pop_frame):  Add vxgdb versions from Mark Fox.
+       (examine_prologue, frame_struct_result_address):  Add code
+       to deal with the saved value of G13 (struct return address
+       pointer).
+       (frame_args_address):  Modify Mark's version to prefer the
+       saved value over the current value in the topmost frame.
+       Cache result in the frame info to avoid performance hair in
+       callers.
+       (print_fault):  Add gdb960 code for printing faults.
+       (_initialize_i960):  Actually call check_host.
+
+       * ieee-float.c (ieee_extended_to_double, ieee_double_to_extended):
+       add stub routines.  FIXME, these currently just return zero!
+
+       * infcmd.c (program_info):  Use PRINT_RANDOM_SIGNAL.
+       (attach_command):  Call target_attach, not target_open, now.
+
+       * infrun.c (normal_stop):  Make global, not static, for vx_attach.
+       (child_attach):  Rename from child_open.
+       (wait_for_inferior): Use PRINT_RANDOM_SIGNAL.  If stop_pc is zero,
+       don't confuse it with a zero step_resume_break_address. 
+
+       * inftarg.c (child_detach):  Eliminate inferior_pid test.
+       (child_files_info):  Clean up message a bit.
+       (child_ops):  Use child_attach, not child_open, to attach.
+
+       * mem-break.c:  #ifdef out the whole file if BREAKPOINT is not
+       set (e.g. on VxWorks or NINDY).  Move read_memory_nobpt from
+       findvar.c to here, since it depends on the contents of the
+       shadow_contents of breakpoints, but keep if #if 0 since it is
+       never called.
+
+       * nindy-tdep.c:  New file, contains nindy_frame_chain_valid, moved
+       from i960-tdep.c.
+
+       * printcmd.c (address_info):  Handle LOC_LOCAL_ARG.  Lint.
+       (ptype_command, display_command):  Eliminate have_inferior_p and
+       have_core_file_p in favor of target_has_stack or
+       target_has_execution.
+       (print_frame_args):  Handle LOC_LOCAL_ARG.  Eliminate duplicate
+       code for actually finding the values of arguments, though we still
+       keep track of the maximum stack offset for use in printing unnamed
+       arguments.  Handle missing FRAME_ARGS_ADDRESS.
+
+       * remote-nindy.c (i960_print_fault):  Move to i960-tdep.c.
+       (struct nindy_regs):  Define registers passed to/from nindy.
+       (nindy_fetch_registers, nindy_store-registers):  Translate between
+       nindy and GDB formats for the registers.
+       (dcache_init):  Statically allocate the cache, since it was being
+       allocated by a malloc that was never freed anyway.
+       (nindy_create_inferior):  Error, not core dump, if no exec file.
+       (nindy_before_main_loop):  Use target_load, not target_add_file.
+
+       * remote-vx.c (net_load):  Specify large timeout for load
+       requests.  Allow user to break out with INTERRUPT.
+       (net_break):  Remove useless code, clean up.  Change callers.
+       (parse-args, skip_white_space, find_white_space):  Clean up arg
+       parsing to cope with quoted strings.
+       (net_wait, net_quit):  Never call error, just return status.
+       (vx_read_register, vx_write_register):  Cleanup status checking.
+       #ifdef the code based on which CPU we are using (960 or 68k),
+       FIXME, this should be completely general but it isn't yet.
+       (vx_xfer_memory, vx_resume):  Cleanup status checking.
+       (vx_run_files_info):  Improve message.
+       (vx_load_command):  Renamed from vx_add_file_command.  Allow load
+       to be interrupted.
+       (net_ptrace):  Remove unused routine.
+       (vx_wait):  Adopt code from vxgdb960 to cope with broken
+       connections to target machine and prompt to disconnect.  Remove
+       debug printouts.  Map some EVENT_'s to SIGnals.
+       (add_symbol_stub, vx_open):  Print names of object files we found,
+       and "ok" if we read their symbols OK.  Clarify output in general.
+       (vx_attach, vx_detach, vx_kill):  Add these commands.
+       (vx_convert_from_virtual, vx_convert_to_virtual):  Simplify.
+       (vx_run_ops):  Turn off all_mem, to avoid spurious msg in the
+       "info files" output, and create_inferior, since we already have
+       an inferior.
+
+       * stack.c (frame_info):  Replace Frame_unknown with 0.
+       (print_frame_arg_vars):  Handle LOC_LOCAL_ARG.
+       (return_command):  Pop until the PC matches as well as the FP,
+       so it works even if the FP is shared with another function,
+       as in "frameless" or "leaf" procedures.
+
+       * symfile.c (load_command):  renamed from add_file_target_command.
+       (add_syms_addr_command):  renamed from add_file_addr_command.
+       (add_syms_command):  Stub to call target_add_syms.
+       (_initialize_symfile):  Change command names and descriptions,
+       add-file => add-syms, and load from alias to its own command.
+
+       * target.c (kill_or_be_killed, maybe_kill_then_attach,
+       maybe_kill_then_create_inferior):  Default for attempts to start
+       a process, if one is already running, is to ask about killing
+       it and retry if yes.
+       (upstack_create_inferior):  #if-0 it, strata obsolete it.
+       (push_target, unpush_target, pop_target):  to_close() a target
+       before unstacking it. 
+       (target_info):  Renamed from target_files_info.
+       (_initialize_targets):  Rename "i files" as "i target", accessible
+       under both names.
+
+       * target.h:  Improve comments about the target_ vectored routines.
+
+       * tm-i960.h:  Remove NINDY-specific stuff to tm-nindy960.h.
+       Convert commenting style to standard GNU style.
+       (DBX_PARM_SYMBOL_CLASS): allow LOC_LOCAL_ARG's to be recognized.
+       (SKIP_PROLOGUE):  No longer a no-op.
+       (SAVED_PC_AFTER_CALL):  Now handles leaf procedures.
+       (*_REGNUM):  Sort register numbers.
+       (REGISTER_BYTES, REGISTER_BYTE, REGISTER_RAW_SIZE,
+       MAX_REGISTER_RAW_SIZE, REGISTER_CONVERTIBLE,
+       REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW):  Float regs
+       are now 10 byte extendeds, not 8 byte doubles.
+       (FRAME_CHAIN_VALID):  Make this config-dependent, since it differs
+       for nindy versus vxworks targets.  FIXME, this should possibly go
+       in the target vector.
+       (EXTRA_FRAME_INFO, INIT_EXTRA_FRAME_INFO):  Cache both
+       frame_saved_regs and arg pointer with each frame.
+       (FRAMELESS_FUNCTION_INVOCATION):  New leafproc support.
+       (FRAME_ARGS_ADDRESS):  Use cached result.
+       (FRAME_ARGS_ADDRESS_CORRECT):  New, avoids g14 guessing.
+       (FRAME_FIND_SAVED_REGS):  Change arg to subsidiary fn.
+       (PRINT_RAMDON_SIGNAL):  Call print_fault.
+       (POP_FRAME):  Now works.
+
+       * tm-nindy960.h:  Break this off tm-i960.h.  NINDY-specific
+       option parsing and startup; STACK_END_ADDR, FRAME_CHAIN_VALID,
+       BREAKPOINT, and DECR_PC_AFTER_BREAK are here.
+       (ADDITIONAL_OPTION_HANDLER):  use target_load, not
+       target_add_file.
+       
+       * tm-vxworks960.h:  Break this off tm-i960.h.  VxGDB specific
+       startup; DECR_PC_AFTER_BREAK, and FRAME_CHAIN_VALID are here.
+
+       * valarith.c (value_subscripted_rvalue):  Avoid handling
+       floats and doubles specially; it gave alignment errors.  Lint.
+
+       * valops.c (value_of_variable, value_of_this):  Error if unknown
+       value.
+
+       * valprint.c (print_floating):  Bcopy rather than pointer-deref,
+       to avoid alignment problems.
+       (value_print):  Handle unknown value address.
+       (cplus_val_print):  Two args are ignored; remove them.  Change caller.
+       (val_print):  Use unpack_long rather than pointer-deref.
+
+       * values.c:  Lint.
+       (unpack_long, unpack_double):  Use bcopy rather than pointer-deref
+       to avoid alignment problems.
+       (value_being_returned):  Error if return value unknown.
+       (set_return_value):  Add bogosity warning, FIXME.        *
+
+       * TODO:  A woman's work is never done.
+
+       * Makefile.dist:  Distribute REMOTE_OBS into tconfig files.
+       Separate INCLUDE_CFLAGS for use with lint.  Add LINTFILES.
+       Add ieee-float.o to OBS.
+       * tconfig/{nindy960,vxworks68,vxworks960}:  Include the desired
+       REMOTE_OBS remote-interface files in the TDEPFILES and TM_FILE.
+       * tconfig/i960:  FIXME.  Half-merge, produce warning if config'd.
+
+       Changes to generalize the VxWorks RPC protocol slightly, to handle
+       i960 as well as 68000.
+
+       * vx-share/dbgRpcLib.h (VX_SOURCE_STEP):  Add.
+       * vx-share/reg.h:  Produce i960 regs #ifdef I80960
+       * vx-share/xdr_ptrace.c:  Skip FPA registers if 960.
+       * vx-share/xdr_rdb.h:  Add SOURCE_STEP struct and xdr decl.
+       * vx-share/xdr_rdb.c:  Add xdr_SOURCE_STEP routine.
+       * vx-share/xdr_regs.c:  Add xdr_regs, xdr_fp_status, xdr_ext_fp
+       for i960.  Change xdr_vectors to xdr_opaques for 68k registers,
+       so they will move in target byte order rather than network
+       byte order (happens to be the same).    
+
+Mon Feb 25 03:41:44 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * tm-convex.h (END_OF_TEXT_DEFAULT):  Remove #if 0'd block.
+
+Sun Feb 24 00:55:53 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * am29k-pinsn.c, 
+       Add contribution lines to various files, showing where they
+       came from.
+
+       * breakpoint.c (break_insn, check_break_insn_size,
+       read_memory_nobpt):  Remove to mem-break.c.
+
+       * xm-*.h, param-no-tm.h, tm-29k.h, valprint.c:  Change BYTE_ORDER to
+       HOST_BYTE_ORDER.
+
+       * tm-29k.h (STAB_REG_TO_REGNUM):  Warn user if symbol table
+       entry has bad register number.  This change is not
+       tested in this release, FIXME.
+
+       * frame.h:  Eliminate Frame_unknown in favor of a simple zero.
+       tm-vax.h:  Ditto.
+
+       * value.h:  Force value's contents field to be aligned to hold
+       at least a double or a long long (if supported).  This avoids
+       doing bcopy's in and out of the contents field.
+
+       (step_1):  Avoid coredump under obscure circumstances when we
+       have no frame.
+
+       * symtab.h (misc_info):  Add field to misc function vector for
+       any kind of cached information the target code desires.  AMD
+       29000 uses this to avoid repeating examine_function_prologue's.
+
+       * coffread.c:  Lint.  Remove static symfile, read_section_header.
+       core.c (have_core_file_p):  Lint: remove.
+       expprint.c (print_subexp):  Lint.
+       infptrace.c, valops.c, valprint.c:  lint.
+
+       Roll in changes from vxgdb-5.0.1:
+
+       * symtab.h:  Comment byte order of each address class.  Add
+       LOC_LOCAL_ARG for frame-relative args (960).
+       expread.y:  Use LOC_LOCAL_ARG where LOC_ARG is used.
+       symtab.c, symmisc.c:  ditto.
+       
+       * infrun.c (init_wait_for_inferior):  Clear stop_signal.
+
+       * remote.c (remote_resume):  Error if resume with a signal.
+
+       * symfile.c (prim_record_misc_function):  Clear misc_info.
+       (fill_in_vptr_fieldno):  Check stub type of arg.
+
+       * valops.c (value_cast):  Avoid looking up names of types whose
+       name we don't know, to prevent coredump.  Sun CC produces typedef
+       rtx and the name of *rtx is zero...
+
+Mon Feb 18 21:16:25 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Roll in changes from final AMD 29000 port (Tiemann).
+
+       tconfig/am29k:  Add COFF_ENCAPSULATE and TARGET=TARGET_AM29K
+       for ../include/a.out.encap.h.  This might not work now that BFD
+       is separately compiled.  Instead, BFD support for encap will have
+       to translate machine type 29k into the right COFF_MAGIC.
+       
+       * infcmd.c: Remove references to inferior_pid that aren't used
+       in actual ptrace calls; use target_has_execution, etc.
+       (have_inferior_p):  Remove function.
+       (program_info):  Print target info rather than "process number";
+       avoid gratuitous messages unless from_tty.
+       (run_stack_dummy, finish_command):  Set proceed_to_finish.
+       infrun.c: Remove inferior_pid refs.  Decl & init proceed_to_finish.
+       main.c:  Lint.  Lose have_inferior_p().
+       inferior.h (have_inferior_p):  Remove, lint.
+       (proceed_to_finish):  Add flag to ask that all regs be saved
+       by normal_stop, for the few commands that need it, speeding up
+       serial I/O.  Add comments to stop_registers.
+
+       * remote-eb.c:  Remove newline from breakpoint message we grep
+       for.  Never time out when running the user program.
+       
+
+
+Wed Feb 13 15:34:40 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Roll in changes from vxgdb-5.0.1:
+
+       * dbxread.c (read_dbx_symtab): If we encounter a "FORTRAN COMMON"
+       symbol in its raw form, we are processing an unlinked ".o" file.
+       See if the target environment has assigned it an address, using
+       target_lookup_symbol (VxWorks does), and enter it into the symtab
+       that way.
+
+       * tm-vxworks.h (FRAME_CHAIN, FRAME_CHAIN_VALID):  Override usual
+       68k versions for a simpler version that assumes zero FP at bottom.
+       Fixes bug of truncated stack reports.
+
+       * target.h (target_lookup_symbol):  Define this routine's args
+       and result, finally.
+
+       * target.c (nosymbol):  Default routine for target_lookup_symbol.
+       (target_default):  Default lookup_symbol and call_function too.
+       (files_info):  Only print has_all_memory warning if a non-dummy
+       target follows.
+
+       * remote-vx.c (vx_read_register, vx_convert_to_virtual,
+       vx_convert_from_virtual): If target does not have floating point,
+       zero register "values", and avoid doing cross-net conversions.
+       (vx_lookup_symbol):  Rename net_lookup_symbol, add to vectors.
+       (vx_open):  Rearrange code that attaches to target and reads
+       symbols for all loaded modules, to work if some of the modules
+       are not accessible.  Add symbol_stub() and add_symbol_stub()
+       as callbacks from catch_errors().  Allow connect attempt to be
+       interrupted painlessly with ^C (FIXME, there are still some bugs
+       if the interrupt happens during symbol reading.).  Print
+       final message with puts_filtered, since symbol messages are
+       now filtered too.
+
+       Misc cleanup:
+
+       * main.c (catch_errors):  Only print errstring if non-null.
+       (command_loop):  Avoid an ioctl per command to test ISATTY.
+
+       * remote-vx.c (net_load):  make static; avoid sophomoric msg.
+       (vx_xfer_memory):  Return correct result!
+       (vx_files_info):  Indicate whether target has float or not.
+       (vx_lookup_symbol):  Complain, not error, if target gone.
+       (vx_open):  Print "Connected" msg before disabling immediate-quit.
+       [FIXME:  lookup_symbol and vx_open changes need testing.]
+
+       target.c, remote-eb.c, inftarg.c, am29k-opcode.h, target.h,
+       tm-29k.h, tmm-vxworks68.h, symfile.c, gdb-int.texinfo: Add
+       contributor lines and update copyrights to 1991.
+
+       Changes from an attempted H-PUX host port:
+
+       * infptrace.c (PT_ATTACH, PT_DETACH):  Handle HP/UX, which 
+       defines PT_ATTACH and PT_DETACH but not PT_KILL.
+       * remote-eb.c (eb_open):  Misplaced endif kills sysv H/PUX.
+       * remote-vx.c: include <sys/time.h> for HPUX.
+       * hp300hpux-xdep.c (fetch_core_registers):  Rewrite old
+       "core_file_command" routine to BFD regime.  May not work yet.
+
+       Attempted port of "gdb-3.4 Van Jacobson xgdb" to modern gdb.
+
+       * xgdb.c: Replace X10 version with some VJ version.
+       (FIXME:  Its copyright assignment is not on record.)
+       * xgdb.c:  Update include files to X11R4 (Xaw crud).
+       (xgdb_display_source, create_text_widget): fix call to
+       get_filename_and_charpos.  Rewack source window stuff for X11R4
+       (gleaned from include files, and "nm's" of binary libraries, since
+       I had no doc available).
+       (append_selection, append_selection_word): Disable with FIXME
+       since R4 changed interface here.
+       (create_buttons):  Add back the old set of buttons.
+       (xgdb_create_window):  Fix call to XtInitialize (&argc not argc).
+
+       * Makefile.dist (xgdb, xgdb-init.c):  Update for X11R4 on Suns.
+       Roll VERSION to 3.94 (not yet final though).
+
+Sat Feb  9 09:46:25 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * obstack.h (obstack_ptr_grow, obstack_ptr_grow_fast,
+       obstack_int_grow, obstack_int_grow_fast):  Eliminate
+       cast on left of assignment, which gives MIPS cc fits and is
+       not Standard C.
+
+       * sparc-pinsn.c (print_insn): Eliminate 'set' test, subsumed by
+       F_ALIAS.  Use printf, not fprintf, when not passing a file
+       pointer...
+       (compare_opcodes): Check that identical instructions have
+       identical opcodes, complain otherwise.
+
+       * sparc-opcode.h (st %fsr):  Fix opcode "lose" mask.  This
+       was reported by Roland McGrath.
+       (unimp): Only match if exactly zero instruction.  (Roland)
+       (branches and traps):  Generate all variations of these
+       instructions with macros, based on a single call that defines
+       each condition name and its binary representation.
+       (set):  Turn on alias bit, to avoid test in sparc-pinsn.c.
+
+       * valprint.c (val_print_fields):  Take, and use, format parameter.
+       This means that "p/x struct" again prints the elements in the
+       desired format.  Changed callers.
+
+       * stack.c (frame_info):  Use filtered output, and indicate wrap
+       points.  Remove kludgy formatting designed to avoid line wrap.
+
+       * utils.c (wrap_here):  If the line is already full (because
+       we had printed a long indent or long wrapped string), do an
+       immediate newline-and-indent.
+
+       * m68k-pinsn.c (print_insn_arg): Bugfix from
+       ntmtv!thompson@ames.arc.nasa.gov (Mike Thompson): 'bkpt #0'
+       instruction is incorrectly disassembled as bkpt #8.
+
+       * dbxread.c (end_psymtab): Bugfix from Peter Schauer
+       <pesrem@regent.e-technik.tu-muenchen.de>: If you want to set a
+       breakpoint in a *.y file gdb will say Reading in symbols for *.y...
+       and then will dump core (sometimes). I traced it back to an
+       uninitialized symfile_name in psymtab_to_symtab.
+       (const_vol_complaint):  Add quotes to message.
+       (define_symbol):  Only believe line number if gcc_compiled.
+       Avoid allocating symbol if we will not return it.
+
+       Add target strata support so that newly established targets go
+       into their right place in the target stack (e.g. a new exec file
+       doesn't wipe out the ability to access the running process).
+
+       * target.h, core.c, exec.c, inftarg.c, remote-eb.c,
+       remote-nindy.c, remote-vx.c, remote.c, target.c:  Add to_stratum
+       and initialize it properly in all the targets.
+
+       * target.h:  Document strata.  Change return type of push_target.
+
+       * target.c (nomemory):  new function for dummy memory access.
+       (tcomplain):  Rename complain, now also used in symfile.c.
+       (push_target):  Push targets within strata.  New return value shows
+       whether new target is on top of stack or not.  Always keep dummy
+       target on stack.
+       (target_files_info):  Ignore dummy target.
+
+       * core.c (core_open):  Warn user, and skip accessing file, if the
+       core target is not the topmost target in the stack.
+       * remote-nindy.c (nindy_create_inferior):  Avoid unpush_target, now
+       already handled.
+
+       * remote-vx.c:  Remove vx_prepare_to_store from vxworks memory
+       target_ops, it doesn't belong there since we have no regs there.
+       Change name of target from machine => memory to clarify.
+
+Thu Feb  7 16:32:09 1991  John Gilmore  (gnu at spiff.cygnus.com)
+
+       * Freeze version 3.93 for release.
+
+       * Makefile.dist:  Handle vx-share and nindy-share subdirs
+       properly when building gdb.tar.Z.
+
+       * symtab.c:  lint; add no_symtab_msg to consolidate the messages
+       printed in various places, so I could change just one copy.
+
+       * dbxread.c, coffread.c:  Change references to bfd->iostream
+       to cast to FILE *, now that BFD avoids needing types defined
+       in other header files.
+
+Tue Feb  5 21:39:35 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * command.c, dbxread.c, expprint.c, infcmd.c, infptrace.c,
+       infrun.c, printcmd.c, remote-nindy.c, source.c, sparc-tdep.c,
+       sparc-xdep.c, symfile.h, symmisc.c, utils.c, valprint.c: Lint
+       (actually gcc -Wall).
+
+       * dbxread.c:  Remove first_global_sym, last_global_sym, since
+       they are never referenced.
+
+       * defs.h (baud_rate):  Declare.
+       main.c: Define it, and add the -b option to set it.
+
+       * gdb-int.texinfo:  Add text on how to define a new host or target
+       architecture, prompted by Per Bothner's questions about MIPS
+       support.
+
+       * gdb.texinfo:  Document "complaints".  Change doc of -q since
+       gdb no longer prints the copyright and blurb if you specify a file
+       name to be debugged (just like Emacs).  Add doc for Nindy-specific
+       command line flags for specifying target serial port and such.
+       Update copyright to 1991.
+
+       * gdbcore.h:  Remove a large mass of now-useless crud, since BFD
+       has taken over for us the job of ripping up executable files.  The
+       crud caused Per Bothner's port to not compile.
+
+       * infrun.c (normal_stop):  Avoid printing "Program exited
+       normally" if we are in batch mode.  This allows a GDB which
+       executes a program on a target system, to behave like a Unix
+       command (input from stdin, output to stdout, no extraneous
+       output).
+
+       * main.c (main):  Allow additional machine-dependent command line
+       options to be specified with the ADDITIONAL_OPTIONS,
+       ADDITIONAL_OPTION_CASES, ADDITIONAL_OPTION_HELP, and
+       ADDITIONAL_OPTION_HANDLER macros.  Also allow machine-dependent
+       processing to occur just before the main loop with
+       BEFORE_MAIN_LOOP_HOOK.  
+       (main):  If a "core file" argument is specified, and it is not a
+       core file, try it as a process ID to attach.  
+       (symbol_completion_function):  Attempt to cope with 
+       "show screen-" TAB, not very successfully.  This needs more work,
+       FIXME.
+       (batch_file):  New function, returns whether we are reading
+       commands from an interactive tty on stdin, or from somewhere else.
+       Called by normal_stop since it doesn't get from_tty passed down
+       to it like many commands do.
+
+       * remote-nindy.c:  Handle command line options for nindy
+       connection.
+       (nindy_before_main_loop):  Prompt user for tty name if they
+       don't specify it before getting to the interactive command loop.
+
+       * tm-i960.c:  Add ADDITIONAL_OPTIONS, etc, to handle -O, -brk,
+       and -r command line options.  Also add hook before main loop
+       to make it easy to specify a tty.
+
+       * TODO:  More things to do, one done.
+
+Mon Feb  4 23:57:39 1991  John Gilmore and Mike Tiemann  (at cygint.cygnus.com)
+
+       * dbxread.c:  Make complaint() calls pass pointer, not struct.
+       Add complaints about badly formatted C++ type information
+       (const/volatile indicator, and parse errors resulting in
+       error_type).  Fix C++ virtual member fn comment.
+       (read_struct_type):  Avoid bumping pointer if we got a parse
+       error; this prevents our walking beyond the end of a string.
+       Terminate loop on null char as well as semicolon.
+       (process_one_symbol):  Fix the LBRAC fix so that it uses the
+       last previous SLINE, FUN, or SO record's PC address.  C++ debug
+       symbols did not have SLINE records in a useful order compared
+       to the LBRAC records.
+       (define_symbol):  Handle "catch" records.
+
+       * symtab.c (check_stub_type):  Added new complain
+       `stub_noname_complain' and added a consistency check to
+       keep the debugger from crashing when finishing from an
+       exception frame.  A real fix will be needed later.
+
+Sat Feb  2 10:43:05 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * infcmd.c (attach_command):  Make global.
+
+       * Makefile.dist (REMOTE_OBS):  Make these compile by default,
+       but make them easy to comment out.  Perhaps later they should
+       be enabled by what CPU you configure for?  FIXME.
+       (VERSION):  Roll to 3.93.
+       (pinsn.o):  Remove rule for obsolete file.
+       (dbxread.o,coffread.o,mipsread.o):  Use ${srcdir} explicitly.
+
+       Run down a problem that manifested by printing the wrong function
+       name in stack traces of read_ofile_symtab.  Turned out that the 
+       problem was the SunOS 4.1.1 (and previous) C compiler outputs
+       the LBRAC symbol with an address in the *data* segment, which
+       blew our binary search through the blocks.
+
+       * dbxread.c: Use the complain() facility consistently to bitch
+       about problems in the symbol file we are reading.
+       (finish_block):  Add code to check the nesting of the blocks;
+       complain and Procrust them to fit if wrong.
+       (make_blockvector):  Check the order of the blocks, complain 
+       [but don't cope] if wrong.
+       (process_one_symbol):  ifndef SUN_FIXED_LBRAC_BUG, check LBRAC
+       symbols to be sure their PC value is greater than the last SLINE
+       (line number) symbol we've seen, complaining and adopting the
+       SLINE PC value if wrong.
+
+       * symfile.h (struct complaint, complaint_root, complain, 
+       clear_complaints):  Add.
+       * symfile.c (complain, complaint_root, clear_complaints):  Add
+       facility to deal with non-fatal complaints and to regularize their
+       suppression.
+       (symbol_file_add):  Clear complaint counters to allow new complaints.
+       (initialize_symfile):  Add 'set complaints' and 'show complaints'.
+
+       * dbxread.c (dbx_symfile_read):  Remember the address and size
+       of the string table for the main symbol file, so we won't read it
+       more than once.
+       (dbx_psymtab_to_symtab):  Fix the check for main symbol file,
+       to avoid reading the string table yet again.  Lint.
+       (throughout):  Improve filtered output, including word wrap.
+       (read_range_type):  Improve Bothner's fix to handle other types too.
+
+       * utils.c:  Improve line wrap implementation.  Handle unlimited
+       width by making chars_per_line unsigned.
+       (puts_filtered):  New, easy, function.  
+
+       * defs.h (puts_filtered):  add.
+
+       * mipsread.c (compare_symbols, sort_symtab):  Remove these fns,
+       call the identical sort_symtab_syms() in symfile.c instead.
+
+       * expread.y:  Suggest the `file' command rather than `symbol-file'.
+
+       * command.h (enum var_types):  Add zinteger for seroable
+       unsigned integer.
+       * command.c (do_setshow_command):  Handle var_zinteger.  Restructure
+       nested if's into a switch.
+
+       * breakpoint.c (bpstat_print): If bpstat "print" flag is not set,
+       we did not stop because of a breakpoint (it must have been for
+       some other reason, like a "stepi"), so don't print anything.
+
+       * symtab.c: Include <sys/types.h> all the time.  Now that BFD
+       doesn't include <sys/types.h>, old SunOS's require it for
+       <sys/stat.h>.
+
+Sat Feb  2 10:39:15 1991  Per Bothner  (bothner@cs.wisc.edu)
+
+       A test port of gdb-3.92.6 to the Sony NEWS.
+
+       * Makefile.dist
+       Don't normally link in remote- or vx stuff.
+       Some of it doesn't compile, and it wastes space for 99% of the users.
+       Remove reference to no-longer-used HAVE_VPRINTF.
+       Fixed BFD_DEP typo to BFD_DIR.
+       * dbxread.c
+       Fix cast in arg to bfd_h_getlong.
+       Make char *prefix be const.
+       Fix how certain range types are mapped into builtin unsigned int types.
+       * infrun.c
+       Remove 2 #includes. They cause errors (on Sony, at least),
+       and aren't needed (they wern't in earlier versions).
+       * printcmd.c
+       print_address_symbolic should never demangle labels
+       (since it prints *assembler-level* labels).
+
+              [This was superseded by the change to printcmd below.]
+
+       * utils.c
+       Add some "volatile" return types to avoid warnings.
+       If MISSING_VPRINTF add vprintf function and not just macro
+       (since vprintf is used in printcmd.c).
+       * valprint.c
+       Unless __GNUC__, use obstack_grow instead of obstack_ptr_grow.
+       (The latter isn't grokked by some PCC-based compilers.)
+
+            [This change is in abeyance, we prefer to fix obstack_ptr_grow.]
+
+       Make chunk size of dont_print_obstack 32*4 instead of default 4096.
+       * nindy-share/coffstrip.c
+       Added some forward declarations (otherwise, gcc complains
+       about implicit extern redefined as static).
+
+Sun Jan 20 02:38:19 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Changes inspired by Per Bothner:
+       * printcmd.c (print_address_symbolic):  Take additional parameter
+       specifying whether to demangle.
+       (print_address):  Pass in asm_demangle to control demangling.
+       (print_address_demangle):  New fn, takes explicit arg to control
+       demangling.
+       * utils.c:  Add new vars demangle and asm_demangle, and let them
+       be set and shown.
+       (fputs_demangled):  If !demangle, just print the argument.
+       (fprint_symbol):  If !demangle, just print raw symbol.
+       * valprint.c (val_print):  Call print_address_demangle rather than
+       print_address, to cause demangling to depend on the global
+       rather than assembler-level demangling setting.
+       * WHATS.NEW, gdb.texinfo:  Document.
+
+       * main.c (show_command):  Show all settings if no arg.
+       (initialize_main):  Make "info set" the same as naked "show".
+       * command.c (cmd_show_list):  Handle prefix commands in the
+       list, and print the name of the setting as well as its English
+       description and value.
+
+       Allow gdb functions to specify where a line should wrap if it
+       exceeds the size of a terminal line.  Use it to make the output
+       prettier.
+       * utils.c (set_screen_width_command):  New fn, mallocs a buffer
+       of the right size when screen width changes.
+       (set_screensize_command, screensize_info):  Remove #if 0'd fns.
+       (wrap_here):  New fn, indicates a point in the output where we
+       should wrap the line rather than just letting it overflow at a
+       random place.
+       (fputs_filtered):  Implement wrapping.
+       (n_spaces):  New fn, returns a pointer to N spaces.
+       (print_spaces_filtered):  Use n_spaces.
+       * defs.h (n_spaces):  Declare.
+       * stack.c (print_frame_info):  Wrap with 4-space indent after
+       fn name and before filename and line number.
+       * printcmd.c (print_frame_args):  Wrap with 4-space indent
+       before each argument name is printed.
+       * valprint.c (value_print):  Wrap with no indentation before
+       each repetition.
+       (val_print_fields):  Wrap with indentation relative to nesting
+       level before each field name.
+       (val_print):  Wrap with nesting indentation before array elements.
+       * command.c (do_setshow_command):  Avoid extra newlines,
+       wrap with 4-space indent around values printed, end with period.
+       * WHATS.NEW, gdb.texinfo, gdb-int.texinfo:  Document.
+
+       * breakpoint.c (breakpoint_1):  Implement addressprint for
+       "info breakpoints" display.  Change file name and line number
+       format to " at file:nnn" rather than " (file line nnn)".
+       * gdb.texinfo:  Document.
+
+
+Fri Jan 18 07:21:25 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Frozen for gdb-3.92.6 release.
+
+       README, WHATS.NEW:  Update for 3.92.6 release.
+
+       tconfig/{altos, i386v, i386v32, m88k, umax}:  Eliminate
+       coffread.o from configs since it is now built by default.
+       tconfig/{3b1, altosgas, arm, convex, hp300bsd, hp300hpux,
+       i386v-g, i386v32-g, isi, merlin, news, news1000, np1, pn,
+       pyramid, symmetry, vax, vxworks68}:  Eliminate dbxread.o
+       from configs since it is now built by default.
+
+       Makefile.dist: Update for release 3.92.6.  Handle files that
+       have been moved to ../include, ../getopt, or ../bfd.  Add
+       saber.suppress and tests directory.  Add config.status to
+       the release (it will say "none").
+
+       coredep.c:  Minor formatting fixes.
+
+       These changes were made in early December but only checked in now:
+       * nindy-share/Onindy.c, nindy-share/coffstrip.c,
+       nindy-share/nindy.c:  lint
+       * nindy-share/nindy.c (ninStopWhy):  Don't byteswap the 
+       register values coming back from the target; we store values
+       in target byte order everywhere.
+
+Wed Jan 16 19:01:37 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * am29k-opcode.h, am29k-pinsn.c:  Add 29050 opcodes.
+
+       * valprint.c (cplus_val_print, val_print_fields):  New functions,
+       which print C++ objects.  They conspire to avoid printing a
+       virtual base class more than once, following all the twists and
+       turns of C++ virtual base rules.
+       (val_print):  Call the above rather than do it by hand.
+
+       * symfile.c (symbol_file_add):  Only reset symfile_mtime for main
+       symbol file, not for added files like shared libs.  This really
+       needs to be generalized to a timestamp per file.
+
+       * core.c (cleanup_core):  Avoid coredump if no core file.
+       
+       * config.gdb:  Accept -host or -target in place of +host or
+       +target.
+
+       * coffread.c (find_linenos):  Avoid desupported BFD interface
+       to line numbers.  We still read them manually rather than using
+       BFD's "generic" features.
+
+       * gdbrc.tex, threecol.tex:  Add GDB reference card and its
+       formatting code.
+       Makefile.dist:  Add refcard to OTHERS list for creating tar files.
+
+       * Makefile.dist:  Eliminate use of $< in explicit targets.
+
+       * readline/Makefile:  Use $< rather than $*.c, which does not
+       include the VPATH in GNU Make.
+
+       * tconfig/i960-bout, tconfig/i960-coff:  These are identical
+       copies of tconfig/i960, added for global configuration
+       compatability.  All i960 versions can read both coff and b.out.
+
+       * tm-88k.h:  Fix multiline macro that lacked \'s.  Remove
+       COFF_FORMAT and COFF_CHECK_X_ZEROES since these are now handled
+       automaticaly.
+
+       * TODO:  Think of more things to do.
+
+Wed Jan  2 19:09:29 1991  John Gilmore  (gnu at spiff.cygnus.com)
+
+       tconfig/{am29k,i960,sun2*,sun3*,sun4*}:  Eliminate config
+       of sdb versus dbx debug symbols.  Add kludge for 68881 80-bit to
+       64-bit float conversion.
+
+       tconfig/sun4, tconfig/sun3, xconfig/sun4, xconfig/sun3:  Make
+       equivalent to sun?os4 so global config works.
+
+Wed Jan  2 18:20:51 1991  John Gilmore  (gnu at spiff.cygnus.com)
+
+       Fix from Eberhard Mattes <mattes@azu.informatik.uni-stuttgart.de>
+       
+       * main.c:  Only declare linesize once; declare pagesize not at
+       all, since it is never used.
+       (main):  Clear newly allocated line before it is used.
+
+Fri Dec 28 00:13:42 1990  John Gilmore  (gnu at cygint)
+
+       Further stabilization for the Intel 960.
+
+       * Makefile.dist: Parameterize the location of the "include"
+       and "bfd" directories, as well as "getopt".  Add symfile.c.
+       Link in both dbxread and coffread.  Fix up "make depend" to
+       rewack the locations of include, bfd, and getopt in its output.
+
+       * README:  Document moving include files, improve some of
+       the other doc.
+
+       * coffread.c:  Move common code out to symfile.c.  Change
+       symbol_file_command style interface to use new *_symfile_init
+       and *_symfile_read interface under BFD.  Use BFD internal
+       info to locate line table, symbols, etc.
+
+       * core.c (core_fetch_registers):  Rename to get_core_registers
+       to avoid confusion with fetch_core_registers.
+       (register_addr):  Move to coredep.c, which is already machine
+       dependent.  This leaves core.c pretty clean of dependencies.
+
+       * coredep.c (register_addr):  Accept this routine from core.c.
+
+       * dbxread.c: Move common code (with coffread.c, etc) into new
+       symfile.c.  Each psymtab now contains a pointer to the
+       format-dependent function that knows how to read it in.  Make
+       some things static.  
+       (dbx_psymtab_to_symtab): Renamed from psymtab_to_symtab_2.
+       (process_one_symbol): Add code to complain about a "compiler bug
+       we muzzle here", if we actually see it.
+
+       * eval.c (evaluate_subexp):  Insert missing "break" statements
+       in code that determines whether a variable is an lvalue in
+       memory, register, or whatever.  I detected this via a compiler
+       bug in which it *almost* mashed out the whole switch statement.
+
+       * gdb-int.texinfo:  Add minor sections on configuring gdb for
+       release, and about the README file.
+
+       * infcmd.c (registers_info):  Fix formatting somewhat.  Still
+       not as pretty as before, but it handles byte swapping.
+
+       * remote-nindy.c: If data cache routines are interrupted while
+       waiting for the remote end, be sure that any uninitialized cache
+       blocks are on the free list, not on the valid list!
+
+       * symfile.h: Flesh out this header file with all the various
+       routines and variables that have been merged in from dbxread.c
+       coffread.c, and symtab.c to symfile.c.
+
+       * symfile.c: New file, containing code common to dbxread.c,
+       coffread.c, and some code from symtab.c.  All generic code for
+       reading symbol files should be in here now.
+       (unrecord_misc_function):  Remove unused function.
+
+       * symtab.h:  Remove file-reading things to symfile.h.
+
+       * symtab.c:  Remove file-reading things to symfile.c.
+
+       * tm-i960.h:  Fix FRAME_CHAIN types; define PRINT_RANDOM_SIGNAL
+       to decode i960 fault types.
+
+       * target.h, remote.c, remote-eb.c, remote-vx.c, remote-nindy.c,
+       target.c: Change type of the "resume" function from int to void,
+       since its result was never used.
+
+Sat Dec 22 02:51:40 1990  John Gilmore  (gnu at cygint)
+
+       * main.c:  Replace "stupid" with "caution"; you now "set caution
+       on or off".
+
+       * printcmd.c (print_scalar_formatted):  Fix typo in 'g' format
+
+       * infcmd.c (do_registers_info):  Call val_print to deal with the
+       byte order of the registers being printed.  FIXME, this makes
+       the formatting of the output uglier.
+
+       * infcmd.c (wait_for_inferior):  If PRINT_RANDOM_SIGNAL is
+       defined, call it for signals the debugger doesn't itself use.
+       The i960 uses this for more detailed fault information.
+
+       * remote.c (remote_open):  If arg is null, print help rather than
+       dumping core.
+
+       * sparc-xdep.c (register_valid):  Avoid declaring size, since
+       various modules will think of various sizes depending on the
+       architecture of their tm-file.  FIXME, we need protection against
+       actually entering one of those modules, which would clobber
+       storage if not for the target architecture compiled into gdb.
+
+       * stack.c (up_command, down_command):  Always print the frame
+       you arrive at.
+       (up_silently_command, down_silently_command):  New commands
+       for use in scripts.
+
+       * i960-pinsn.c (reg), i960-tdep.c:  Lint.
+
+       * i960-tdep.c (i960_frame_chain_valid): Lookup_symbol now takes
+       more parameters than it used to.
+
+       * findvar.c (registers):  Increase slop to 256 bytes, which should
+       protect us against even most RISC machines with large register
+       sets.
+       (locate_var_value):  Move declaration inside related ifdef.
+
+       * remote-nindy.c ():  Use TIOCSETN rather than TIOCSETP
+       throughout, to avoid throwing away buffered input from the board.
+       (nindy_wait):  Supply_register takes addr_of_value, not value.
+       (i960_print_fault):  Renamed from i80960_fault.
+       (nindy_fetch_registers):  Avoid have_regs stuff, just get them.
+       (nindy_store_registers):  Avoid regs_changed stuff, just stuff
+       them.
+       (nindy_create_inferior):  Don't bother to write PC_REGNUM since
+       we can set the PC in the call to proceed().  Unpush nindy_ops
+       before pushing it on top, to avoid message to user.  Eliminate
+       commentary from Unix machines that just misleads here.
+       (reset_command):  Fix error message to suggest target command.
+       
+Wed Dec 19 11:03:56 1990  John Gilmore  (gnu at cygint)
+
+       Release 3.92.5 as frozen.
+
+       Stabilize the merged release...with help from lint, Saber C,
+       gcc -W, etc.
+
+       Everywhere:  Add include files needed to declare return types
+       of functions called.
+
+       * gdb.texinfo:  Roland Pesch is documenting gdb, glory be!
+
+       * breakpoint.h:  Add undeclared breakpoint functions, and some
+       functions for display handling since I couldn't think of a better
+       .h to put them in.
+
+       * breakpoint.c (insert_breakpoints):  Make code for disabling
+       shared library bkpts more likely to work.  It's used when we
+       rerun a program and stop before the shared library has been
+       mapped in.
+       (breakpoint_cond_eval, bpstat_stop_status):  Pass arg as int,
+       cast from pointer, so it squeezes through catch_errors.
+       (bpstat_stop_status):  Fix logic broken some time ago.  We now
+       always create a bpstat if the stop address matches a breakpoint,
+       even if we don't stop there -- just like the old code used to do
+       before I got my fingers into it (sigh).
+       (breakpoint_1):  Print "ignore count" after "stop only if"
+       condition, since that's how it actually works.
+       (mention):  Handle watchpoints as well as breakpoints.
+       (watch_command):  use set_raw_breakpoint and mention to do most 
+       of the work (and initialize all the fields!).  Only pass one
+       arg to parse_c_expression, since that's all it takes.
+
+       * command.c (not_just_help_class_command):  Rename arg to args
+       since we ignore "unused argument" warnings on vars named "args".
+       inflow.c (child_terminal_info):  ditto.
+       infptrace.c (kill_inferior):  ditto
+       main.c (catch_errors, version_info, quit_command, pwd_command,
+       source_command, dump_me_command, editing_info,
+       set_history_size_command, set_history, show_history,
+       set_verbose): ditto
+       stack.c (locals_info):  ditto
+       target.c (target_files_info):  ditto
+       valprint.c (set_input_radix, set_output_radix):  ditto
+
+       * core.c:  Remove old variables for handling core and exec file
+       sections (data_start, data_end, stack_start, stack_end,
+       reg_stack_start, reg_stack_end, reg_stack_offset, text_start,
+       text_end, exec_data_start, exec_data_end, text_offset,
+       exec_data_offset, data_offset, stack_offset).  They're
+       superseded the more general build_section_table and
+       xfer_memory.
+       (get_exec_file):  Mention the `file' command.
+       (read_memory_check):  Rename to memory_error, and only call it
+       in the case of an actual error.
+       (read_memory, write_memory):  call memory_error.
+       (core_fetch_registers):  Register section name is ".reg".
+
+       coredep.c:  Remove a bunch of crud now that all this file does
+       is pull the registers out of a core file.
+       (fetch_core_registers):  Rewrite to actually work, I hope.
+
+       dbxread.c:  Use a.out.gnu.h, not system a.out, now.
+       Replace index() with strchr().  Remove all the pre-BFD macro
+       definitions for accessing the symbol file.
+       (struct dbx_symfile_info):  Encapsulate the information that
+       dbx_symfile_init needs to pass to dbx_symfile_read in this
+       struct.
+
+       (dbx_new_init, dbx_symfile_init, dbx_symfile_read,
+       dbx_symfile_discard): Rearrange symbol file reading to divide
+       the format-specific part from the format-independent part,
+       leaving the format-independent part such as file name expansion
+       and opening in symtab.c.  This replaces
+       partial_symbol_file_open and partial_symbol_file_read.
+       Symbol_file_read, add_file, add_file_target_command,
+       add_file_addr_command move to symtab.c.  Pass an explicit
+       "mainline" flag for when reading the main symbol table, rather
+       than relying on the offset address to be zero or nonzero.
+
+       (dbx_symfile_read): Don't allow void *'s to be printed as
+       typedefs.
+       (SWAP_SYMBOL):  Use bfd routines to byte-swap the symbols.
+       (ADD_PSYMBOL_TO_LIST):  Make the "function call rather than
+       macro" debug version really work.
+       (read_dbx_symtab):  Remove unref'd parameter inclink.
+       Avoid swapping N_SLINE symbols, for speed.
+       Merge N_TEXT!N_EXT case with the other external symbol
+       definitions' case. Add comments.
+       (start_psymtab):  Allocate the symfile name in the psymtab on
+       the psymbol_obstack, rather than using the caller's storage.
+       (end_psymtab): Only allocate a dependencies list if there are
+       more than zero.
+       (psymtab_to_symtab_2):  Use BFD when reopening file to read
+       its symbols for real.
+       (read_struct_type):  Add FIXME comments where it needs work
+       for C++ bogosity.
+       (read_huge_number):  Add FIXME about overflows.
+       (read_range_type):  Add FIXME about comparing a long to 1<<32.
+
+       * coffread.c:  Minor changes to move things closer to the new
+       regime with symtab.c and dbxread.c   Major work is still needed
+       here.
+
+       * exec.c (exec_file_command):  Remove old variables (see core.c
+       above).
+       (xfer_memory): If memory transfer is right at the end of a
+       section, don't lose.
+
+       * findvar.c (get_saved_register):  If value is in a real
+       register, LVAL is lval_register, not lval_memory.
+
+       frame.h:  Declare print_sel_frame and record_selected_frame.
+
+       gdb-int.texinfo:  New file, for GDB internals documentation.
+       Very simple, unformatted doc of cleanups is there for now.
+
+       gdbcore.h:  Remove obsolete variables that described a.out
+       section addresses and offsets.  (See core.c above.)
+       Declare fetch_core_registers and registers_fetched.
+
+       getopt.c:  Declare char *alloca(); even on SPARC.
+
+       infcmd.c (run_command):  Call target_kill rather than
+       kill_inferior. 
+       (step_command, next_command, stepi_command, nexti_command):
+       Declare from_tty parameter even though we don't use it.
+       (run_stack_dummy):  argument BUFFER is a char array, not
+       a pointer to REGISTER_TYPE.
+       (finish_command):  using_struct_return needed a value *, 
+       not a struct symbol *.
+
+       * infptrace.c (child_xfer_memory):  To avoid dependency on
+       where sections are in memory, try PT_WRITE_D and if that fails,
+       try PT_WRITE_I.  Most Unixes don't care which you use.
+
+       * infrun.c (step_resume_break_shadow):  Change to array to
+       match other breakpoint shadow storage.
+       (clear_proceed_status):  Pass address of bpstat to
+       bpstat_clear, not the bpstat itself.
+       (child_create_inferior):  FIXME comment about if the child
+       exits.
+       (start_inferior):  Remove old function.
+       (child_open):  Use target_kill rather than kill_inferior.
+       (wait_for_inferior):  Ditto.
+       (insert_step_breakpoint, remote_step_breakpoint):  Use
+       new step_resume_break_shadow.
+
+       * inftarg.c (child_wait):  If all child processes die,
+       pretend that the one being waited for exited with signal 42.
+
+       * main.c (command_line_input):  When scanning for comments,
+       don't coredump on unclosed quotes.
+       (quit_command):  Use target_kill rther than kill_inferior.
+       (_initialize_main):  Rename class_user from "user" to
+       "user-defined".
+
+       * printcmd.c (print_command_1):  Initialize "fmt" if no format
+       is specified by the user.
+       (print_frame_args):  Only add to args_printed if we are
+       actually fetching args from the stack (avoiding undefined
+       arg_size).
+       (_initialize_printcmd):  Remove bogus \{ from string.
+
+       * remote-eb.c (eb_open):  Avoid coredump on no argument.
+
+       * remote-nindy.c:  Bring out of Intel environment into new
+       target environment.  Remove all conditional compilation on
+       I80960.  Massive hacking throughout.
+       (nindy_xfer_inferior_memory):  New routine stolen from
+       infptrace.c.
+       (nindy_create_inferior):  New routine pieced together, probably
+       not quite working yet.
+       (nindy_ops):  New target_ops struct for nindy.
+
+       * remote-vx.c:  Use write_memory rather than target_write_memory
+       to get error checking.
+       (vx_add_file_command, vx_open): Use symbol_file_add rather than
+       add_file.
+       (vx_create_inferior):  Use target_terminal_ours...
+
+       * signame.c (_initialize_signame):  Always initialize, since
+       we need the table for things other than psignal.
+       
+       * solib.c (solib_add):  Use symbol_file_add, not add_file.
+       (solib_address):  Return boolean result rather than struct
+       pointer which nobody else knows the type of.
+
+       * sparc-tdep.c, valops.c:  Use write_memory rather than
+       target_write_memory, to get error checking.
+
+       * stack.c (locals_info, catch_info, args_info,
+       get_selected_block, frame_command, up_command): Use
+       target_has_stack, rather than have_inferior_p or
+       have_core_file_p.
+
+       * sun3-xdep.c (fetch_core_registers):  Rewrite for new BFD regime.
+
+       * symfile.h:  New file, defining the interface between the
+       generic and object-file-specific symbol reading code.
+
+       * symtab.c:  Move generic symbol-reading interface to symtab.c,
+       from dbxread.c, coffread.c, mipsread.c, etc.  Add symtab_fns
+       table to map BFD targets to symbol-reading modules in GDB.
+       Change index to strchr.
+       (lookup_struct_elt_type):  Use error() rather than hand-made
+       simulations thereof.
+       (lookup_partial_symbol):  Speedup slightly when length == 0.
+       (symbol_file_add):  New function.
+       (symbol_file_command):  Call it.
+       (symfile_open, symfile_init):  New function.
+       (add_file_target_command, add_file_addr_command): moved from
+       dbxread.c.
+
+       * target.c (target_command):  use target_kill.
+
+       * target.h (target_files_info):  Don't declare, never called
+       from outside.
+
+       * tm-sun2.h, tm-sun3.h (STACK_END_ADDR): Use system include
+       files to determine stack end address.
+
+       * valarith.c (value_x_binop, value_x_unop): Change error message
+       to be more useful.  Pass proper argument to value_struct_elt.
+
+       * valops.c (value_assign):  FIXME comment that long long 
+       bitfields will break here.
+
+       * Makefile.dist:  Add symfile.h, remote-nindy.c, remote-eb.c.
+       Update `make saber_gdb' to work better.
+
+       * TODO:  A woman's work is never done.
+
+       * cplus-dem.c, environ.c, inferior.h, infrun.c, inftarg.c,
+       main.c, obstack.c, printcmd.c, remote-eb.c, remote-nindy.c,
+       remote-vx.c, remote.c, solib.c, source.c, sparc-pinsn.c,
+       sparc-tdep.c, sparc-xdep.c, symmisc.c, symtab.c, symtab.h
+       target.c, terminal.h, tm-sparc.h, tm-sunos.h, utils.c,
+       valops.c, valprint.c, exec.c:  Lint.
+
+
+Wed Dec 12 23:44:15 1990  John Gilmore  (gnu at cygnus.com)
+
+       Continuing Intel 960 port merge of GDB.
+
+       * Makefile.dist:  Merge i960 "nindy-share" files.  Rename
+       malloc.h to gmalloc.h to avoid name conflicts in /usr/include.
+       Don't ship gdb.dvi in tar file.  Link gdb with init.o, not init.c.
+       Wack over "make depend" so it handles files in subdirectories
+       vx-share, nindy-share, bfd, and in the current directory.
+
+       * blockframe.c (get_prev_frame_info):  Remove fatal error
+       if stack not defined.
+
+       * core.c (core_open, core_detach):  New functions that handle
+       the old "core-file" command as "target core" and "detach" instead.
+       (core_file_command):  Call them.
+       (core_xfer_memory):  Use common routine xfer_memory.
+
+       * dbxread.c:  Include a.out.gnu.h, not system a.out.h.
+       dbxread now uses bfd for everything but symbol reading itself.
+       BFD internals are used to drag out the relevant file offsets.
+       (partial_symbol_file_open):  Change args all around for BFD.
+
+       * symtab.c: Rename "value" to "val" everywhere, so we can
+       #include "value.h".
+       (symbol_file_command):  New command, moved from dbxread.c
+       and coffread.c.  It uses BFD to read the file, then vectors
+       based on its type, to dbx or coff symbol readers.
+       * symtab.h:  Extern a few vars for symbol_file_command.
+
+       * target.h:  Breakpoint takes a char * save area, not a char **.
+
+       * valprint.c (val_print):  When unpacking bitfields, offset
+       the address in gdb of the value, if it is declared with a shorter
+       type.  Remove the last "runtime kludge test" of host byte order.
+
+       * utils.c:  Remove old my_bfd_read routine.
+
+       * stack.c (frame_info):  Use target_has_stack.  Print program counter
+       register's actual name rather than "pc", since it's called the
+       "ip" (instruction pointer) on the i960 (sigh).
+
+       * target.c (target_command):  Add command for selecting a target
+       type and calling its open routine.  This is used for initiating
+       communication with a particular target, in a generic way.
+
+       * tm-i960.h:  Update for modern gdb.  Remove semicolons from
+       various macros.  Handle reading struct return convention, and
+       error-out attempts to return structs with the "return" command.
+       Be sure gdb doesn't think we know how to call functions in the
+       inferior.
+
+       * i960-tdep.c:  Rename FRAME_CHAIN_VALID and FRAME_FIND_SAVED_REGS
+       to i960_xxx in lower case.
+       (arg_address):  Circumvent errors due to LOC_ARG_BLOCK
+       not being defined yet.
+
+       * remote.c (remote_open):  Call start_remote to initialize 
+       wait_for_inferior during open.
+       (remote_xfer_inferior_memory):  Return length written rather
+       than errno value.
+
+       * remote-vx.c (target_command -> vx_open):  Use new generic
+       target command.
+       * remote-eb.c, inftarg.c, exec.c: ditto.
+
+       * infrun.c:  Fix comments.
+       (attach_program -> child_open):  Use new generic target command.
+       (wait_for_inferior):  Clear saved register values before target_wait,
+       so target_wait can set some of them if convenient.
+
+       * infptrace.c (fetch_inferior_registers, store_inferior_registers):
+       Return success indicator, not void.
+       (child_xfer_memory):  Avoid fetching initial word if we'll
+       overwrite it anyway.
+
+       * infcmd.c (attach_command):  Use new generic target open routine.
+       (_initialize_infcmd):  Update doc on attach and detach commands.
+       (do_registers_info):  Merge in a byte-order problem as a FIXME
+       comment.
+
+       * findvar.c (find_saved_register):  Avoid problem in current frame.
+       (read_relative_register):  Ditto.
+       (write_register):  Convert byte order on the way out.
+
+       * exec.c (file_command):  Add.
+       (add_to_section_table, exec_command):  Use new bfd_map_over_sections.
+       (xfer_memory):  Common function between core_xfer_memory and
+       exec_xfer_memory.
+       (exec_xfer_memory):  Use it.
+
+       * pn-opcode.h:  Document that a "PN" is a Gould PowerNode.
+
+       * breakpoint.c, breakpoint.h, symtab.h, value.h, frame.h, utils.c,
+       valops.c, stack.c, target.c, sparc-xdep.c, source.c, printcmd.c,
+       infcmd.c, i960-pinsn.c, eval.c, defs.h:  lint and gcc -Wall.
+
+Sun Dec  2 16:45:06 1990  John Gilmore  (gnu at cygnus.com)
+
+       Merge Intel 960 port of gdb, continuing...
+
+       * dbxread.c (partial_symbol_file_open, partial_symbol_file_read,
+       symbol_file_command):  Pass from_tty arg to hush 'em up.
+
+       * coffread.c (symbol_file_command):  Avoid output if from_tty != 1.
+       Add magic numbers for 960 COFF format.
+
+Fri Nov 30 09:18:20 1990  John Gilmore  (gnu at cygnus.com)
+
+       Merge Intel 960 port of gdb, from Intel "1.2" release.
+
+       CHANGE_LOG entries from their port, which was based on
+       gdb+-2.8.0:
+
+    Thu Sep  6 11:02:22 PDT 1990
+       Remove temp file if download is interrupted.
+
+    Wed Aug  1 09:08:33 PDT 1990
+       Now uses binary protocol to talk to NINDY.
+       Old hex protocol (NINDY 2.13 and older) supported with -O switch.
+       Times out after 5 seconds when trying to talk to NINDY.
+
+    Tue May 29 12:54:49 PDT 1990
+       Added variable baud rate (-b switch).
+       Source code reorganization.
+
+    Thu Apr 26 11:09:55 PDT 1990
+       More cleanup of batch mode;  specifically, execute "-s", "-e", and
+       "-se" switches as soon as they are encountered on the invocation line.
+
+    Fri Apr 20 13:47:15 PDT 1990
+       Add -brk switch.
+
+    Thu Apr 19 09:54:28 PDT 1990
+       Add 'reset' command.
+
+    Wed Apr 18 09:48:07 PDT 1990
+       After opening remote tty, wait for 1 second to go by without input
+       from it before trying to talk to NINDY (fixes problems with the
+       Heurikon HK80/V960E).
+
+    Mon Apr  4 16:33:05 PDT 1990
+       Some output was not being suppressed in 'batch' mode.
+
+    Thu Mar 22 15:31:11 PST 1990
+       Ask user if old symbol table should be deleted when new file is
+       downloaded.
+
+       Allow user to run a program downloaded before gdb960 was brought up.
+
+       Correct "exec-file" help message for i80960 context.
+
+       Correct bug in calculating user space address:  could occasionally
+       corrupt user program.
+
+       Make sure to zero low-order bits in rip's because of bug in 960CA
+       A-step part:  could cause operation faults when "next"ing across
+       a function call.
+
+       Correct bug that made it impossible to get source line numbers for
+       code loaded at addresses higher than 0x7fffffff.
+
+    Wed Jan 10 12:43:22 PST 1990
+       Open remote tty for exclusive use.
+
+    Fri Jan  5 12:14:42 PST 1990
+       Correct disassembly (CA manual was right after all):
+       opcode for sysctl is 0x659
+
+    Mon Oct 23 12:03:04 PDT 1989
+       Use G960BASE and G960BIN environment variables to find 'sx' utility.
+
+    Mon Oct 16 14:15:09 PDT 1989
+       "sfr0"-"sfr31" should have been named "sf0"-"sf31"
+
+    Mon Oct  2 15:56:31 PDT 1989
+
+       Added 960CA disassembly support.
+
+       To simplify maintenance:
+               - eliminated use of symblic links on pinsn.c: use i960-pinsn.c
+                       directly instead.
+               - eliminated opcode.h: incorporates tables into i960-pinsn.c
+               - moved 960-specific routines from i960-pinsn.c to i960-md.c
+               - made disassembly interface identical to that in gdmp960.
+
+
+
+Wed Nov 28 21:32:48 1990  John Gilmore  (gnu at cygint)
+
+       * target.h: Allow targets to stack.  Add target_has_memory,
+       _registers, etc.  Restructure memory access and "info files"
+       to walk the target stack.
+       * exec.c, core.c, inftarg.c, remote.c, remote-vx.c, remote-eb.c,
+       target.c:  Change tables to match target.h.
+       * inflow.c (child_mourn_inferior):  pop child_ops.
+       (generic_mourn_inferior):  Use new has_stack flag.
+       * infptrace.c (child_xfer_memory): New memory regime.
+       * inftarg.c (child_files_info): New "info files" regime.
+       * remote-eb.c: New memory regime, new info files.
+       * remote-vx.c: New memory regime, new info files.  Now use
+       separate targets for VxWorks attachment to machine, and 
+       actually running a process under VxWorks, since one has
+       stack & execution & regs and the other doesn't.
+       * remote.c: New memory regime, new info files.
+       * sparc-xdep.c (fetch_core-registers):  New memory regime.
+       * target.c:  New routines and support for stacked targets,
+       new memory regime, new info files regime.
+       
+
+       Generalize section handling for an arbitrary number of sections,
+       including use of the new BFD (binary file) library.
+       * gdbcore.h: Add struct section_table.
+       * exec.c (build_section_table):  Iterate all sections and
+       record what gdb needs to know about them.
+       (exec_command):  Use it.
+       (exec_xfer_memory):  Use the table.
+       (exec_files_info):  Print the table.
+       * core.c (core_file_command, core_xfer_memory, core_files_info):
+       Likewise.       
+       * source.c (find_source_lines):  Use bfd_get_mtime.
+       * dbxread.c:  Quick changes to make it compile with new BFD.
+       * utils.c (error):  Avoid using bfd_error in generic routines.
+       
+       * core.c (core_fetch_registers):  Get from the ".regs" section of
+       the BFD core file.
+       * sparc-xdep.c (fetch_core_registers):  Use the .regs info.
+
+       * inferior.h (attach_flag):  Export.
+       * infcmd.c (run_command):  use new target_create_inferior.
+       * infrun.c (child_create_inferior):  Don't return result.
+       * Makefile.dist (VERSION):  3.91.4.
+
+Fri Nov 23 28:15:38 1990  John Gilmore  (gnu at cygint)
+
+       * breakpoint.c (bpstat_num):  Handle breakpoints which have
+       since been deleted, such as temporary breakpoints.
+       infcmd.c (program_info):  ditto.
+
+       * core.c (core_file_command):  Display the frame where the core
+       dump occurred.
+
+       * main.c:  lint.
+
+       * remote-vx.c (target_command):  Merge in target command from
+       targ-vx.c.  A few other cleanups.
+
+       * TODO, Projects:  Lots more stuff to do...
+
+Fri Nov 23 18:15:38 1990  John Gilmore  (gnu at cygint)
+
+       Massive changes to wall off the remote-debugging interface
+       behind a function vector.  The port to handle VxWorks targets
+       is also part of this.
+
+       All files:  Replace references to renamed functions,
+       remove references to remote_debugging, remove references to
+       have_include_file, have_core_file in favor of target_has_stack,
+       target_has_memory, etc.
+
+       * Modularize the breakpoint interface.
+       breakpoint.h (BREAKPOINT_MAX):  New define sets max length of
+       a breakpoint instruction.
+       breakpoint.c: struct breakpoint's shadow_contents now sized as
+       BREAKPOINT_MAX.
+       (insert_breakpoints):  Vector to target to install breakpoints.
+       (remove_breakpoints):  Vector to target here too.
+       Remove REMOTE_SA_SPARC kludges and other remote_debugging.
+       sparc-tdep.c (single_step):  Use new breakpoint interface for
+       the single-step breakpoints.
+       mem-break.c (memory_insert_breakpoint, memory_remove_breakpoint):
+       New file, contains routines to insert and remove breakpoints by
+       reading out the old contents and later replacing them.  This is
+       how ptrace breakpoints work, and many remote systems as well.
+
+       * tm-vxworks68.h:  New config file, overrides a few things for
+       Wind River's preferences.
+
+       * target.h:  New file, for transfer vector used to talk to the
+       inferior (child, attached, core, exec, remote, etc).  All accesses
+       to the thing being debugged should come through these vectors.
+       target.c:  New file, routines to handle transfer vector.
+       (various files):  Add transfer vectors XXX_ops for the various
+       targets and pseudo-targets (core files, etc) we support.
+
+       * breakpoint.c (bpstat_stop_status):  Further explorations of
+       watchpoints and why things don't work all the time.
+       (bpstat_alloc):  New fn to allocate a bpstat and chain it.
+
+       * config.gdb:  Only add "source ${srcdir}/.gdbinit" to
+       the local gdbinit if it doesn't already have it.
+
+       * core.c (core_ops):  add and install.
+       Allow core debugging without exec file.
+
+       * dbxread.c (free_and_init_header_files):  Merge two fns.
+       (end_symtab):  Free named symbol table when a new version comes in.
+       (read_dbx_symtab):  Relocate all kinds of symbols with base
+       address.  First step toward handling different text, data, bss
+       reloc.
+       (add_file_addr_command):  Renamed add_file_command.
+       (add_file_command):  Vector to remote handler.
+       Add "load" as an alias for "add-file" command.
+
+       * defs.h:  Allow "volatile" to be used in non-ANSI; use it for
+       non-returning functions.
+
+       * exec.c:  Add exec_ops, and push it as a target when an exec
+       file is specified.
+
+       * infcmd.c (run_command):  Pass executable file name and arg list
+       separately when starting an inferior.  Permit "run" when no exec
+       file is specified, for VxWorks.
+       (detach_command):  Move to child_detach in inftarg.c.
+
+       * inftarg.c:  New file.  Unix-child-specific routines, and the
+       child_ops structure.
+
+       * inferior.h (registers):  Export "registers" as the way for
+       target dependent register handlers to find gdb's local copy of
+       the registers.  Rename "stop_after_attach" to "stop_soon_quietly"
+       since it is now used by places that want wait_for_inferior to
+       handle the grunge but want to see every trap from the inferior.
+
+       * inflow.c (create_inferior):  Pull out, and merge into infrun.c.
+       Eliminate remote_debugging hooks in terminal handling.
+
+       * infrun.c:  Replace start_inferior with child_create_inferior.
+       Move all the hair of Unix shells and ptrace idiosyncracies into
+       child_create_inferior, so remote handlers don't have to deal.
+       Remove running_in_shell.  Rename stop_after_attach to
+       stop_soon_quietly, and use it in a few other places where we want
+       to just call wait_for_inferior and get control back on the first
+       trap.  trap_expected now never takes a value > 1.
+       (init_wait_for_inferior):  Initialize static vars when a new
+       process is created.
+
+       main.c (gdbinit):  Add new hook for .gdbinit file name, let
+       it be overridden by config files as GDBINIT_FILENAME.
+       (DEFAULT_PROMPT):  Add new hook for overriding (gdb) prompt.
+       Both of these are used for VxWorks gdb.
+
+       mcheck.c:  rename include file "gmalloc.c" to avoid problems
+       with system include file "malloc.c".
+
+       param-no-tm.h:  New include file, same as param.h but does not
+       include the default "tm.h" file.  This is used in files where
+       the target is known, e.g. remote-eb.c or sparc-xdep.c.
+
+       param.h:  Now just a shell that includes tm.h and param-no-tm.h.
+
+       remote-vx.c:  New file, VxWorks remote debugging support.  Uses
+       RPC routines that are shared with the target system, in directory
+       ${srcdir}/vx-share.
+
+       remote.c:  Vectorize remote interface.
+
+       source.c:  Globalize source_path, and make an alias "l" for "list"
+       since we now have the "load" command.
+
+       sparc-xdep.c:  Use new param-no-tm.h.
+
+       symmisc.c (free_named_symtab):  Add new function from Wind River.
+       However, ifdef it out for now while we think about what it should
+       really be doing.
+
+       tm-sun3.h, xm-sparc.h, xm-sun3.h, xm-symmetry.h: Move
+       PREPARE_TO_STORE to
+       the xm- file, and change its name to CHILD_PREPARE_TO_STORE, since
+       non-Unix-children handle this with their own code in the target
+       transfer vector.
+
+       Makefile.dist:  Roll version to 3.92.3.  Add vx-share stuff to
+       source and target lists.  Add vx-share to default list of include
+       directories.  Add new files to src and target lists: mem-break,
+       target, inftarg, remote-eb, remote-vx, targ-vx.  Be sure the
+       ${srcdir} versions of munch and createtags are used.
+
+       * valops.c (find_function_addr):  Split out of call_function.
+       (call_function_by_hand):  Rename call_function; this function 
+       calls functions in the target by laboriously patching the target
+       word-by-word with the right stack, args, regs, etc.
+
+
+Mon Nov  5 17:29:10 1990  John Gilmore  (gnu at cygint)
+
+       Handle AMD 29000 a bit better.
+
+       * remote-eb.c (readchar):  Mask received char log to make it readable.
+       (remote_start):  Pass arguments down to executing program.
+       Make startaddr unsigned.
+       infrun.c (start_inferior):  Accept args, pass them to
+       remote_start.
+       infcmd.c (run_command):  Pass args down to start_inferior.
+
+       * tconfig/am29k-aout, tconfig/am29k-coff:  New files specifying
+       the target object file format.
+       tm-29k.h:  Pay heed to COFF_ENCAPSULATE.
+
+       * am29k-pinsn.c (print_insn):  Print 0x on hex numbers in disassembly.
+       am29k-tdep.c (examine_prologue):  Better checking of function prefixes.
+
+Sun Oct  7 18:20:45 1990  John Gilmore  (gnu at cygint)
+
+       * Makefile.dist (VERSION):  Roll version to 3.91.9 and freeze.
+       * TODO:  We did a few things, we have more to do though.
+
+       * xm-sparc.h (CLEAR_DEFERRED_STORES):  Define.
+       * inflow.c (inferior_died):  Clear deferred stores.
+       
+       * Debug problems with dummy frames and calls to the inferior.
+       * tm-sparc.h (PUSH_DUMMY_FRAME, POP_FRAME):  Move to sparc-tdep.c.
+       * sparc-tdep.c (do_restore_insn):  Simplify.
+       (sparc_frame_find_saved_regs):  Simplify and fix what we find.
+       (sparc_push_dummy_frame):  Simplify and fix what we push.
+       (sparc_pop_frame):  Slightly more hair here, deciding whether
+       we are restoring a saved PC or returning to a return address in %i7.
+       * sparc-xdep.c (read_inferior_registers):  Debug if valid reg is read.
+
+       * utils.c (xmalloc, xrealloc):  Return type depends on __STDC__.
+       * symtab.h (xmalloc): ditto, for obstack_chunk_alloc.
+       * obstack.h (chunkfun): ditto.
+       * defs.h (xmalloc, xrealloc): ditto
+
+       * utils.c (quit):  Grab the terminal from the child if necessary. 
+
+       * inflow.c (term_status_command): Rename to term_info, change
+       to "info terminal".
+
+       * sparc-pinsn.c (print_insn):  Disassembly prefers real instructions.
+       (is_delayed_branch):  Speed up.
+       * sparc-opcode.h: Add ALIAS bit to aliases.  Fix up opcode tables.
+       Still missing some float ops, and needs testing.
+
+       * Support for input and output radixes other than base 10
+       * defs.h (input_radix, output_radix):  Declare.
+       * expread.y (yyparse, parse_number):  Handle changes of input
+       radix, and ambiguous names-or-numbers in radixes >10.
+       * printcmd.c (print_scalar_formatted):  Print formatted hex
+       numbers in varying column widths.
+       * valprint.c (val_print):  Use output_format to print scalar ints.
+       (set_input_radix, set_output_radix, set_radix):  Create.
+       (set_output_radix):  Set output_format from output_radix.
+       (_initialize_valprint):  add `set radix' but leave the others off.
+       
+       * main.c (execute_command): Let stupid questions be turned off.
+       (_initialize_main): Handle "set stupidity", etc.
+
+       * main.c, inflow.c, inferior.h, frame.h, command.c, defs.h, 
+       sparc-pinsn.c, sparc-xdep.c, value.h, valops.c, values.c:  Lint.
+
+Tue Oct  2 11:20:02 1990  John Gilmore  (gnu at cygint)
+
+       * TODO, Makefile.dist, ChangeLog:  Freeze for 3.91.8 release.
+       bfd stuff is still screwed up, but with some manual work, it
+       compiles.
+
+       * breakpoint.c (bpstat_do_actions):  Start over if a command
+       proceeds the inferior, since the inferior will have stopped and
+       will need to have its new stop-actions taken care of.
+
+       * dbxread.c (read_struct_type):  Expression gives Sun3 4.0.3
+       compiler fits, simplify it.
+
+       * gdb.texinfo (directory command): Doc new dir command.
+       source.c (directory_command):  "dir" now puts things on the front
+       of the path, moves dups up front, and handles multiple names
+       on the command line, inserting each one in order.  It also
+       blows away cached line and full_filename info.
+
+       * stack.c (backtrace_command):  Skip "more stack frames follow"
+       unless interactive.
+
+       * Change #ifndef HAVE_VPRINTF to #define MISSING_VPRINTF in
+       xm-convex.h, xm-hp300bsd.h, xm-isi.h, xm-merlin.h, xm-news.h, 
+       xm-np1.h, xm-pn.h, xm-pyr.h, xm-symmetry.h, xm-umax.h, xm-vax.h.
+       The only odd one was Gould NP1, which had defined vprintf to
+       "printf"!!!
+
+       * Merge Ted Goldstein <tedg@Eng.sun.com>'s changes for epoch.
+       printcmd.c (print_command_1): Pass 'inspect' flag down as a global
+       variable, inspect_it.
+       valprint.c (print_string, val_print): Use the global inspect_it
+       to indicate whether to print in Epoch style or normal style.    
+
+Mon Oct  1 23:55:26 1990  John Gilmore  (gnu at cygint)
+
+       * printcmd.c (call_command):  add an alias for the "print" command
+       which runs expressions and doesn't print the result if void.
+       (print_command_1): implement it.
+
+       * command.c: Remove #if 0'd code.  Initialize all the fields
+       in add_cmd ().  Rename do_nothing_command to
+       not_just_help_class_command, and make it externally visible.
+       command.h: add user_commands to struct.
+       * main.c (define_command):  Don't overload c->function with a char
+       string as well as a function pointer.
+
+       * eval.c (evaluate_subexp):  Reinstall tiemann changes to
+       calling convention of value_struct_elt () that got dropped in
+       merge.
+
+       * tm-sparc.h (FRAME_FIND_SAVED_REGS):  move to sparc-xdep.c.
+       sparc-tdep.c (sparc_frame_find_saved_regs):  ditto.
+
+       * tm-sparc.h (POP_FRAME): replace some constants with defines.
+
+       * sparc-xdep.c (store_inferior_registers):  defer stores to regs
+       until a good time (e.g. when we are about to run the child),
+       saving ptrace calls.
+       * infrun.c (proceed):  handle DO_DEFERRED_STORES.
+       * tm-sparc.h: define DO_DEFERRED_STORES.
+
+       * sparc-xdep.c (store_inferior_registers): when storing float
+       registers, don't store stack regs too.  When storing the SP,
+       however, DO store the stack regs too.  This fixes a bug in which
+       the dummy frame is not recognized when a call_function finishes,
+       because its frame pointer (in the stack regs) was never
+       initialized.
+       (read_inferior_registers):  Mark WIM and TBR and FPS and CPS valid
+       even though we don't know how to read them from an inferior.
+       valops.c (call_function):  Comment about storing SP.
+
+       * infrun.c (save_inferior_status): Save away the original bpstat
+       chain so it can be restored later.  Install the copied version for
+       use by whoever saved the status.  It will be blow away by
+       restore_inferior_status, and the original chain restored.  This is
+       important for people who have pointers into the original.
+
+       * breakpoint.c, command.h, copying.awk, dbxread.c, defs.h,
+       findvar.c, frame.h, obstack.h, obstack.c, inflow.c, value.h,
+       main.c, printcmd.c, sparc-tdep.c, symtab.c, valprint.c: lint
+
+
+Fri Sep 28 20:32:46 1990  John Gilmore  (gnu at cygnus.com)
+
+       * Makefile.dist: Roll version to 3.91.8.  Add bfd.h and bfdconfig.h
+       temporarily to the makefile.  Add am29k-opcode.h and WHATS.NEW.
+       Add stuff.c and kdb-start.c to the OTHERS list for tar files.
+
+Fri Sep 28 19:12:12 1990  John Gilmore  (gnu at cygint)
+
+       * Merge Mike Tiemann's multiple inheritance changes from Sun.
+       Store the baseclasses in a type struct starting from array element
+       0 rather than from the unusual array element 1.
+
+       dbxread.c: the above.
+       (virtual_context): Add
+       Read new debug information about which virtual function table
+       a virtual function is from, and store it in fn_field.fcontext.
+       
+       symtab.h: Add fcontextt.  Fix baseclass indices.  Typo in
+       TYPE_FN_FIELD_STATIC_P.
+
+       symtab.c: the above.
+       valops.c: the above.  Handle pointer casts of object *'s.
+       (search_struct_method): Add.
+       (value_struct_elt): First arg is now a pointer to a value, and is
+       modified on return.
+
+       valprint.c: the above.
+       values.c (value_virtual_fn_field): Add type arg.  Handle
+       offsetting to the proper object when calling virtual fns.
+       The above.
+       (baseclass_addr): Add valuep arg.
+
+       * README:  Document the current state of BFD config (missing).
+       * TODO, ChangeLog, Makefile.dist: Roll version.
+       * WHATS.NEW: Add summary of changes since 3.5.
+
+Thu Sep 27 16:23:12 1990  John Gilmore  (gnu at cygint)
+
+       * dbxread.c (read_struct_type): Clear bit vectors whenever
+       we allocate one.
+       symtab.c (B_CLRALL): define.
+
+       * tm-sparc.h (STORE_RETURN_VALUE): Avoid clobbering types by
+       using == rather than =.  Huh...  This fixes the dreaded problem
+       wherein builtin_type_int becomes TYPE_CODE_FLT.
+
+       * core.c (info_files): Show the inferior pid.
+
+       * config.gdb: Avoid putting "dir" command into .gdbinit.  GDB
+       already knows how to look in the source directory.
+
+       * Remove psymtab hair from many places.  Remove duplicated code
+       for searching symbol tables.  Hide psymtabs from most places.
+       Make it fast to get from a psymtab to its symtab.
+
+       blockframe.c (blockvector_for_pc): Remove psymtab hair.
+       coffread.c (psymtab_to_symtab): Rename to psymtab_to_symtab2.
+       mipsread.c (psymtab_to_symtab): Rename to psymtab_to_symtab2.
+       dbxread.c: export psymtab_to_symtab, make it work if called N times.
+       (psymtab_to_symtab): Rename to psymtab_to_symtab2.  Initialize
+       new symtab completely.  New psymtabs get symtab pointer
+       initialized to zero.  Remove MI warning printf.  
+       symtab.h: Comments.  Add psymtab to symtab pointer.
+       (PSYMTAB_TO_SYMTAB): New macro.
+       symtab.c: use PSYMTAB_TO_SYMTAB.  Add psymtab_to_symtab and export it.
+       source.c: use PSYMTAB_TO_SYMTAB.  Remove symtab version and
+       compilation fields.
+       stack.c (backtrace_command): Avoid pre-pass to read symbols, if
+       verbose is not set.
+       (print_frame_info): Avoid special-casing symbols that have not yet
+       been read in.
+
+       * source.c (open_source_file): Quick path if we have already
+       located the source file by its full name.
+
+       * symtab.c (lookup_symbol): Use find_pc_symtab rather than
+       find_pc_psymtab.  When a name is found in the misc function
+       vector, search the symbol table for its mangled name, not the
+       name that the user typed.
+
+       * bfd.h: Fix missing comment terminators, make #endifs match.
+
+       * valarith.c (value_less): Handle unsigned int comparisons.
+       Add FIXME about pointer compares, which assume host and target
+       pointers are the same.
+
+       * command.c (do_nothing_command): lint
+       dbxread.c: lint.  Remove sort_syms.  Document C++ visibility info,
+       fix comments on debug symbol format for visibility.  Actually set
+       visibility of symbols.
+       main.c (echo_command): lint; use <readline/history.h>.
+       tm-sparc.h (FRAME_FIND_SAVED_REGS): lint
+       obstack.h (_obstack_blank): Rearrange pointer math to avoid
+       pointing past end of allocated memory; saber complains.
+       obstack.h: Declare the external functions that we use.
+       valarith.h: use <string.h>
+       solib.c (solib_add): lint.
+
+Fri Sep 21 17:05:19 1990  John Gilmore  (gnu at cygint)
+
+       * main.c (initialize_main):  Default info_verbose to off, now that
+       symbol reading is fast.
+       (quit_command):  Avoid clobbering exec_bfd while quitting.
+
+       * Initial BFD (binary file diddling library) merger:
+       coffread.c: Change AOUTHDR to struct exe_hdr.
+       dbxread.c: ditto.
+       core.c: initialize initialized data at compile time.
+       (core_file_command):  Move from coredep.c, convert to bfd.
+       (xfer_core_file): Convert to bfd.
+       exec.c (exec_file_command): use bfd routines.
+       gdbcore.h: BFD.
+       mips-tdep.c: Remove exec_file_command and friends.
+       source.c: bfd.
+       
+       * coredep.c: (fetch_core_registers) Convert core_file_command to
+       fetch_core_registers.
+       mips-xdep.c, sparc-xdep.c, sun3-xdep.c: ditto.
+       
+       * utils.c: (error): Bogus crap, FIXME, to print bfd errors.
+       (my_bfd_read): More bogosity, which I don't think we call.
+       (program_name): Remove this atrocity asap!
+
+Wed Sep 19 13:36:41 1990  John Gilmore  (gnu at cygint)
+
+       * From Per Bothner:
+       values.c: allocate_repeat_value was not clearing the
+       optimized_out field.
+       (value_static_field): minor stylistic fix (wrong macro was used).
+       valops.c (value_struct_elt_for_address): didn't work for C++
+       static fields.
+
+       * signame.c (_initialize_signame):  Initialize signal names once.
+
+       * breakpoint.h, command.c, copying.awk, defs.h, environ.c,
+       exec.c, frame.h, infcmd.c, inferior.h, main.c, munch, sun3-xdep.c,
+       symtab.h, tm-29k.h, valprint.c, value.h, values.c:  Lint.
+
+       * remote-eb.c:  Support user-settable baud rates on the serial port.
+
+       * tm-sun3.h (PREPARE_TO_STORE): fix typo.
+
+Fri Sep 14 13:28:29 1990  John Gilmore  (gnu at cygint)
+
+       * tconfig/sun3os4: Remove warning about native assembler,
+       since it also occurs in the xconfig file.
+
+       * findvar.c (registers): Allocate some slop after `registers'
+       to prevent stray accesses from trashing the next variable.
+
+       * tm-68k.h (REGISTER_BYTES):  Allocate the right number of bytes
+       on the sun-3, by changing the #ifdef from `sun3' (which is not
+       defined by cc) to `sun'.  Symptom was trashed builtin_type_XXX
+       vars, which happened to follow `registers' in the executable.
+
+       * readline/history.c (history_search): Heed gcc-2's advice
+       and parenthesize && inside ||).
+
+       * am29k-opcode.h, am29k-pinsn.c, am29k-tdep.c, remote-eb.c,
+       tm-29k.c:  Insert FSF copyright headers.
+
+       * remote-eb.c:  Better comments.
+
+       * Makefile.dist:  Update to 3.91.6.
+       * TODO: note PREPARE_TO_STORE problem.
+
+Thu Sep 13 09:52:33 1990  Jim Kingdon  (kingdon at cygint)
+
+       * stack.c (frame_info): Only use FRAME_FIND_SAVED_REGS if defined.
+
+       * remote.c:  Wrap the whole file in #if !defined (SPECIAL_REMOTE).
+
+       * infrun.c (wait_for_inferior, at end): Don't set up
+       prev_* if the inferior no longer exists.
+
+       * inferior.h (CALL_DUMMY_LOCATION): New macro, to replace
+       CANNOT_EXECUTE_STACK.
+       valops.c (call_function): Use it.
+
+       * tm-convex.h: Add CALL_DUMMY_LENGTH for use by PC_IN_CALL_DUMMY.
+
+       * inferior.h (PC_IN_CALL_DUMMY): New macro.
+       infrun.c (wait_for_inferior, 2 places): Use it.
+
+       * values.c (value_being_returned): Only use
+       EXTRACT_STRUCT_VALUE_ADDRESS if defined.
+
+       * Move PREPARE_TO_STORE from xm-sun3.h to tm-sun3.h to do the
+       right thing for remote-eb.c.  
+
+       * sun3-xdep.c:  Remove extraneous call to remote_store_registers.
+       * sun386-xdep.c, hp300hpux-xdep.c, sparc-xdep.c:  Ditto.
+
+       * blockframe.c:  Put get_frame_saved_regs inside #if !defined
+       (FRAME_FIND_SAVED_REGS).
+
+       * findvar.c ({fetch,store}_registers): Check for
+       REMOTE_{FETCH_STORE}_REGISTER macro.
+
+       * findvar.c (get_saved_register): Add argument lval and
+       change meaning of argument addr.
+       findvar.c:  Change calls to get_saved_register to reflect
+       new calling convention.
+       valops.c (value_assign): Use get_saved_register instead of
+       find_saved_register.
+
+Sun Sep  2 12:40:20 1990  Jim Kingdon  (kingdon at cygint.cygnus.com)
+
+       * coffread.c (read_one_sym): Make temp_aux an AUXENT, not
+       an (uninitialized) pointer to one.  Use "&" when passing it
+       to fread.
+
+Fri Aug 31 22:57:54 1990  Jim Kingdon  (kingdon at cygint.cygnus.com)
+
+       * coffread.c (getfilename): Use DGUX x_offset and x_name if
+       defined.
+
+       * coffread.c (symbol_file_command): Put semicolon after
+       "int from_tty".
+       Put safe_to_init_tdesc_context in #if defined (TDESC).
+       Put #ifdef TDESCs in 1st column for non-ANSI cpp's.
+       coffread.c: #include <sys/stat.h>.
+       (read_coff_symtab): Typo: in_source_files -> in_source_file.
+       Add missing ')' in check for "lc%" and friends.  Remove
+       extraneous '}'.
+       Declare read_one_sym() at top of file.
+       (read_file_hdr): Put in extra #ifdefs so MC68MAGIC and
+       MC68WRMAGIC can have the same value without causing a duplicate
+       case.
+
+Thu Sep 13 15:55:36 1990  John Gilmore  (gnu at cygint)
+
+       * Allow a Makefile to be built without building the
+       tm and xm file links that screw up builds in subdirectories.
+       This is done with `config.gdb none', then you can do things
+       like `make gdb.tar.Z'.
+       * tconfig/none: Config file for no target system
+       * xconfig/none: Config file for no host system
+       * config.gdb: If no TM or XM files are called out by the
+       host or target file, don't make links for them.
+
+       * cplus-dem.c: Add documentation.
+
+       * dbxread.c (read_ofile_symtab): Turn a fatal error into a
+       simple error, so the user's gdb doesn't crash due to some object
+       file problem (e.g. somebody is rebuilding the file out from under
+       gdb).
+
+       * printcmd.c (print_address_symbolic): demangle the symbol.
+
+       * Makefile.dist (OTHERS): Remove tdesc-lib because it has 
+       Motorola copyrights in it.  Make "make gdb.tar.Z" work.
+       (alldeps.mak): sort and uniq all results from this; duplicates
+       hose gdb.tar.Z link building.  Remove RCS files from
+       tconfig and xconfig.  Add config files for sun386.  Add
+       a few odd files to OTHERS and HFILES.
+
+Mon Sep 10 21:20:24 1990  John Gilmore  (gnu at cygint)
+
+       * Makefile.dist: Pull solib.c to tconfig/sun?os4.
+       Roll version number to 3.91.5.  Make lint work in bindir.
+
+       * README:  Document cross-debugging and new file structure.
+
+       * blockframe.c: Lint.  Include "value.h" to declare read_register.
+       (find_pc_partial_function): remove duplicate line.
+
+       * command.h: Lint.  Declare error_no_arg and dont_repeat.
+
+       * tm-news.h: Remove inadvertently duplicated stuff.
+
+       * mipsread.c: Remove cache_pc_function stuff, now done cleanly.
+       Clean up usage of misc_function_type.  Declare some CORE_ADDRs.
+
+       * config.gdb: Allow `config.gdb host target' form.  Clean
+       up previous change that printed bogus messages when you just said
+       `config.gdb'.
+
+       * core.c: #include "command.h" for lint.
+       * dbxread.c: lint
+       * eval.c: lint
+       * main.c: Remove some casts of enums.  Lint.
+       * source.c: lint
+       * symtab.c: lint
+       * symtab.h: lint
+       * expread.y: lint
+       * valarith.c: lint
+
+       * printcmd.c (initialize_printcmd): Fix thinko in inspect cmd.
+       
+       * sparc-tdep.c (isannulled): Take instruction as parameter, don't
+       read it from memory.  This will allow us to save ptrace calls
+       eventually.   Changed caller single_step too.
+
+       * sparc-xdep.c (fetch_inferior_registers): Avoid reading regs
+       that we aren't going to use, saving many ptrace calls, especially
+       when watchpointing or single stepping.  Use some #define's for
+       constants.
+       (store_inferior_registers): Ditto.
+       (core_file_command): Use some #define's for constants.
+
+       * tm-sparc.h: Add #define's for some register numbers, so we
+       can eliminate the use of random constants in sparc-xdep.c.
+
+       * stack.c (frame_command, print_frame_info, up_command,
+       down_command) Remove frame_changed, since it
+       causes a bug and doesn't seem to do anything useful.  In some
+       places it was used as a flag, in others as a stack level (?).
+
+       * utils.c: Use MISSING_VPRINTF rather than HAVE_VPRINTF, so the
+       default is to use the portable (vprintf) version rather than the
+       kludge version.
+       * xm-news.h (MISSING_VPRINTF): Add.
+
+       * valprint.c (val_print): Demangle fancy vtbl printouts.  Lint.
+
+Sat Sep  8 00:24:12 1990  John Gilmore  (gnu at cygint)
+
+       * Remove stuff that forces -Bstatic linking of gdb, and warnings
+       about linking debugged programs -Bstatic in the sun?os4 config
+       files in tconfig and xconfig subdirectories.
+
+       * main.c (main):  Remove unreached exit(0) now that we exit
+       via quit_command().
+
+       * Create TODO file for online bug list.  There are too many
+       "little" bugs to keep track of on paper.
+
+       * Change Projects file to refer to bug-gdb@cygnus.com
+       rather than kingdon@ai.
+
+Fri Sep  7 23:35:15 1990  John Gilmore  (gnu at cygint)
+
+       * Makefile.dist (VERSION): 3.91.4 now.
+
+       * symtab.c (init_misc_bunches): Rename from init_misc_functions.
+       (condense_misc_bunches): Add sanity check that misc_count is
+       the same as the number of symbols in the bunch.
+       
+       * coffread.c: rename init_misc_bunches.  Pass an argument 
+       to condense_misc_bunches (a zero).
+
+       * dbxread.c (partial_symbol_file_read): Call init_misc_bunches
+       every time we are called; don't rely on our caller to do it.
+       (add_file): Remove call to init_misc_bunches.
+
+       * mipsread.c: Only warn, don't error, if unknown symbol types.
+       This keeps an old gdb from falling on its face if it sees newly
+       extended symbol info.  Rename init_misc_bunches.
+
+Fri Sep  7 22:58:15 1990  John Gilmore  (gnu at cygint)
+
+       * Merge in changes from Per Bothner for DECstations and other
+       MIPS stuff.  The rest is Bothner speaking:
+
+       The next message is a merger of Alessando Forin's mips port with
+       mine.  I've tried to use my good if biased judgment to get
+       the best of both. It *does* need testing.
+
+       Some of the changes are general, *not* mips-specific.
+
+       param.h:
+       Didn't believe in little-endian bit order.
+       There are still inconsistencies about whether flags
+       like BITS_BIG_ENDIAN are integer (#if ...) or
+       boolean (#ifdef ...). I tried to paper over them.
+
+       dbxread.c,coffread.c,mipsread.c,symtab.c,symtab.h:
+       Moved some misc_function code that was common to
+       {dbx,coff,mips}read.c to symtab.c.
+       In the process, I think I cleaned things up a bit.
+       At the same time, moved obsavestring and obconcat to symtab.c.
+
+       dbxread.c:
+       Removed obsolete condense_addl_misc_bunches (use
+       condense_misc_bunches(1) instead).
+
+       exec.c:
+       Needed to include <sys/dir>, at least on DECstations.
+
+       valops.c, mips-tdep.c, tm-mips.h:
+       Added PUSH_ARGUMENTS macro to support funny argument-pushing
+       conventions (when STACK_ALIGN is insufficient).
+       Needed on mips, where doubles need 8-byte alignment,
+       but ints only need 4.
+
+       mips-opcode.h:
+       Removed cruft that was not being used.
+       Merged in many fixes (most from Frank Yellin, fy@lucid.com).
+
+       mips-pinsn.c:
+       Print $ before register-names (I think that makes things a little
+       more consistent).
+       Never print two instructions, even if one delays.
+       Removed hex-disassemble set_cmd.  (This is not mips-specific,
+       so I think the argument is whether it is generally worthwhile or not.
+       I'm inclined to think not, given how easy it is to
+       convert between radixes in gdb.)
+
+       mipsread.c:
+       This is basically Alessando's code.
+       It doesn't use obstacks; I changed it to use obstacks
+       in a few minor places where using malloc causes a
+       memory leak. (Probably, more places could/should be changed.)
+       I added record_misc_function where it was missing.
+       In symbol_file_command and add_file_command, I tried
+       to make the code consistent with more recent versions.
+       Minor sylistic changes in parse_procedure.
+       Make a .gdbinfo. psuedo-symbol point back to the real
+       procedure symbol (using the isym field).
+
+       mips-tdep.c:
+       This is basically from my port, but with a lot of details
+       and a number of routines merged in from Alessando's version.
+       I basically used my code "raw" backtrace (use heuristics
+       from the actual code, rather than symbol table info) - though
+       the idea is Alessandro's. I feel my code is a little cleaner
+       here, particularly in being a little more flexible, such as being
+       able to handle gcc-produced code (which it now can).
+       It also doesn't do frame caching (which is not useful
+       more recent gdb versions).
+       I also used my code for push_/pop_dummy, more or less.
+       I tried to incorporate AF's code for testing sigtramp
+       while backtracing; I probably got it wrong.
+       Added mips_print_register, which tries to scrunch as much
+       information as possible on a screen...
+       Removed the skip-prologue set_cmd. As with hex-disassemble (see
+       under mips-pinsn.c), I don't see anything mips-specific here,
+       and I don't see it being all that useful anyway.
+       
+       tm-mips.h:
+       Added a $fp psuedo-reg distinct from $fp (nice for gcc).
+       Use more register names (rather than hard-cases numbers).
+       
+Thu Sep  6 18:33:15 1990  John Gilmore  (gnu at cygint)
+
+       * Hack up 3.90.11 changes:
+
+       * Makefile.dist (depend): parameterize $(GCC).
+       Add solib.c and solib.o.
+       (readline): Fix vpath for both absolute or relative SRCDIR.
+
+       * blockframe.c: Fix from Schaefer@asc.slb.com for shared libs.
+       Also, let the part I didn't understand at least compile so
+       I can test the rest.  FIXME.
+
+       * dbxread.c: Fix thinko using strcmp.
+       (init_psymbol_list): declare static.
+       (partial_symbol_file_open): Comment cleanups better, avoid
+       cleaning up the string table since the caller will do that.
+       Move the stat for mod time into symbol_file_command, temporarily.
+       (There should be a mod time for each symbol file, eventually,
+       to control its rereading.  FIXME.)
+
+       * infptrace.c (PT_WRITE_D): use same value as PT_WRITE_I for
+       SunOS, which gives error for shared libs otherwise.  (From
+       Schaefer, probably FIXME needs work for portability.)
+
+       * solib.c:  Move #include "param.h" to work.
+       Lowercase all the Uppercase Letters In the Messages.
+       (find_solib): Clean up inferior_so_name for debug printouts.
+       Allow no argument, to mean all shared libraries.
+
+       * symmisc.c: include param.h to get CLEAR_SOLIB.        
+
+Wed Sep  5 18:00:08 1990  John Gilmore  (gnu at cygint)
+
+       * Merge in Kingdon's changes from FSF: the diffs from 3.90.9
+         to 3.90.11.  ChangeLog entries below are from this.
+
+Wed Jun 13 09:17:39 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * Version 3.90.11.
+
+       * Makefile.dist (HFILES): Add tm-sunos.h.
+
+Tue Jun 12 16:15:26 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Version 3.90.10.
+
+       * Makefile.dist (gdb.tar.Z): Change linking of config so it works.
+
+Thu Jun  7 16:22:27 EDT 1990  Jay Fenlason (hack@ai.mit.edu)
+
+       * sparc-opcode.h  Added single-operand version of rett.
+
+Mon Jun  4 18:12:31 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * m-sparc.h (REG_STRUCT_HAS_ADDR, STRUCT_ARG_SYM_GARBAGE):
+       Put parens around gcc_p in expansion.
+
+Thu May 24 15:44:51 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * utils.c (lines_to_list): Return 10 if lines_per_page == 0.
+
+Wed May 23 16:36:04 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Changes for Sun shared libraries:
+       blockframe.c (find_pc_partial_function): If a non-text symbol
+       is found, set *address = pc - FUNCTION_START_OFFSET.
+       breakpoint.c (insert_breakpoints) [DISABLE_UNSETTABLE_BREAK]:
+       Disable breakpoints instead of giving an error.
+       source.c (select_source_symtab): Initialize cs_pst.
+       symmisc.c: Call CLEAR_SOLIB if defined.
+       symtab.h: Make text{low,high} CORE_ADDR not int.
+       (psymtab): New field addr.
+       solib.c: New file.
+       dbxread.c: Move DECLARE_FILE_HEADERS outside functions.
+       (record_misc_function): Give correct type for N_DATA symbols.
+       (condense_misc_bunches): do "misc_function_count = j" regardless
+       of inclink.
+       Take code which is shared between symbol_file_command and
+       add_file_command and put it into partial_symbol_file_{open,read}.
+       Split add_file_command into add_file_command and add_file.
+       Make psymtab_to_symtab read in the string table if the file
+       is not symfile.
+       Two new parameters to read_dbx_symtab and start_psymtab.
+       tm-sunos.h: New file.
+
+Tue May 22 17:43:03 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * infcmd.c: Change cont_command to continue_command and "cont"
+       to "continue".
+
+Mon May 21 14:41:41 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * breakpoint.c (enable_breakpoint): Get value of watchpoint.
+
+       * defs.h [sparc]: Use <alloca.h> regardless of __GNUC__.
+
+       * values.c (USE_STRUCT_CONVENTION): Check for structures of
+       size 1,2,4,8 rather than size < 8.
+
+       * dbxread.c (dbx_lookup_type): Do f->length *= 2 as many times
+       as necessary, not just once.
+
+       * sparc-opcode.h: Add a bunch of new opcodes which Sun as supports.
+
+Thu May 17 15:04:09 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * {t,x}m-sun386.h, sun386-xdep.c, {x,t}config/sun386
+
+       * tm-news.h: Add CALL_DUMMY_*.
+
+       * tm-68k.h: Remove duplicate comment at FRAME_FIND_SAVED_REGS.
+
+       * config.gdb: In list_host, list_target, use ${i}, not $i.
+
+Tue May 15 21:27:12 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * source.c (find_source_lines) [BROKEN_LARGE_ALLOCA]: Use xmalloc.
+
+       * sparc-opcode.h: Change all store floating-point state register
+       instructions to have the right match & lose fields.
+
+Sat May  5 12:39:18 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Makefile.dist: Move -I${srcdir} to GLOBAL_CFLAGS and pass
+       VPATH to readline.
+       config.gdb: If srcdir != ., create readline directory and
+       copy a makefile into it.
+
+       * wait.h, infrun.c: Change WRETCODE to WEXITSTATUS for
+       consistency with POSIX.
+
+       * breakpoint.c (bpstat_stop_status): Disable watchpoint
+       when we exit its exp_valid_block.
+
+Tue Sep  4 11:46:46 1990  John Gilmore  (gnu at cygint)
+
+       * Makefile.dist: Bump version to 3.91.3.
+
+       * Clean up handling of breakpoint commands (somewhat).
+         Prompted by Tiemann bug report "cont 10" doesn't work any more.
+
+         inferior.h: Add breakpoint_proceeded to inferior status struct
+         and globals; save it and restore it.
+         (clear_breakpoint_commands): Cleanup, remove old #define.
+
+         infrun.c (clear_proceed_status): Set breakpoint_proceeded.
+         (save_inferior_status, restore_inferior_status): handle it also.
+         (proceed): Remove earlier code that set breakpoint_proceeded.
+         It is now set only in clear_proceed_status.
+         (clear_proceed_status): Cleanup, use bpstat_clear rather
+         than clear_breakpoint_commands.  No callers need the stop_bpstat
+         between clear_proceed_status and proceed.
+
+         infcmd.c: Add breakpoint_proceeded definition and comment.
+         (cont_command, jump_command, signal_command): Move call to
+         clear_proceed_status right next to call to proceed.
+
+         breakpoint.c (bpstat_do_actions): Avoid clobbering our
+         caller's argument while running down the chain of breakpoints.
+         Use new variable "breakpoint_proceeded" to determine when
+         a command that it executes moves the inferior past the
+         breakpoint.
+         (bpstat_clear): Handle NULL argument.
+         (bpstat_clear_actions): Avoid useless call to
+         breakpoint_auto_delete.
+         (delete_breakpoint):  Clean up bpstat's that are pointing to
+         the deleted breakpoint from the stop_bpstat chain.
+         (breakpoint_auto_delete): Simplify.
+
+       * Clean up handling of EOF, error on stdin, etc.  This was
+         prompted by a network problem that caused gdb to go into an
+         infinite loop filling up its malloc'd memory.
+
+         main.c (return_to_top_level): Cleanup: call bpstat_clear_actions,
+         not clear_breakpoints_commands, which is now gone.
+         (main): If command_loop returns (e.g. from EOF on stdin), do
+         a quit_command (looping back to command_loop if quit_command
+         doesn't really quit).
+         (command_loop): check result from command_line_input and
+         exit if it returns NULL, rather than passing the NULL to
+         execute_command.
+         (gdb_readline):  Free malloc'd result space before returning
+         NULL for EOF.
+
+       * utils.c (query): Handle C-d to mean "yes", just as if the
+         input was not a terminal.  Also avoid infinite loop if EOF
+         occurs in mid-input-line before newline.  This allows
+         query to be used at EOF on stdin with reasonable results.
+
+       * infrun.c (proceed): Set breakpoint_proceeded.
+
+       * values.c (value_as_long): Avoid infinite recursion for enums.
+         (_initialize_values): Fix typo in help msg (kingdon).
+
+       * Makefile.dist (RL_LIB): Use RL_LIB_DEP for dependencies,
+         RL_LIB for linking.  This allows -lreadline for linking
+         and nothing for dependencies, once readline is a real library.
+
+       * config.gdb: Jim Kingdon: give useful error message if the
+         host or target type is not recognized.
+
+       * defs.h (alloca): SPARC <alloca.h> does not declare alloca,
+         it just defines it.  Dumb, but deal with it.
+
+       * Jim Kingdon suggests:
+         in xconfig/sun3os4, CFLAGS should be XM_CFLAGS.
+
+Wed Aug 29 18:03:27 1990  John Gilmore  (gnu at cygint)
+
+       * Makefile.dist (VERSION): Bump version # to 3.91.2.
+
+       * Clean up Bothner's changes.
+
+       * blockframe.c (clear_pc_function_cache): New function.
+       * blockframe.c: remake cache_pc_function_* static.
+       * dbxread.c (symbol_file_command): remove references to
+                   cache_pc_function_* variables.
+       * dbxread.c (read_struct_type): Use VOFFSET_STATIC.
+       * printcmd.c: Avoid kludging a global variable (addressprint)
+         to avoid printing the address of a string twice.  Instead,
+         pass the format letter 's' down low enough that it can be seen
+         to avoid this problem.
+         (print_formatted): Pass format arg to value_print.
+         (restore_addressprint): Remove function.
+         (do_examine):  Avoid hacking addressprint, cleanups and such.
+         (print_frame_args):  Add a comment to a Bothner change.
+       * symtab.h: define VOFFSET_STATIC and use it instead of "-1".
+       * symmisc.c (free_all_symtabs): Call clear_pc_function_cache
+         to wipe out the values cached in blockframe.c.
+       * symtab.c (find_method): Add comment saying how big you must
+         allocate to be "big enough".  Per being terse again.
+       * valprint.c (val_print): Handle format letter "s" to print
+         strings without addresses.  Add comment to vtbl printing code
+         which casts with wild abandon.  Rearrange reference-printing
+         code so it prints:
+              @0xaddr: value           (print w/addressprint)
+              value                    (print w/~addressprint)
+              @0xaddr                  (parameter lists w/addressprint)
+         or   nothing                  (parameter lists w/o addressprint)
+
+Tue Aug 28 10:47:18 1990  John Gilmore  (gnu at cygint)
+
+       * Merge more changes from Per Bothner:
+
+Gdb's handling of TYPE_CODE_REF was so counter-C++ (and otherwise
+annoying) that I tried to improve it. Here are my suggestions.
+
+       These patches all attempt to handle TYPE_CODE_REF (as in C++) better.
+
+       findvar.c:
+       Do automatic de-reference when taking the address of a reference.
+       printcmd.c:
+       Don't deref_ref when printing parameter lists.
+       valops.c:
+       More attempts at treating refernences properly.
+       valprint.c:
+       In val_print, if deref_ref==0, don't print dangling " = ".
+       value.h:
+       Add COERCE_REF macro, which de-references an REF.
+
+       * Merge changes from Per Bothner:
+
+* Fixed (Sony news)-specific configuration problems.
+* Fixed other problems with using vanilla pcc and libc (enum problems;
+assumption that vsprintf exists).
+* Some major speed-ups (finc_pc_partial_function now caches a match;
+parsing avoids duplicate symbol_lookup calls).
+* Changed handling of baseclasses (no longer use baseclasses field
+of struct type, use the first n_baseclasses fields instead).
+* Various minor changes/fixes, most C++-related.
+
+blockframe.c:
+Cache the most previous match from find_pc_partial_function.
+(Save both low and high ends of matching function's pc range.)
+This speeds up the loop of infrun.c:wait_for_inferior quite
+a bit, and makes step/next commands much zippier.
+command.c:
+Added an enum->int cast (otherwise, some compilers barf).
+dbxread.c:
+No longer set baseclass offset to 0, since multiple
+inheritance now mostly works.
+Added a number of casts, to shut up compiler warnings
+(after stabs where made enums, not ints).
+When discarding a symbol table (in symbol_file_command),
+must clear the cache introduced in blockframe.c.
+Don't convert $vtbl_ptr_type to vtbl any more.
+Get rid of TYPE_BASECLASEES and  baseclass_vec (see also symtab.h).
+Mask off sign bit emitted by g++ for virtual table offset.
+Set voffset to -1 (not 1) for static member functions.
+expread.y:
+Changed parsing/lexing of names to avoid doing symbol lookup twice
+(once when lexing to determine symbol class, once for real).
+Now only call symbol_lookup once. Fields of 'this' win especially big.
+printcmd.c:
+Subpress printing addr twice in the case of 'x/s addr'.
+symtab.c:
+lookup_basetype_type is no longer used.
+Add find_methods as recursive helper function to decode_line_1.
+This allows multiple inheritance to work.
+Also, once one or more matches has been found, do not look in
+base-classes. (Baseclass methods would be overridden, anyway.)
+symtab.h:
+Removed baseclasses array in struct type.
+Instead of using baseclasses[i], use fields[i-1].
+Added virtual_field_bits[i] to indicate if the i'th baseclass is virtual.
+Changed sign convention of voffset (previous was inconsistent).
+tm-news.h:
+Some macros (CALL_DUMMY and relatives) were missing. Put them back.
+utils.c:
+Used to assume existence of vsprintf. Re-written to not need it
+if HAVE_VPRINTF is undefined.
+valops.c:
+typecmp was too pessimistic. Made it less so.
+valprint.c:
+Don't print space after address.
+If vtable points to a misc symbol (with 0 offset), print it,
+since that indicates the actual class of the object.
+Changed ype_print_derivation_info to use new inheritance
+scheme (without baseclasses vector).
+values.c:
+In value_primitive_field, fixed some bugs left over from previous set of fixes.
+Also, changes needed because TYPE_BASECLASSES were removed.
+xm-news.h:
+REGISTER_U_ADDR didn't work for PC. Rewrote to use an array.
+
+Tue Aug 21 20:08:54 1990  John Gilmore  (gnu at cygint)
+
+       * source.c:
+  If there is no path set, and the symbols don't indicate what directory
+  a file was compiled in, look in the current directory.  But either
+  a path or a known compilation directory will prevent this.
+
+       * dbxread.c:
+  Three independent bug fixes:
+   * Remove the #if 0 block that breaks some stuff.
+   * SunOS 4.1 fixed the promoted-parameter-wrong-addr bug in Sun C;
+     adapt gdb to either SunOS 4.0.* or 4.1.
+   * MAX_OF_TYPE and MIN_OF_TYPE thinko.  By tedg@sun, I think.
+       * symtab.c:
+  Instantiate the class T when looking for methods in it.  (Tiemann@sun)
+
+       * valprint.c:
+  (type_print) Demangle the name being printed.
+  (type_print_base) Handle botched demangling without coredump (tiemann).
+
+       * values.c:
+  (check_stub_method):  Document routine.
+                       (tiemann) fix bug for no-arg functions
+                       Avoid clobbering beyond end of malloc'd storage.
+                       Terminate the argument list properly.
+
+Sat Aug 18 01:29:59 1990  Per Bothner (bothner@cs.wisc.edu)
+
+       * Changes merged by John Gilmore:
+    
+breakpoint.c:
+  In breakpoint_1, use new print_address_symbolic instead
+  of find_pc_partial_function. (This forces use of assembler-level
+  addresses, and avoids misleading non-mangled source-level names.)
+cplus-dem.c:
+  Generalize ansi argument such that -1 means skip arglist totally.
+  Removed global variable print_ansi_qualifiers (which made
+  code non-reentrant), in favor of extra explicit arguments
+  to internal routines.
+printcmd.c:
+  Add new helper function print_address_symbolic.
+  Use find_pc_misc_function instead of find_pc_partial_function
+  (since we want assembler-level symbols here).
+stack.c:
+  Print unknown function as just "f (...)", not "f (...) (...)".
+  Use new fputs_demangled explicitly.
+symtab.c:
+  Fixed a typing violation (problem: value.h cannot be imported
+  without renaming many variable in this file).
+  lookup_symbol: If no matching misc_func, look for a C++-mangled name.
+  decode_line_1: Moved forward some never-reached code.
+  Made decode_line_2 skip function prologues correctly.
+utils.c:
+  fputs_filtered should not demangle by default.
+  Add new fputs_demangled to demangle on demand..
+valops.c:
+  Change value_struct_elt to use value_primitive_field (using recursive
+  utility function search_struct_field). This allows foo.bar to work
+  for multiple inheritance (so far only for data fields).
+  Change check_field in the same way (recursive helper function
+  to support multiple inheritance).
+  (Note: there are more of these problems that I haven't fixed.
+  Any code that says TYPE_BASECLASS (t, 1) is probably wrong.)
+  value_of_this: 'this' symbol name is now just "this", note "$this".
+valprint.c:
+  Don't print static members.
+  Avoid printing "members of <type>" if there are none.
+  Simplified type_print_derivation_info by merging duplicate code.
+  Remove useless blank lines in type_print_base (ptype command).
+value.h:
+  Added declaration of new routine value_primitive_field.
+values.c:
+  Added value_primitive_field which is generalized version of
+  value_field that can handle multiple inheritance (non-zero offsets etc).
+  Re-implemented value_field to call value_primitive_field.
+
+Fri Aug 17 23:33:44 1990  John Gilmore  (gnu at cygint)
+
+       * infcmd.c -- insert else to avoid 'delete env' coredump when you
+       delete the whole environment.  Karl Berry reported the bug.
+       * source.c - fix openp to avoid //'s in filenames, which
+       trigger an Emacs bug causing it to not be able to find files
+       when running gdb in a window.
+       * dbxread.c - zap the #if 0 that botches the add-file code.
+       It seems to work a lot better without all the code commented out.
+
+Fri Jul 20 16:58:46 1990  John Gilmore  (gnu at cygnus.com)
+
+       * Merge Tiemann's and Ted Goldstein's changes, detailed below,
+       into gdb-3.90.9.
+
+Tue Jul 17 19:34:33 1990  Ted Goldstein  (tedg at golem)
+
+       * Makefile - added a ${CFLAGS} to a couple of entries,
+       added remote-sa.sparc.c
+       * added remote.sa-sparc.c, a modification of remote.c
+       which conducts a dialog directly with the SparcStation prom.
+       * breakpoint.c, infrun.c, sparcdep.c  added 
+       remote_insert_breakpoint(), and remote_remove_breakpoint() 
+       to breakpoint.c instead of directly writing breakpoint instructions.
+       * sparcdep.c on remote_debugging,there is no need 
+       to remove signle step breakpoint instructions.
+       * main.c added "-epoch" flag and "int epoch_interface" to main.c
+       global variable
+       * printcmd.c - epoch interface sends lisp expressions to open up
+       epoch windows on inspection.
+       * valprint.c - added arrayprint, and addressprint and made adding
+       format controls easier
+       * wait.h added a couple of undef's because we were getting
+       complaints about WSTOPSIG and WTERMSIG begin redefined.
+
+
+Wed Jul  4 05:27:51 1990  Michael Tiemann  (tiemann at masham)
+
+       * symtab.c (decode_line_1): Add support for handling method stubs
+       in the type information.
+
+Tue Jul  3 09:39:18 1990  Michael Tiemann  (tiemann at masham)
+
+       * values.c (baseclass_addr): Run loop from INDEX+1 to
+       N_BASECLASSES; otherwise, we can still get into a loop.
+       @@ This should be restructured to use a cleaner search strategy.
+
+Sun Jul  1 12:28:51 1990  Michael Tiemann  (tiemann at masham)
+
+       * dbxread.c (define_symbol,read_type): Grok GNU C++'s new
+       abbreviation "Tt" for tags which have the same name as their
+       typedecls.
+
+Fri Jun 29 01:03:46 1990  Michael Tiemann  (tiemann at masham)
+
+       * symtab.c (list_symbols): add ability to set breakpoints on all
+       the functions which match a particular regular expression.
+
+Tue Jun 26 04:26:29 1990  Michael Tiemann  (tiemann at masham)
+
+       * cplus-dem.c (cplus_demangle): New parameter ANSI says whether we
+       should print ANSI qualifiers (such as `const' and `volatile').
+       All callers changed to call with ANSI == 1, except from
+       `check_method_stub', which uses old-style syntax.
+
+       * symseg.h (struct fn_field): Remove unneccessary `args' field.
+       * symtab.h (TYPE_FN_FIELD_ARGS): Redefined.
+
+       * values.c (check_stub_method): New function.
+
+       * cplus-dem.c (do_type): Handle "long long" (encoded as 'x').
+
+       * dbxread.c (read_type): Handle new GNU C++ method type stubs.
+       * valprint (type_print_base): Ditto.
+
+       * symtab.c (gdb_mangle_typename): New function.
+
+Tue Jun  5 00:18:43 1990  Michael Tiemann  (tiemann at gzilla)
+
+       * breakpoint.c (catch_command): New function.  Provides a
+       mechanism to set breakpoints based on catch clauses.
+       (disable_catch): Similar, but disables breakpoints on catch
+       clauses.
+       (delete_catch): Similar, but deleted breakpoints on catch clauses.
+
+Sun Jun  3 22:54:08 1990  Michael Tiemann  (tiemann at gzilla)
+
+       * blockframe.c (blockvector_for_pc): New function.
+       * blockframe.c (block_for_pc): Changed to call
+       `blockvector_for_pc' and get the block itself.
+
+       * stack.c (catch_info): New function.  Prints info about
+       exceptions which can be caught in the current frame.
+       * stack.c (print_frame_label_vars): New function.  Similar to
+       `print_frame_local_vars'.
+       * stack.c (print_block_frame_labels): Prints out labels that are
+       defined in this frame.  These labels are exceptions that can be
+       caught.
+
+       * dbxread.c: Updated to handle N_CATCH symtab types.
+
+Thu May  3 22:10:00 1990  Michael Tiemann  (tiemann at teacake)
+
+       * valprint.c (everywhere): TYPE_NAME (TYPE) no longer comes in the
+       form "struct ..." for GNU C++.  Don't flush any part of TYPE_NAME
+       when printing the type.
+
+Wed May  2 22:43:04 1990  Michael Tiemann  (tiemann at teacake)
+
+       * valprint.c (val_print): Use `baseclass_addr' to access the
+       baseclasses pointed to via the derived class object at VALADDR.
+
+       * values.c (baseclass_addr): New function.  Casts derived pointers
+       to baseclass pointers taking virtual baseclasses and multiple
+       inheritance into account.
+
+Sat May  5 12:39:18 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Version 3.90.9.
+
+Fri May  4 12:12:55 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * breakpoint.c (watch_command, bpstat_stop_status): Deal with
+       exp_valid_block field correctly.
+
+       * infrun.c (wait_for_inferior): When checking "don't even think
+       about breakpoints" if stop_signal == SIGTRAP && trap_expected,
+       also check step_resume_breakpoint.
+       Insert breakpoints and continue (not step) if
+       step_resume_break_address != NULL, even if another_trap.
+       If trap_expected and we enter sigtramp, then set up a
+       step_resume_break.
+       If trap_expected is set when we hit the step_resume_break,
+       set another_trap.
+       When calling resume and trap_expected says tell resume to step
+       (2 places), also check step_resume_break_address.
+
+       * infrun.c (wait_for_inferior): Don't set
+       prev_{pc,sp,func_{start,name}} before calling wait ().
+       Do set them after exiting loop.
+       Move their declarations outside functions.
+       (start_inferior): Initialize them.
+
+Thu May  3 00:15:11 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * infrun.c (wait_for_inferior, after check for trap_expected > 1):
+       Restore old code which distinguishes between trap_expected and
+       running_in_shell, just make the latter take any non-TRAP signal,
+       not just SEGV.
+
+       * values.c (allocate_value): Zero VALUE_OPTIMIZED_OUT flag.
+
+       * Makefile.dist (pinsn.o): Use PINSN_CC to compile.
+       xconfig/3b1 (CC,PINSN_CC): Define.
+
+       * xconfig/altos, altos-dep.c: Rename altos-dep.c to altos-xdep.c.
+
+       * Version 3.90.8
+
+       * breakpoint.c (bpstat_stop_status),
+       infrun.c (wait_for_inferior) [SHIFT_INST_REGS]: New code.
+
+       * param.h, tm-88k.h: Define ADDR_BITS_*.
+       infcmd.c (jump_command, read_pc), infrun.c (wait_for_inferior),
+       printcmd.c (do_one_display): Use them.
+
+       * utils.c: Split #ifdef USG into a USG_UTILS and a QUEUE_MISSING.
+       xm-88k.h: Define USG_UTILS.
+
+Wed May  2 00:05:33 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * printcmd.c (printf_command) [__INT_VARARGS_H]: New code.
+       (printf_command): Add from_tty parameter.
+
+       * valprint.c (value_print): Check VALUE_OPTIMIZED_OUT flag.
+
+       * value.h: Add optimized_out field and change lazy field to
+       char.  Add macro VALUE_OPTIMIZED_OUT.
+
+       * i386-pinsn.c: Change from Eirik Fuller to write to stream directly
+       instead of stuffing things in buffers (oappend, etc).
+
+       * breakpoint.c (bpstat_do_actions): If *BSP is set to NULL by
+       execute_command, exit both loops.
+
+       * Makefile.dist: Don't set TARGET_ARCH.  Add .c.o rule.
+
+Tue May  1 17:07:23 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Makefile.dist (RAPP_OBS, rapp),
+       rgdb.c, rserial.c, rudp.c, serial.c, udp.c, xdep.h,
+       remote.h: Added.
+       m68k-xdep.c, coredep.c: Wrap in #if !defined (RDB).
+
+       * valops.c (value_struct_elt), values.c (value_static_field):
+       Change error messages to remove references to `info methods'.
+
+Tue Apr 24 10:25:10 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * More 88k changes:
+       infrun.c (start_inferior): Add START_INFERIOR_HOOK.
+       infcmd.c [SHIFT_INST_REGS]: New code.
+       findvar.c (read_relative_register_raw_bytes): Return a value.
+       infcmd.c (do_registers_info): Check value from
+       read_relative_register_raw_bytes.
+
+       * command.c (delete_cmd): Free the struct cmd_list_element(s)
+       we are removing.
+
+Mon Apr 23 10:42:21 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * More 88k changes:
+       findvar.c (get_saved_register): New function.
+       findvar.c: Rewrite code which called find_saved_register to
+       call get_saved_register instead.
+
+Sun Apr 22 14:47:51 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * valprint.c (val_print): Change error message printed when
+       the type has TYPE_FLAG_STUB set.
+
+       * valprint.c (val_print): Check for TYPE_CODE_UNDEF.
+
+       * findvar.c (write_register): Set register_valid (regno).
+
+       * valops.c (call_function): Check for NULL return from block_for_pc.
+
+Fri Apr 20 11:31:23 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * findvar.c (write_register): Add PREPARE_TO_STORE.
+       {sun3,sparc,symmetry}-xdep.c (PREPARE_TO_STORE): Add.
+       infptrace.c, {mips,pyr,symmetry,sun3,arm,hp300hpux}-xdep.c
+       (store_inferior_registers): Don't call read_register_bytes.
+       symmetry-xdep.c (store_inferior_registers):
+       #if 0 out code to fetch registers.
+
+       * values.c (value_as_long): Call COERCE_ARRAY.
+
+       * tm-sun3.h: Include tm-68k.h not m-68k.h
+
+       * sparc-tdep.c (single_step): Set next_pc, npc4 within
+       if (!one_stepped), not outside it.
+
+       * Changes from Data General for 88k:
+       * coffread.c (read_file_hdr): Add *88*MAGIC.
+       * coffread.c (have_symbol_file_p): New function.
+       * coffread.c [COFF_CHECK_X_ZEROES] [TDESC]: New code.
+       * coffread.c (read_one_sym): If there is more than one
+       aux entry, don't give an error message, just ignore the
+       extra ones.
+       * coffread.c (process_coff_symbol): Replace clipper with
+       BELIEVE_PCC_PROMOTION in #ifdef's.
+       * coffread.c: Define L_LNNO32 if not defined.
+       (enter_linenos): Use it.
+       * blockframe.c: Add INIT_FRAME_PC hook and use it in
+       get_prev_frame_info.
+       m-m88k.h: Use INIT_{FRAME_PC,EXTRA_FRAME_INFO} to do tdesc stuff.
+       Use dummy versions of FRAME_CHAIN_*.
+       * Makefile.dist, xconfig/i386*: Rename M_CLIBS to XM_CLIBS and add
+       TM_CLIBS and CDEPS.
+       tdesc/libdc.o: New target.
+       tdesc.{c,h}, tdesc/*, {t,x}config/m88k: New files.
+
+Thu Apr 12 15:47:00 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * m68k-opcode.h (bras, bsrs): Use "Bw" not "Bg".
+
+Tue Apr 10 20:50:25 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Version 3.90.7.
+
+       * xm-mips.h (BYTE_ORDER): If not defined, make it LITTLE_ENDIAN.
+
+       * mips-xdep.c ({fetch,store}_inferior_registers): Remove variable
+       offset and just use register_addr (regno, 1).
+       (core_file_command): Remove variable reg_offset and just use
+       register_addr (regno, 0).
+
+       * gdbcore.h [COFF_FORMAT]: #undef a_magic before redefining it.
+
+       * infrun.c ("if (trap_expected && stop_signal != SIGTRAP)", near end
+       of wait_for_inferior): Always pass 0 as first arg to resume.
+       #if 0 out "SIGSEGV in shell" test right above it (now redundant).
+
+       * i386-pinsn.c (oappend_address): New function.
+       (oappend): Make it "static void" and declare at top of file.
+       (OP_J, OP_DIR): Use oappend_address.
+
+Mon Apr  9 15:22:09 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * mips-xdep.c: Include <mips/inst.h> not "mips/inst.h".
+
+       * wait.h [HAVE_WAIT_STRUCT]: Put #defines in #if !defined so that
+       it's OK if they are defined in <sys/wait.h>.
+
+       * findvar.c (fetch_registers): Pass "registers", not "&registers",
+       to remote_fetch_registers.
+
+       * mips-tdep.c (_initialize_mipsdep): Remove hex_disassembler
+       and re-write skip_prologue to use add_set_cmd.
+
+       * Makefile.dist (alldeps.mak): Don't put \ after the last
+       filename in each list.
+
+Sun Apr  8 01:59:19 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Version 3.90.6.
+
+       * Makefile.dist (alldeps.mak): "XM_FILE" -> "XM_FILE=".
+
+       * valarith.c (value_x_{un,bin}op): use "operator" not "operator "
+       to match dbxread.c change of 16 Mar 90.
+
+       * valarith.c (value_x_unop): Pass &static_memfuncp,
+       not static_memfuncp.
+
+       * breakpoint.c: Add watchpoint stuff.
+       breakpoint.h: Add bpstat_should_step.
+       infrun.c (proceed, wait_for_inferior): Use it.
+       breakpoint.h: Add bpstat_print (and rename old bpstat_print
+       to bpstat_should_print).
+       infrun.c (normal_stop): Use it.
+
+       * value.h: Add value_free.  Declare a few functions.
+
+Sat Apr  7 21:43:43 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): Remove PROFILE_TYPES code and
+       insert comment suggesting easy shell script equivalents.
+
+       * values.c (unpack_long): Give better error messages for
+       unrecognized sizes of ints and floats.
+
+Fri Apr  6 00:32:21 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * dbxread.c, gdbcore.h (IS_OBJECT_FILE): Check for a_drsize
+       nonzero as well as a_trsize.
+
+       * More places: Use SWAP_TARGET_AND_HOST.
+
+       * valops.c (destructor_name_p): Only skip "struct " if present.
+
+       * main.c (gdb_readline): Return NULL on end of file.
+
+       * sparc-opcode.h: Add jmp 1+2, jmp 1+i, jmp i+1.
+
+       * Makefile.dist: Make expread.tab.c unambiguously be in srcdir.
+
+       * main.c: Split source_command into source_command and
+       read_command_file.
+       (main): Accept "-" as arg to +command for stdin.
+
+       * dbxread.c (psymtab_to_symtab): Don't read string table.
+       (symbol_file_command): Save string table size.
+
+       * Version 3.90.5
+
+       * symtab.c: Remove declaration of lookup_misc_func.
+
+       * mips-pinsn.c: Add use_hex_p stuff (re-worked from Forin stuff).
+
+       * mips-opcode.h: Add bdelay field.
+       mips-pinsn.c: Various changes from Forin, I think to make it look
+       like the MIPS assembler format.
+       mips-tdep.c, mips-xdep.c, mipsread.c: Various changes from Forin.
+
+       * gdbcore.h: Declare register_addr.
+
+       * gdbcore.h: Include <a.out.h>, before trying to redefine N_TXTADDR
+       and friends.
+       various: Don't include both a.out.h and gdbcore.h.
+
+       * Makefile.dist (HFILES): Add param.h
+
+       * utils.c (init_malloc): Moved here from mcheck.c and modified
+       to use the standard mcheck.c
+       Makefile.dist: Modify to reflect new mcheck.
+
+Thu Apr  5 16:38:28 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * valprint.c (val_print, print_hex_chars): Print integers
+       larger than LONGEST.
+
+       * valarith.c (value_sub): Give error message if attempt to
+       subtract something of the wrong type from a pointer.
+
+       * breakpoint.c (bpstat_stop_status): Initialize retval to NULL.
+
+       * i386-tdep.c (i386_pop_frame): Change addr to adr.
+
+Wed Apr  4 05:21:50 1990  Jim Kingdon  (kingdon at teenage-mutant)
+
+       * main.c (command_line_input): return NULL on end of file.
+       (execute_command): If p is NULL, return almost right away.
+       (read_command_lines): Treat end of file like "end".
+
+       * printcmd.c (print_frame_args): Change it so num is number
+       of ints of args, not number of args.
+
+       * xm-*.h: Make sure BYTE_ORDER is defined.
+       Also fix various #includes of old names of things.
+
+       * main.c (command_line_input): Fix comment code of 2 Apr.
+
+       * values.c (value_from_long, unpack_long): SWAP_TARGET_AND_HOST.
+       various: Replace {BYTES,WORDS}_BIG_ENDIAN with TARGET_BYTE_ORDER.
+       valarith.c various: SWAP_TARGET_AND_HOST.
+       dbxread.c (READ_FILE_HEADERS): SWAP_TARGET_AND_HOST.
+       (SWAP_SYMBOL): New macro.  Use it wherever symbuf_idx is incremented.
+       exec.c (exec_file_command): SWAP_TARGET_AND_HOST.
+
+       * valarith.c (value_subscripted_rvalue): Just bcopy() the
+       appropriate bytes rather than playing strange games with
+       value_from_long.
+
+       * param.h (SWAP_TARGET_AND_HOST): New macro.
+
+       * tm-np1.h (V7_REGNUM): Change from 27 to 26.
+       (REGISTER_VIRTUAL_TYPE): Return correct result for vector regs.
+       gould-tdep.c: New file.
+
+       * Move reading of register before store from
+       findvar.c (write_register) to
+       infptrace.c, *-xdep.c (store_inferior_register).
+
+       * findvar.c (fetch_registers, store_registers): New functions.
+       write_register{,_bytes}: Use store_registers regardless of
+       have_inferior_p.
+       registers_valid: New variable.
+       (supply_register, read_register, etc.): Use it.
+       (read_register_gen): New variable.
+       various: Use read_register_gen rather than read_register_bytes
+       where appropriate.
+       *-xdep.c (fetch_inferior_registers): Remove remote_debugging check.
+       infrun.c (wait_for_inferior, start_inferior): Call registers_changed
+       not fetch_inferior_registers.
+       *-xdep.c (fetch_inferior_registers): Call registers_fetched if
+       not setting registers via supply_register, and if fetching
+       all registers.
+       infptrace.c, *-xdep.c (fetch_inferior_registers): Add param,
+       # of register to fetch (-1 for all).
+       infptrace.c, hp300hpux-xdep.c (fetch_inferior_registers):
+       Actually fetch only those registers needed.
+       value.h: Declare all the extern register functions from findvar.c.
+
+       * coffread.c (read_coff_symtab): Test for specific kinds of GCC
+       labels (LI%.*, LPB%.*, etc), not just ??%.*.
+
+       * coffread.c (record_misc_function): Use mf_text not mf_unknown.
+
+       * utils.c,defs.h (lines_to_list): New function.
+       source.c (select_source_symtab, list_command, forward_search_command,
+       reverse_search_command), stack.c (print_frame_info):
+       Use it instead of 10.
+
+       * munch: If MUNCH_NM variable exists, use it.
+
+       * main.c (initialize_main): Set rl_readline_name.
+       main.c: #include readline.h and #undef savestring.
+       Remove declarations of things declared in readline.h.
+
+       * main.c (gdb_readline): If instream == 0, read from stdin.
+
+       * main.c (main): Only call clearerr if ISATTY.  Exit loop if
+       feof (instream).
+
+       * infcmd.c (detach_command): Set inferior_pid to 0 after
+       calling remote_close.
+
+       * main.c (main): If exec and sym files are the same, and there
+       is an error reading execfile, don't try to read sym file.
+
+       * infcmd.c (detach_command) [ATTACH_DETACH]: Don't try to detach
+       from inferior when remote debugging.
+
+       * source.c (reverse_search_command): Change while test from 1 to
+       line > 1.
+
+Tue Apr  3 18:14:14 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Version 3.90.4.
+
+       * Makefile.dist (gdb.tar.Z): Use -z option to tar rather than
+       creating gdb.tar and calling compress separately.
+
+       * breakpoint.c (read_memory_nobpt): Do not treat bcopy as if it
+       returned an "errno" value.
+
+       * various: Make sure gdbcore.h is not included before a.out.h.
+
+       * Makefile.dist (OPCODES): Add mips-opcode.h.
+
+       * config.gdb: Print lists of {hosts,targets} after finding srcdir.
+       When parsing +{host,target}=, strip off +{host,target}=, not +{x,t}m=.
+
+       * Makefile.dist (gdb.tar): Do {t,x}config not just config.
+
+Mon Apr  2 02:42:23 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * sparc-opcode.h (inc): Fix incorrect lose field.
+
+       * valarith.c (value_subscripted_rvalue): Use TARGET_BYTE_ORDER,
+       rather than checking endianness at runtime.
+
+       * main.c (comand_line_input): Accept comments anywhere, not
+       just at starts of lines.
+
+Sat Mar 31 21:59:35 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * symtab.c (check_stub_type): Call lookup_symbol with 5 args.
+
+Fri Mar 30 15:23:52 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * frame.h: #include param.h.
+       param.h: Protect against multiple inclusion.
+
+       * i386-tdep.c (i386_get_frame_setup): Fix comment about what
+       opcode 0x55 is.
+       If 0x81 or 0x83 is followed by something besides 0xec,
+       put codestream back where it was and return 0.
+       [USE_MACHINE_REG_H]: Include <machine/reg.h> not <sys/reg.h>
+       Move include of a.out.h above <sys/user.h>.
+       (i386_frame_find_saved_regs): Make locals signed.
+       (i386_frame_find_saved_regs, i386_push_dummy_frame, i386_pop_frame):
+       Use REGISTER_BYTES, REGISTER_RAW_SIZE, etc. to deal with floating
+       point registers.
+
+Wed Mar 28 18:33:40 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * Makefile.dist (OTHERS): Add gdb.dvi.
+       (gdb.dvi): New rule.
+
+       * breakpoint.c (_initialize_breakpoint): Clean up docstrings so
+       as not to mention subcommands (e.g. auto-display).
+       Call add_cmd not add_abbrev_cmd for "disable breakpoint" and
+       put it in class_alias.
+
+       * breakpoint.c (set_breakpoint_count): New function.
+       (set_breakpoint, break_command_1): Use it.
+
+       * breakpoint.c (get_number): New function.
+       (*_command, map_breakpoint_numbers): Use it.
+
+       * infptrace.c (write_inferior_memory): Remove remote_debugging
+       stuff (is handled in core.c).
+       (read_inferior_memory): Remove #if 0'd out remote_debugging code.
+
+Tue Mar 27 16:51:27 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * inferior.h: Include frame.h.
+
+       * findvar.c (write_register): Replace sun4 #ifdef with
+       check of CANNOT_STORE_REGISTER.
+       xm-sparc.h: Define CANNOT_STORE_REGISTER.
+
+       * sparc-tdep.c: Remove superfluous declaration of
+       get_breakpoint_commands.
+
+       * breakpoint.{c,h}: Add bpstat stuff.
+       bpstat_do_action: Re-work do_breakpoint_commands into this.
+       main.c (command_loop): Call bpstat_do_action not
+       do_breakpoint_commands.
+       inferior.h, infrun.c, breakpoint.c, infcmd.c:
+       Rework breakpoint_commands and stop_breakpoint
+       stuff to use bpstat instead.
+
+       * infcmd.c (program_info): "info reg"->"info registers".
+
+       * np1-opcode.h: Renamed from npl-opcode.h.
+       gould-pinsn.c: Include np1-opcode.h.
+       Makefile.dist (OPCODES): Change npl-opcode.h to np1-opcode.h
+
+       * coffread.c (read_enum_type): Stop reading when we hit .eos.
+
+Mon Mar 26 15:52:35 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Version 3.90.3.
+
+       * breakpoint.c (read_memory_nobpt): New function.
+       gdbcore.h: Declare read_memory_{nobpt,check}.
+       mips-tdep.c: Use read_memory_nobpt not breakpoint_shadow_val.
+
+Fri Mar 23 14:26:38 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * inflow.c (terminal_inferior): Reenable commented out
+       inferior_thisrun_terminal check.
+       (terminal_ours_1): If inferior_thisrun_terminal is nonzero,
+       return immediately.
+
+       * Makefile.dist: Rewrite DEPFILES, M_FILE, etc. stuff to deal
+       with host & target separation.
+
+       * config/*: Split into xconfig/* and tconfig/*.
+       *-dep.c: Split into *-xdep.c and *-tdep.c.
+
+       * main.c (main): Always pass two args to xrealloc.
+
+Thu Mar 22 20:29:25 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * Makefile.dist ({,dist}clean): rm {x,t}m.h not param.h
+       xgdb.o: Remove obsolete dependency (now in depend).
+
+       * arm-pinsn.c: Include arm-opcode.h not opcode.h.
+
+       * mips-pinsn.c, mips-opcode.h: New files from Bothner (from
+       release of 24 Jan 90 with mips-opcode.h patch from 1 Feb 90).
+
+       * utils.c (xmalloc): Return NULL on request for 0 bytes.
+
+Wed Mar 21 13:30:08 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * config.gdb: Re-write machine stuff to deal with host & target.
+
+       * xm-altos.h: Don't define HAVE_WAIT_STRUCT.
+
+       * m-*.h: Split into xm-*.h and tm-*.h.
+
+       * infrun.c (wait_for_inferior): Put #ifdef sony_news code
+       in regardless of machine.
+
+       * symtab.c (decode_line_1): Add quotes and capitalize error
+       message "no class, struct, or union named".
+
+       * Makefile.dist (cplus-dem.o): Compile with -Dnounderscore.
+
+       * stack.c (print_frame_info): Use print_symbol to print function name.
+
+       * symtab.c (output_source_filename): Don't print a comma if
+       we are skipping a filename already printed.
+
+Tue Mar 20 10:48:54 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * symtab.c (output_source_filename): Don't print a filename
+       more than once.
+
+       * utils.c (fprint_symbol): New function.
+       defs.h: Decalare it.
+       various: Use fprint_symbol to print symbol names.
+       Makefile.dist (SFILES, OBS): Add cplus-dem.{c,o}.
+
+Mon Mar 19 17:11:03 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * coffread.c (read_file_hdr): Add MC68K??MAGIC.
+
+       * coffread.c (read_coff_symtab): Ignore swbeg and string label
+       symbols.
+
+       * coffread.c (read_coff_symtab): Increment num_object_files
+       in case C_STAT not C_FILE.
+       New variable in_source_file.  Set it in case C_FILE.
+       Check it in case C_STAT.
+
+       * coffread.c [FUNCTION_EPILOGUE_SIZE]: New code.
+       m-umax.h (FUNCTION_EPILOGUE_SIZE): Define.
+
+       * config/3b1: New file.
+
+       * config/sun*: Print message warning people to use GAS with GCC.
+
+Sun Mar 18 02:56:40 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * infcmd.c (run_stack_dummy): Change error message.
+
+       * m-68k.h (REGISTER_VIRTUAL_TYPE): Make pc, fp, sp char *.
+
+       * m-mips.h (LONGEST, BUILTIN_TYPE_LONGEST): Remove.
+
+Sat Mar 17 21:27:49 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * mips-dep.c: Remove infptrace.c stuff.
+
+       * m-bigmips.h: New file.
+       m-mips.h [MIPSEB]: Remove *_BIG_ENDIAN stuff.
+
+       * m-sparc.h (FIX_CALL_DUMMY): Do not insert unimp instruction
+       if function was compiled with gcc.
+
+       * m-mips.h: Remove FIX_CALL_DUMMY_ALIGNED and make FIX_CALL_DUMMY
+       use new args.
+
+       * valops.c (call_function): New args to FIX_CALL_DUMMY.
+       m-*.h (FIX_CALL_DUMMY): Take new args.
+
+       * values.c (using_struct_return): New parameter gcc_p.
+       valops.c (call_function): New variable using_gcc.
+       valops.c (call_function) [REG_STRUCT_HAS_ADDR]: New code.
+
+       * m-mips.h, mips-dep.c: New files from Forin.
+       m-mips.h: Replace RETURN_STRUCT_BY_REF with USE_STRUCT_CONVENTION.
+
+Fri Mar 16 13:17:19 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Makefile.dist: Add some dependencies of m-*.h files.
+       (HFILES): Add m-68k.h.
+
+       * dbxread.c (read_struct_type): Put "operator+" not "operator +"
+       in symtab.
+
+       * core.c: Split read_memory into read_memory_check and read_memory.
+       breakpoint.c (insert_breakpoints): If can't read memory,
+       tell user that error was due to seting breakpoints.
+
+Thu Mar 15 11:47:19 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * infrun.c [COFF_ENCAPSULATE]: Include a.out.encap.h.
+
+       * blockframe.c (FRAMELESS_LOOK_FOR_PROLOGUE): Make it a function.
+       various m-*.h: Call function not macro.
+       frame.h: Declare the function.
+
+Wed Mar 14 02:44:51 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * sparc-dep.c: Include signame.h.
+
+       * sparc-pinsn.c (print_insn): When looking for sethi before
+       delayed branch, call read_memory_noerr not read_memory.
+
+       * m-isi.h, m-sun3.h, m-news.h, m-hp300bsd.h, m-altos.h,
+       m-hp300hpux.h, m-sun2.h: Merge machine stuff except inferior
+       function call stuff into new file m-68k.h.  Create m-3b1.h.
+
+Tue Mar 13 21:34:33 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * inflow.c (new_tty): If can't open tty, print error message
+       before exiting.
+
+       * blockframe.c: Remove declaration of psymtab_to_symtab.
+       symtab.h: Declare psymtab_to_symtab.
+       blockframe.c: Remove declarations of block_for_pc and
+       find_pc_function_start.
+       frame.h: Add declarations of block_for_pc and find_pc_function_start.
+       Remove declaration of nonexistent function find_pc_function.
+       values.c: include frame.h instead of declaring block_for_pc.
+
+       * Version 3.90.2.
+
+Mon Mar 12 14:20:06 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * main.c (main): Delete superfluous "e" from long_options.
+
+Sat Mar 10 15:47:23 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * valprint.c (val_print): Print <%d bit integer> not just
+       <large integer>.
+
+       * dbxread.c (error_type): Fix loop that finds '\0' so that on
+       exit, *pp points to the '\0', not the character after.
+       (read_type): Make sure that places which call read_type and then
+       try to read more input stop immediately with another error
+       upon encountering '\0'.
+
+       * dbxread.c (read_range_type): Fix check for large signed
+       integral type to match comment and reality.  Set TYPE_LENGTH based
+       on n2bits for signed, n3bits for unsigned.
+
+       * infcmd.c (cont_command): Print warning message if we
+       decide to ignore the argument.
+
+       * gdb.texinfo (attach): @xref{Attach} -> @xref{Remote}.
+
+Fri Mar  9 16:26:47 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * symtab.h (address_class): Reinstate LOC_EXTERNAL with rewritten
+       comment.
+
+       * expread.y (yyerror, parse_c_1): Make yyerror take a char * arg.
+
+       * main.c (symbol_completion_function): Don't call error() on
+       "info jkldskf".
+
+       * m-npl.h (USE_STRUCT_CONVENTION): Change >= to >.
+
+Thu Mar  8 00:19:01 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * symseg.h: Nuke more symseg references including LOC_EXTERNAL.
+       Put contents of symseg.h into symtab.h and remove symseg.h.
+
+Wed Mar  7 18:02:15 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * symtab.h (SYMBOL_LINE): New macro.
+       symtab.c (decode_line_1): Accept variable as well as function.
+       Lookup variable/function in selected block if no file specified.
+       printcmd.c: #if 0 out whereis_command.
+
+       * command.c (do_setshow_command): Call function with additional
+       argument C.
+       main.c (set_history_size_command): Take argument C.
+       (set_verbose): New function to set docstring.
+       (initialize_main): Put set_verbose in command list.
+       command.c (lookup_cmd_1): Accept result_list NULL.
+
+       * valprint.c (_initialize_valprint): Change docstring for
+       "set unionprint" to normal set/show form.
+
+       * command.c (add_show_from_set): Check that docstring starts with
+       "Set " before assuming it does.
+
+       * main.c (show_history): Call cmd_show_list.
+       command.{c,h} (cmd_show_list): New function.
+       command.h: Declare do_setshow_command.
+
+       * command.h (cmd_list_element): New field completer.
+       main.c (symbol_completion_function): Use it.
+       symtab.h: Declare make_symbol_completion_list.
+       command.c (add_cmd): Set completer.
+       main.c, gdbcmd.h (noop_completer): New function.
+       infcmd.c: Set completer for environment functions.
+
+       * symtab.c (types_info, _initialize_symtab): #if 0 out.
+       various: Use fputs_filtered, not fprintf_filtered(%s).
+
+       * valprint.c (type_print_base): Check for integers larger than
+       LONGEST.
+
+       * sun3-dep.c: Include "signame.h" instead of directly declaring
+       sys_siglist.
+
+Tue Mar  6 14:59:34 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * infrun.c (signals_info): Allow argument to be a signal name
+       as well as an expression.
+       (handle_command): Check for error from sig_number.
+
+       * main.c (float_handler): Change error message.
+
+       * inflow.c (create_inferior): If getenv ("SHELL") exists, use it
+       instead of /bin/sh.
+
+       * dbxread.c (read_dbx_symtab, case N_SO): New variable first_symnum.
+       Pass it to {start,end}_psymtab.
+
+       * dbxread.c (read_ofile_symtab): Increment symbuf_idx and symnum
+       when calling process_symbol_pair.
+
+       * symtab.c (sources_info, output_source_filename):
+       Re-write so output_source_filename takes a first parameter
+       instead of a next one.
+
+       * dbxread.c (read_dbx_symtab, case N_SO): When incrementing
+       symbuf_idx, increment symnum also.
+
+       * values.c (set_internalvar_component): Use VALUE_CONTENTS,
+       not VALUE_CONTENTS_RAW.
+
+       * symmisc.c (free_symtab): Don't free filename (now in symbol_obstack).
+
+       * environ.c (init_environ): Copy entire string, including
+       terminating '\0'.
+
+       * value.h, values.c: Rename value_lazy to value_fetch_lazy.
+       values.c (value_of_internalvar): Call value_fetch_lazy.
+
+       * dbxread.c (read_huge_number): Return an error on encountering
+       a large decimal number.
+
+       * dbxread.c (read_huge_number): Reverse sense of overflow test.
+
+       * valprint.c (val_print, case TYPE_CODE_INT): Check for integers
+       larger than LONGEST.
+
+       * dbxread.c (read_ofile_symtab): When calling process_one_symbol,
+       call it with desc and value rather than with bufp->n_{desc,value}.
+
+       * defs.h (LONG_MAX): Define.
+
+       * sun3-dep.c: Declare sys_siglist.
+
+       * infptrace.c: Move include of gdbcore.h after a.out.h
+
+       * Makefile.dist (expread.o, mcheck.o): Remove leading "./" not
+       leading ".".
+
+       * m-hp300hpux.h [!HPUX_VERSION_5]: Define KERNEL_U_ADDR_HPUX.
+       infptrace.c [KERNEL_U_ADDR_HPUX] [KERNEL_U_ADDR_BSD]:
+       Set kernel_u_addr using nlist().
+       m-hp300bsd.h: Define KERNEL_U_ADDR_BSD.
+
+Mon Mar  5 16:52:41 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): If value of .o symbol is crazy,
+       don't end psymtab.
+
+       * dbxread.c (read_dbx_symtab): Ignore first of a pair of N_SO
+       when both appear.
+       (start_subfile, start_symtab): Extra parameter dirname.
+       (start_subfile): Use obsavestring, not savestring, for name.
+       various: Call start_{subfile,symtab} with extra argument.
+       (end_symtab): Set dirname field in symtab.
+       (read_ofile_symtab): Call process_symbol_pair on pair of N_SO.
+       (process_symbol_pair): New function.
+       symtab.h (symtab): New field dirname.
+       source.c (open_source_file): New function.
+       source.c: Use open_source_file instead of openp where appropriate.
+
+       * defs.h (TARGET_CHAR_BIT): Define.
+
+Sun Mar  4 13:11:48 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * dbxread.c (fill_symbuf): Print error messages nicely.
+
+       * Makefile.dist (SFILES): Put standalone.c at end.
+
+       * Makefile.dist (alldeps.mak): Put out backslash after arm-convert.s.
+
+       * symtab.{c,h} (builtin_type_error): New type.
+       symseg.h (type_code): Add TYPE_CODE_ERROR.
+       valprint.c (val_print, type_print_base),
+       values.c (using_struct_return, set_return_value):
+       Check for and deal with TYPE_CODE_ERROR.
+       dbxread.c (error_type): New function
+       (read_type and subroutines): Call error_type instead of error.
+
+       * dbxread.c (read_huge_number): New function.
+       (read_range_type): Use read_huge_number and check results
+       to see if it is a large integral type.
+
+       * symmisc.c: Remove symseg stuff.
+
+       * Gould NP1 changes from (or inspired by) chpmjd@gdr.bath.ac.uk
+       dbxread.c (read_dbx_symtab) [N_NBSTS]:
+       Treat this and N_NBLCS like N_LCSYM, etc.
+       (process_one_symbol) [BLOCK_ADDRESS_ABSOLUTE]: New code.
+       m-npl.h (USE_STRUCT_CONVENTION): Add.
+       (IGNORE_SYMBOL): Add 0xa4.
+       (END_OF_TEXT_DEFAULT): Remove.
+       (STRING_TABLE_OFFSET): don't add sizeof(int).
+       [!HAVE_VPRINTF]: Define vprintf to be doprnt, not printf.
+       (BLOCK_ADDRESS_ABSOLUTE): Define.
+       (BREAKPOINT): Pad to size of machine word.
+       (SAVED_PC_AFTER_CALL): Remove ` at start of line (!).
+       (R2_REGNUM): Define.
+       (SP_REGNUM, FP_REGNUM): Switch definitions.
+       (REGISTER_U_ADDR): Use FP_REGNUM in place of SP_REGNUM.
+       (STORE_STRUCT_RETURN, EXTACT_RETURN_VALUE, STORE_RETURN_VALUE,
+       call function stuff):
+       Replace bogus definitions with correct ones for NP1.
+       (CANNOT_EXECUTE_STACK): Define.
+       (FRAME_LOCALS_ADDRESS): Don't add 80.
+       (FRAME_FIND_SAVED_REGS): Also get SP.
+       gould-pinsn.c (findframe): Move framechain declaration outside #if 0.
+       infptrace.c (write_inferior_memory): Check addr against text_end
+       and use PT_WRITE_I or PT_WRITE_D as appropriate.
+       (store_inferior_registers): Don't try to write registers in
+       CANNOT_STORE_REGISTER.
+       m-npl.h (CANNOT_STORE_REGISTER): Define.
+       npl-opcode.h (lil): 0xf8080000 -> 0xf80b0000.
+       
+       * munch: Distinguish between BSD and System V nm by actually
+       seeing what output from nm looks like.
+
+Fri Mar  2 13:43:36 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * printcmd.c (print_frame_args): Change highest_offset to point
+       to next unprinted arg.
+
+       * main.c (main): Print "type help for list of commands" along
+       with the version.  Follow it with a blank line.
+
+Thu Mar  1 14:49:26 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * valprint.c: Move print_address for function from value_print
+       to val_print.
+
+Wed Feb 28 15:06:12 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Makefile.dist (m-sun4os4.h): Depend on m-sparc.h
+
+       * Makefile.dist (version.c): Depend on Makefile.dist, not Makefile.
+
+       * Makefile.dist: Change MAKEFILES to Makefiles.
+
+       * symtab.h: Declare get_sym_file.
+       core.c: Include symtab.h.
+
+       * Move signal name stuff from utils.c to signame.c
+       Move signal name stuff from defs.h to signame.h.
+       Makefile.dist (SFILES, HFILES, OBS): Add signame.{c,h,o}.
+
+Mon Feb 26 12:03:12 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * command.c (add_cmd): Don't call savestring on name.
+
+Sun Feb 25 15:52:18 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * printcmd.c (print_frame_args): Make highest_offset an int.
+       New variable args_printed.
+       (print_frame_nameless_args): Remove parameter end and add num
+       and first.
+       (print_frame_args): Change call to print_frame_nameless_args.
+
+Fri Feb 23 21:40:15 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * stack.c (up_command, down_command):
+       Only print stack frame if from_tty.
+
+Thu Feb 22 12:01:36 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * expread.y: Inlcude value.h and don't cast return value from
+       lookup_internalvar.
+
+       * infrun.c: Remove code in #ifdef UMAX_PTRACE.
+
+       * values.c (convenience_info): Print in form "$foo = 5".
+       Don't print "Debugger convenience variables:" before first one.
+
+       * Makefile.dist: Remove ADD_FILES from CLIBS.
+       (gdb, kdb, xgdb): Put in ADD_FILES as well as CLIBS.
+
+       * m-pyr.h: #if 0 out call dummy stuff.
+       Put in POP_FRAME which just calls error().
+       valops.c: If CALL_DUMMY is not defined, put in dummy call_function
+       which just prints an error message.
+
+Tue Feb 20 22:11:40 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * breakpoint.c (commands_command): Add arg from_tty.
+
+       * main.c (main): Put if (!setjmp (to_top_level)) around calls
+       to *_command made in response to command line arguments.
+
+Mon Feb 19 13:58:28 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * main.c (main): Use getopt_long_only.  Move one-character options
+       to long_options.  Remove entries which are just unambiguous
+       abbreviations of other options.
+
+       * command.h: Add types cmd_types and var_types.
+       Add fields type, var_type, and var to struct cmd_list_element.
+       command.c (add_set_cmd, add_set_from_show): New functions.
+       (add_cmd): Set c->var_type.
+       (add_abbrev_cmd): Call add_cmd instead of duplicating code.
+       main.c: Add showlist.
+       Move parse_binary_operation from main.c to command.c.
+       command.c (do_setshow_command): New function.
+       gdbcmd.h: New file.
+       Makefile.dist: Add gdbcmd.h.
+       many files: Include gdbcmd.h, use add_set_cmd and add_show_from_set.
+       Replace info * with show * where appropriate.
+       utils.c (fputs_filtered): Use UINT_MAX in lines_per_page to mean
+       no paging.
+       defs.h: Define UINT_MAX.
+       infcmd.c (run_command): Use execute_command, not set_args_command.
+       main.c (execute_command): Call do_setshow_command if necessary.
+       main.c (show_command, show_history): New functions.
+       main.c (initialize_main): Call add_prefix_cmd
+       for show and show history.
+
+       * coffread.c (enter_linenos): Print error if
+       file_offset < linetab_offset.
+
+Sun Feb 18 15:37:05 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * convex-dep.c (comm_registers_info): Fix typo.  ("argc"->"arg").
+
+Wed Feb 14 20:45:14 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * config.gdb: Create Makefile with make.
+
+       * Makefile.dist, config.gdb: Move "srcdir=" line from Makefile.dist
+       to new file Makefile.srcdir.
+
+       * valprint.c: Include <errno.h>.
+
+       * value.h: Declare value_coerce_function.
+
+       * findvar.c: Add missing " after #include "gdbcore.h
+
+       * main.c (main): Re-write command parsing to use getopt.
+       On "gdb +help" print options with '+' not '-'.
+       Makefile.dist: Add getopt.
+
+Tue Feb 13 00:08:27 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Makefile.dist: Add "srcdir=."
+       config.gdb: Edit srcdir= rather than adding it to the beginning.
+
+       * pyr-dep.c: Make global_reg_offset, last_frame_offset not static.
+       Move definition of reg_stack_offset to core.c [REG_STACK_SEGMENT].
+
+       * config/pyramid: Print message about alloca.
+
+       * breakpoint.c (clear_command): When printing "no breakpoint"
+       error, only use arg if non-NULL.
+
+       * core.c (read_memory): Rename to read_memory_noerr.
+       (read_memory): New function which calls read_memory and checks for err.
+       gdbcore.h: Declare all extern core.c functions.
+       move myread from core.c to utils.c.
+       declare it in defs.h.
+       (read_memory_integer): move from infcmd.c to core.c.
+       gdbcore.h: Declare it.
+       Many places: Remove error checking on read_memory, or call
+       read_memory_noerr instead.  Include "gdbcore.h" if calling either.
+
+       * value.h (COERCE_ARRAY): Coerce functions to function pointers.
+       valops.c (value_coerce_function): New function.
+
+       * core.c, convex-dep.c, arm-dep.c (xfer_core_file): Return EIO
+       if address out of bounds.
+
+       * m-arm.h, arm-dep.c arm-pinsn.c arm-opcode.h: New files.
+       dbxread.c, m-convex.h (VARIABLES_INSIDE_BLOCK): Add gcc_p parameter.
+       Makefile.dist (alldeps.mak): Special case for arm-convert.s.
+       dbxread.c (define_symbol): Check for local based on it not
+       being any one of the known deftypes.
+       values.c (using_struct_return): Use new macro USE_STRUCT_CONVENTION.
+
+       * Makefile.dist, config.gdb: Put in srcdir stuff.
+
+Mon Feb 12 22:46:16 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * breakpoint.c: Add addr_string and cond_string fields to
+       struct breakpoint.
+       (break_command_1): Set them.  Use mention ().
+       (mention): Create with code from break_command_1.
+       (breakpoint_re_set): New function.
+       (breakpoint_clear): Remove.
+       (condition_command): Set cond_string.
+       (breakpoint_delete): Free cond_string and addr_string.
+       Declare parse_c_1's type and remove casts to struct expression *.
+       symmisc.c (free_all_symtabs): Don't call breakpoint_clear.
+       dbxread.c, coffread.c (reread_symbols): Call breakpoint_re_set,
+       Include breakpoint.h.
+       breakpoint.h: New file.
+       dbxread.c: Move declaration of symmisc.c functions to symtab.h.
+
+Sun Feb 11 17:29:23 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * symtab.c: Make lookup_block_symtab extern.
+       symtab.h: Declare it.
+       valops.c (value_of_this): Use it.
+
+Fri Feb  9 08:59:37 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * config/hp300hpux: Print message telling people to use gcc.
+
+       * value.h: Declare print_floating.
+       printcmd.c (print_scalar_formatted, case 'f'): Use print_floating.
+       valprint.c (val_print, case TYPE_CODE_FLT): Use print_floating.
+       valprint.c (print_floating): Make this function out of is_nan
+       and the code which was in val_print.
+       Put parentheses around high & 0xfffff.
+       Print sign and fraction for NaN's.
+       Print 17 digits not 16 for doubles.
+       (is_nan): Remove.
+       m-news.h, m-sun3.h: Define IEEE_FLOAT.
+
+       * Rename gld-pinsn.c to gould-pinsn.c.
+       config/{pn,npl}: Change name of gld-pinsn.c
+
+Tue Feb  6 00:25:36 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * infptrace.c: Define PT_ATTACH if not defined.
+       m-hp300hpux.h: Define ATTACH_DETACH.
+
+       * main.c (initialize_main): Change alias class to aliases.
+
+       * dbxread.c: Search and destroy references to symsegs.
+       Also remove some #if 0'd code.
+
+       * core.c: Remove reread_exec.
+       dbxread.c (reread_symbols): New function.
+       dbxread.c (symbol_file_command): Set symfile_mtime.
+       coffread.c: Same.
+       infcmd.c (run_command): Call reread_symbols not reread_exec.
+
+       * valprint.c (val_print): When printing string after char *, print
+       it for "" just like any other string.
+
+       * core.c (reread_exec): New procedure.
+       infcmd.c (run_command): Call reread_exec.
+
+       * coffread.c (symbol_file_command): Add from_tty.
+
+       * dbxread.c (symbol_file_command): Only ask about loading new
+       symbol table if from_tty.
+
+Mon Feb  5 02:25:25 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * inflow.c (inferior_died): Call breakpoint_clear_ignore_counts.
+
+       * Makefile.dist (OBS): Remove dbxread.o and coffread.o.
+
+       * config.gdb: Ignore files ending in '#' in config.
+
+       * stack.c (backtrace_command): Add QUIT to get_prev_frame loops.
+
+Sat Feb  3 22:25:09 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * Makefile.dist (YACC): Don't use -v.
+
+Fri Feb  2 19:26:50 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * createtags: Only change .o to .c at end of name.
+
+       * Makefile.dist (alldeps.mak): new target.
+       (Makefile): add alldeps.mak.
+       (SOURCES): remove PINSNS.
+       (TAGFILES: use ALLPARAM.
+       (gdb.tar): add config/.
+
+       * config.gdb: Check for M_FILE= not #param.h
+       config/*: Make sure M_FILE= exists with space after M_FILE=.
+       Makefile.dist (TAGS): Pass M_FILE and DEPFILES.
+       createtags: Change .o to .c.  Remove special tests for dep.c etc.
+
+       * dbxread.c, coffread.c: Don't check COFF_FORMAT and READ_DBX_FORMAT.
+       Makefile.dist: Move {dbx,coff}read.c from SFILES to ALLDEPFILES.
+       config/*: add dbxread.o or coffread.o to depfiles.
+
+       * Makefile.dist (depend): Depend on $(SOURCES), not force.
+
+Thu Feb  1 17:43:54 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * symmisc.c (print_symbol): Print newline after label.
+
+Wed Jan 31 22:35:38 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * dbxread.c (read_addl_syms): Remove code that checks for
+       _etext.
+       Move end_of_text_addr into read_dbx_symtab.
+       (read_dbx_symtab): #if 0 out code which checks for _etext.
+
+Tue Jan 30 15:40:19 1990  Jim Kingdon  (kingdon at albert.ai.mit.edu)
+
+       * Makefile.dist (gdb.tar): Use readline's "make readline.tar"
+       instead of having a list of readline files.
+
+       * infrun.c (normal_stop): #if 0 out "you have found a bug in sh".
+
+       * munch (-DSYSV): Check for .text at end of name.
+       Optionally allow extra underscore before initialize.
+       Remove space between #! and /bin/sh.
+
+       * m-merlin.h: Put in clarifying comments about SHELL_FILE.
+       Makefile.dist (install): Execute M_INSTALL.
+       config/merlin: Define M_INSTALL.
+
+Mon Jan 29 04:32:09 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * inflow.c: Change all references to signal handlers from
+       int (*)() to void (*)().
+
+       * main.c: Declare init_signals before use & make it void.
+       Declare initialize_all_files.
+
+       * Makefile.dist (config.status): New target.
+
+Sat Jan 27 00:19:50 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * defs.h (enum command_class): Remove comma after last element.
+
+       * Makefile.dist (gdb.tar.Z): Use compress <foo >bar rather
+       than deleting gdb.tar.Z before starting.
+
+       * dbxread.c (process_one_symbol): Compare context_stack_depth
+       with !VARIABLES_INSIDE_BLOCK, not VARIABLES_INSIDE_BLOCK.
+
+       * mcheck.c: Put whole file in #if defined MALLOC_RANGE_CHECK.
+
+       * mcheck.c (checkhdr): Call fatal_dump_core not abort.
+
+       * mcheck.c: Copy from malloc distribution.
+
+       * main.c (main): Call init_malloc ().
+
+       * main.c (initialize_signals): Rename to init_signals.
+
+Fri Jan 26 00:53:23 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * *dep.c: Make core_file_command return void.
+
+       * gdbcore.h [!KERNEL_U_ADDR]: Declare kernel_u_addr.
+       infptrace.c [!KERNEL_U_ADDR]: Make it extern.
+
+       * altos-dep.c (NBPG, UPAGES): Wrap #define in #if !defined.
+
+       * m-pn.h (GOULD_PN): Define.
+       *-pinsn.c: Include actual opcode table not just opcode.h
+
+       * main.c [ALIGN_STACK_ON_STARTUP]: New code.
+       m-i386.h: Define ALIGN_STACK_ON_STARTUP.
+
+       * m-merlin.h (NO_SIGINTERRUPT, SHELL_FILE): Define.
+
+       * Move code from infptrace [USE_PTRACE_GETREGS] to sun3-dep.c.
+       m-sun{2,3}.h, m-sparc.h: Define FETCH_INFERIOR_REGISTERS.
+
+       * Makefile.dist, config.gdb, config/*:
+       Re-write to use machine-dependent makefiles instead of cpp.
+
+       * m-hp300hpux.h: Define FETCH_INFERIOR_REGISTERS.
+       infptrace.c: Put {fetch,store}_inferior_registers inside
+       #if !defined FETCH_INFERIOR_REGISTERS.
+
+       * Split execcore.c into exec.c and coredep.c.
+       Move a bunch of stuff from coredep.c and *dep.c to gdbcore.h.
+
+       * infptrace.c ({fetch,store}_inferior_registers):
+       Use U_REGS_OFFSET to set offset.
+       m-umax.h: Define U_REGS_OFFSET.
+
+       * m-umax.h: Define PTRACE_{ATTACH,DETACH}.
+
+       * m-i386.h (N_SET_MAGIC): Define.
+       m-i386gas.h: add #undef N_SET_MAGIC.
+
+Thu Jan 25 18:39:45 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * m-hp300bsd.h: Remove KERNEL_U_ADDR.
+
+       * infptrace.c [!KERNEL_U_ADDR]: Get address of kernel u area
+       at runtime.
+
+       * infptrace.c: Replace numbers with PT_KILL, etc.
+       (store_inferior_registers): Loop for as many words are in the register.
+
+       * infptrace.c [NO_SINGLE_STEP]: Call single_step().
+
+       * kill_inferior{,_fast}: Declare as returning void.
+
+       * m-sun3.h (USE_PTRACE_GETREGS): Define.
+
+       * execcore.c: Add IS_OBJECT_FILE & related stuff.
+
+       * infptrace.c: Include <sys/ptrace.h>.
+       [ATTACH_DETACH] [USE_PTRACE_GETREGS]: New code.
+
+       * Split default-dep.c into infptrace.c and execcore.c.
+
+       * valprint.c [IEEE_FLOAT]: Change void * to char *.
+
+       * breakpoint.c: Change printf_filtered(%s) to fputs_filtered.
+
+Wed Jan 24 00:35:52 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * dbxread.c (symbol_file_command): When freeing everything, free
+       the string table too.
+
+       * Makefile.dist (gdb1): add "rm -f gdb1".
+
+       * printcmd.c (print_scalar_formatted): If size is 0, use 'b'
+       'h', 'w', or 'g' depending on the type.
+
+       * stack.c (backtrace_command): Read in symbols for frames we'll
+       print before printing them.
+
+       * valops.c (value_at): Don't print "I/O error" on EIO from
+       ptrace.  Don't print "out of bounds" for any ptrace error
+       except EIO.
+
+       * valprint.c (type_print_base, case TYPE_CODE_ENUM):
+       Print "FOO = 5" not "FOO : 5".
+
+       * symtab.{c,h}: Make lookup_misc_func extern.
+
+       * Makefile.dist: Define VERSION in makefile, and generate
+       version.c automatically.
+       (gdb.tar): Use gdb-$(VERSION), not dist-gdb.
+
+       * expread.y (yylex): Use lookup_primitive_typename to
+       cut down on calls to lookup_symbol.
+       symtab.{c,h} (lookup_primitive_typename): New function.
+       (lookup_typename): Use it.
+
+       * symtab.{c,h} (check_stub_type): New function.
+       valprint.c (type_print_base, val_print, type_print_derivation_info),
+       values.c (allocate_value): Call it.
+
+       * printcmd.c (whereis_command): New function.
+       symtab.c (lookup_symbol): Add symtab parameter.
+       various: Pass additional argument to lookup_symbol.
+       symseg.h (struct symbol): Add line field.
+       dbxread.c (define_symbol): Set sym->line.
+
+       * dbxread.c (symbol_file_command): Read string table into
+       malloc'd memory (symfile_string_table) and leave it there.
+       (psymtab_to_symtab): Use symfile_string_table.
+
+       * utils.c (sig_abbrev): Return NULL if not found.
+       infrun.c (sig_print_{header,info}): Consolidate duplicated
+       code from handle_command, signals_info.
+       (sig_print_info): Just print number if no name from sig_abbrev.
+
+       * Makefile.dist (OTHERS): Add ChangeLog-3.x
+
+       * infrun.c (restore_inferior_status): #if 0 out
+       "Unable to restore previously selected frame" error message.
+
+       * infrun.c (signals_info, handle_command): Print signal
+       abbrevs along with numbers.
+
+       * infrun.c (handle_command): Accept symbol signal names.
+
+       * utils.c (sig_{number,abbrev}, init_sig): New functions.
+       _initialize_utils: Call init_sig for each signal.
+       defs.h: Declare them.
+
+       * default-dep.c (read_inferior_memory): Check quit_flag in
+       fetch loop.
+
+       * Changes for lazy fetching (speeds things up for big objects):
+       value.h (struct value): New field lazy.
+       VALUE_CONTENTS_RAW, VALUE_LAZY, value_at_lazy: New.
+       findvar.c (read_var_value): Set lazy instead of fetching.
+       various: Copy into VALUE_CONTENTS_RAW, not VALUE_CONTENTS.
+       valops.c: Add value_at_lazy, value_lazy.
+       various: Call value_at_lazy instead of value_at.
+
+       * symtab.h (LONGEST): Define.
+
+       * m-*.h (LONGEST, BUILTIN_TYPE_LONGEST): Delete (in symtab.h).
+
+       * infrun.c (wait_for_inferior): #if 0 out stop if ABOUT_TO_RETURN
+
+       * version.c: Change version number to 4.0development
+
+For older changes see ChangeLog-3.x
+\f
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-3.x b/gdb/ChangeLog-3.x
new file mode 100644 (file)
index 0000000..e8dbcd8
--- /dev/null
@@ -0,0 +1,4846 @@
+Tue Jan 23 15:49:47 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+       * dbxread.c (define_symbol): Deal with deftype 'X'.
+
+       * convex-dep.c (wait): Make it pid_t.
+
+       * convex-dep.c (comm_registers_info): accept decimal comm register
+       specification, as "i comm 32768".
+
+       * dbxread.c (process_one_symbol): Make VARIABLES_INSIDE_BLOCK
+       macro say by itself where variables are.  Pass it desc.
+       m-convex.h (VARIABLES_INSIDE_BLOCK): Nonzero for native compiler.
+
+       * m-convex.h (SET_STACK_LIMIT_HUGE): Define.
+       (IGNORE_SYMBOL): Take out #ifdef N_MONPT and put in 0xc4.
+
+Fri Jan 19 20:04:15 1990  Jim Kingdon  (kingdon at albert.ai.mit.edu)
+
+       * printcmd.c (print_frame_args): Always set highest_offset to
+       current_offset when former is -1.
+
+       * dbxread.c (read_struct_type): Print nice error message
+       when encountering multiple inheritance.
+
+Thu Jan 18 13:43:30 1990  Jim Kingdon  (kingdon at mole.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): Always treat N_FN as a potential
+       source for a x.o or -lx symbol, ignoring OFILE_FN_FLAGGED.
+
+       * printcmd.c (print_frame_args): Cast -1 to (CORE_ADDR).
+
+       * hp300bsd-dep.c (_initialize_hp300_dep): Get kernel_u_addr.
+       m-hp300bsd.h (KERNEL_U_ADDR): Use kernel_u_addr.
+
+       * infcmd.c (run_command): #if 0 out call to
+       breakpoint_clear_ignore_counts.
+
+Thu Jan 11 12:58:12 1990  Jim Kingdon  (kingdon at mole)
+
+       * printcmd.c (print_frame_args) [STRUCT_ARG_SYM_GARBAGE]:
+       Try looking up name of var before giving up & printing '?'.
+
+Wed Jan 10 14:00:14 1990  Jim Kingdon  (kingdon at pogo)
+
+       * many files: Move stdio.h before param.h.
+
+       * sun3-dep.c (store_inferior_registers): Only try to write FP
+       regs #ifdef FP0_REGNUM.
+
+Mon Jan  8 17:56:15 1990  Jim Kingdon  (kingdon at pogo)
+
+       * symtab.c: #if 0 out "info methods" code.
+
+Sat Jan  6 12:33:04 1990  Jim Kingdon  (kingdon at pogo)
+
+       * dbxread.c (read_struct_type): Set TYPE_NFN_FIELDS_TOTAL
+       from all baseclasses; remove vestigial variable baseclass.
+
+       * findvar.c (read_var_value): Check REG_STRUCT_HAS_ADDR.
+       printcmd.c (print_frame_args):  Check STRUCT_ARG_SYM_GARBAGE.
+       m-sparc.h: Define REG_STRUCT_HAS_ADDR and STRUCT_ARG_SYM_GARBAGE.
+
+       * blockframe.c (get_frame_block): Subtract one from pc if not
+       innermost frame.
+
+Fri Dec 29 15:26:33 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * printcmd.c (print_frame_args): check highest_offset != -1, not i.
+
+Thu Dec 28 16:21:02 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * valops.c (value_struct_elt): Clean up error msg.
+
+       * breakpoint.c (describe_other_breakpoints):
+       Delete extra space before "also set at" and add period at end.
+
+Tue Dec 19 10:28:42 1989  Jim Kingdon  (kingdon at pogo)
+
+       * source.c (print_source_lines): Tell user which line number
+       was out of range when printing error message.
+
+Sun Dec 17 14:14:09 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * blockframe.c (find_pc_partial_function): Use
+       BLOCK_START (SYMBOL_BLOCK_VALUE (f)) instead of
+       SYMBOL_VALUE (f) to get start of function.
+
+       * dbxread.c: Make xxmalloc just a #define for xmalloc.
+
+Thu Dec 14 16:13:16 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * m68k-opcode.h (fseq & following fp instructions):
+       Change @ to $.
+
+Fri Dec  8 19:06:44 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * breakpoint.c (breakpoint_clear_ignore_counts): New function.
+       infcmd.c (run_command): Call it.
+
+Wed Dec  6 15:03:38 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * valprint.c: Change it so "array-max 0" means there is
+       no limit.
+
+       * expread.y (yylex): Change error message "invalid token in
+       expression" to "invalid character '%c' in expression".
+
+Mon Dec  4 16:12:54 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * blockframe.c (find_pc_partial_function): Always return 1
+       for success, 0 for failure, and set *NAME and *ADDRESS to
+       match the return value.
+
+       * dbxread.c (symbol_file_command): Use perror_with_name on
+       error from stat.
+       (psymtab_to_symtab, add_file_command),
+       core.c (validate_files), source.c (find_source_lines),
+       default-dep.c (exec_file_command): Check for errors from stat,
+       fstat, and myread.
+
+Fri Dec  1 05:16:42 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * valops.c (check_field): When following pointers, just get
+       their types; don't call value_ind.
+       
+Thu Nov 30 14:45:29 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * config.gdb (pyr): New machine.
+       core.c [REG_STACK_SEGMENT]: New code.
+       dbxread.c (process_one_symbol): Cast return from copy_pending
+       to long before casting to enum namespace.
+       infrun.c: Split registers_info into DO_REGISTERS_INFO
+       and registers_info.
+       m-pyr.h, pyr-{dep.c,opcode.h,pinsn.c}: New files.
+
+       * hp300bsd-dep.c: Stay in sync with default-dep.c.
+
+       * m-hp300bsd.h (IN_SIGTRAMP): Define.
+
+Mon Nov 27 23:48:21 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * m-sparc.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE):
+       Return floating point values in %f0.
+
+Tue Nov 21 00:34:46 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c (read_type): #if 0 out code which skips to
+       comma following x-ref.
+
+Sat Nov 18 20:10:54 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * valprint.c (val_print): Undo changes of Nov 11 & 16.
+       (print_string): Add parameter force_ellipses.
+       (val_print): Pass force_ellipses true when we stop fetching string
+       before we get to the end, else pass false.
+
+Thu Nov 16 11:59:50 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * infrun.c (restore_inferior_status): Don't try to restore
+       selected frame if the inferior no longer exists.
+
+       * valprint.c (val_print): Rewrite string printing code not to
+       call print_string.
+
+       * Makefile.dist (clean): Remove xgdb and xgdb.o.
+
+Tue Nov 14 12:41:47 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * Makefile.dist (XGDB, bindir, xbindir, install, all): New stuff.
+
+Sat Nov 11 15:29:38 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * valprint.c (val_print): chars_to_get: New variable.
+
+Thu Nov  9 12:31:47 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * main.c (main): Process "-help" as a switch that doesn't
+       take an argument.
+
+Wed Nov  8 13:07:02 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * Makefile.dist (gdb.tar.Z): Add "else true".
+
+Tue Nov  7 12:25:14 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * infrun.c (restore_inferior_status): Don't dereference fid if NULL.
+
+       * config.gdb (sun3, sun4): Accept "sun3" and "sun4".
+
+Mon Nov  6 09:49:23 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * Makefile.dist (Makefile): Move comments after commands.
+
+       * *-dep.c [READ_COFF_SYMTAB]: Pass optional header size to
+       read_section_hdr().
+
+       * inflow.c: Include <fcntl.h> regardless of USG.
+
+       * coffread.c (read_section_hdr): Add optional_header_size.
+       (symbol_file_command): Pass optional header size to
+       read_section_hdr().
+       (read_coff_symtab): Initialize filestring.
+
+       * version.c: Change version to 3.4.xxx.
+
+       * GDB 3.4 released.
+
+Sun Nov  5 11:39:01 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * version.c: Change version to 3.4.
+
+       * symtab.c (decode_line_1): Only skip past "struct" if it
+       is there.
+
+       * valops.c (value_ind), eval.c (evaluate_subexp, case UNOP_IND):
+       Have "*" <int-valued-exp> return an int, not a LONGEST.
+
+       * utils.c (fprintf_filtered): Pass arg{4,5,6} to sprintf.
+
+       * printcmd.c (x_command): Use variable itself rather
+       than treating it as a pointer only if it is a function.
+       (See comment "this makes x/i main work").
+
+       * coffread.c (symbol_file_command): Use error for
+       "%s does not have a symbol-table.\n".
+
+Wed Nov  1 19:56:18 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c [BELIEVE_PCC_PROMOTION_TYPE]: New code.
+       m-sparc.h: Define BELIEVE_PCC_PROMOTION_TYPE.
+
+Thu Oct 26 12:45:00 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * infrun.c: Include <sys/dir.h>.
+
+       * dbxread.c (read_dbx_symtab, case N_LSYM, case 'T'):
+       Check for enum types and put constants in psymtab.
+
+Mon Oct 23 15:02:25 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c (define_symbol, read_dbx_symtab): Handle enum
+       constants (e.g. "b:c=e6,0").
+
+Thu Oct 19 14:57:26 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * stack.c (frame_info): Use FRAME_ARGS_ADDRESS_CORRECT
+       m-vax.h (FRAME_ARGS_ADDRESS_CORRECT): New macro.
+       (FRAME_ARGS_ADDRESS): Restore old meaning.
+
+       * frame.h (Frame_unknown): New macro.
+       stack.c (frame_info): Check for Frame_unknown return from
+       FRAME_ARGS_ADDRESS.
+       m-vax.h (FRAME_ARGS_ADDRESS): Sometimes return Frame_unknown.
+
+       * utils.c (fatal_dump_core): Add "internal error" to message.
+
+       * infrun.c (IN_SIGTRAMP): New macro.
+       (wait_for_inferior): Use IN_SIGTRAMP.
+       m-vax.h (IN_SIGTRAMP): New macro.
+
+Wed Oct 18 15:09:22 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * config.gdb, Makefile.dist: Shorten m-i386-sv32.h.
+
+       * coffread.c (symbol_file_command): Pass 0 to select_source_symtab.
+
+Tue Oct 17 12:24:41 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * i386-dep.c (i386_frame_num_args): Take function from m-i386.h
+       file.  Check for pfi null.
+       m-i386.h (FRAME_NUM_ARGS): Use i386_frame_num_args.
+
+       * infrun.c (wait_for_inferior): set stop_func_name to 0
+       before calling find_pc_partial_function.
+
+Thu Oct 12 01:08:50 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * breakpoint.c (_initialize_breakpoint): Add "disa".
+
+       * Makefile.dist: Add GLOBAL_CFLAGS and pass to readline.
+
+       * config.gdb (various): "$machine =" -> "machine =".
+
+Wed Oct 11 11:54:31 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * inflow.c (try_writing_regs): #if 0 out this function.
+
+       * main.c (main): Add "-help" option.
+
+       * dbxread.c (read_dbx_symtab): Merge code for N_FUN with
+       N_STSYM, etc.
+
+Mon Oct  9 14:21:55 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * inflow.c (try_writing_regs_command): Don't write past end
+       of struct user.
+
+       * dbxread.c (read_struct_type): #if 0 out code which checks for
+       bitpos and bitsize 0.
+
+       * config.gdb: Accept sequent-i386 (not seq386).
+       (symmetry): Set depfile and paramfile.
+
+       * m-convex.h (IGNORE_SYMBOL): Check for N_MONPT if defined.
+
+Thu Oct  5 10:14:26 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * default-dep.c (read_inferior_memory): Put #if 0'd out comment
+       within /* */.
+
+Wed Oct  4 18:44:41 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * config.gdb: Change /dev/null to m-i386.h for various
+       386 machine "opcodefile" entries.
+
+       * config.gdb: Accept seq386 for sequent symmetry.
+
+Mon Oct  2 09:59:50 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * hp300bsd-dep.c:  Fix copyright notice.
+
+Sun Oct  1 16:25:30 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * Makefile.dist (DEPFILES): Add isi-dep.c.
+
+       * default-dep.c (read_inferior_memory): Move #endif after else.
+
+Sat Sep 30 12:50:16 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * version.c: Change version number to 3.3.xxx.
+
+       * GDB 3.3 released.
+
+       * version.c: Change version number to 3.3.
+
+       * Makefile.dist (READLINE): Add vi_mode.c
+
+       * config.gdb (i386): Change /dev/null to m-i386.h
+
+       * config.gdb: Add ';;' before 'esac'.
+
+       * Makefile.dist (gdb.tar.Z): Move comment above dependency.
+
+       * dbxread.c (read_ofile_symtab): Check symbol before start
+       of source file for GCC_COMPILED_FLAG_SYMBOL.
+       (start_symtab): Don't clear processing_gcc_compilation.
+
+Thu Sep 28 22:30:23 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+       * valprint.c (print_string): If LENGTH is zero, print "".
+
+Wed Sep 27 10:15:10 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * config.gdb: "rm tmp.c" -> "rm -f tmp.c".
+
+Tue Sep 26 13:02:10 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * utils.c (_initialize_utils): Use termcap to set lines_per_page
+       and chars_per_line.
+
+Mon Sep 25 10:06:43 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab, N_SOL): Do not add the same file
+       more than once.
+
+Thu Sep 21 12:43:18 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * infcmd.c (unset_environment_command): Delete all variables
+       if called with no arg.
+
+       * remote.c, inferior.h (remote_{read,write}_inferior_memory):
+       New functions.
+       core.c ({read,write}_memory): Use remote_{read,write}_inferior_memory.
+
+       * valops.c (call_function): When reserving stack space for
+       arguments, call value_arg_coerce.
+
+       * m-hp9k320.h: define BROKEN_LARGE_ALLOCA.
+
+       * breakpoint.c (delete_command): Ask for confirmation only
+       when there are breakpoints.
+
+       * dbxread.c (read_struct_type): If lookup_basetype_type has
+       copied a stub type, call add_undefined_type.
+
+       * sparc_pinsn.c (compare_opcodes): Check for "1+i" anywhere
+       in args.
+
+       * val_print.c (type_print_base): Print stub types as
+       "<incomplete type>".
+
+Wed Sep 20 07:32:00 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * sparc-opcode.h (swapa): Remove i bit from match.
+       (all alternate space instructions): Delete surplus "foo rs1+0"
+       patterns.
+
+       * Makefile.dist (LDFLAGS): Set to $(CFLAGS).
+
+       * remote-multi.shar (remote_utils.c, putpkt): Change csum to unsigned.
+
+Tue Sep 19 14:15:16 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * sparc-opcode.h: Set i bit in lose for many instructions which
+       aren't immediate.
+
+       * stack.c (print_frame_info): add "func = 0".
+
+Mon Sep 18 16:19:48 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * sparc-opcode.h (mov): Add mov to/from %tbr, %psr, %wim.
+
+       * sparc-opcode.h (rett): Fix notation to use suggested assembler
+       syntax from architecture manual.
+
+       * symmetry-dep.c (I386_REGNO_TO_SYMMETRY): New macro.
+       (i386_frame_find_saved_regs): Use I386_REGNO_TO_SYMMETRY.
+
+Sat Sep 16 22:21:17 1989  Jim Kingdon  (kingdon at spiff)
+
+       * remote.c (remote_close): Set remote_desc to -1.
+
+       * gdb.texinfo (Output): Fix description of echo to match
+       reality and ANSI C.
+
+Fri Sep 15 14:28:59 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * symtab.c (lookup_symbol): Add comment about "asm".
+
+       * sparc-pinsn.c: Use NUMOPCODES.
+
+       * sparc-opcode.h (NUMOPCODES): Use sparc_opcodes[0] not *sparc_opcodes.
+
+Thu Sep 14 15:25:20 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (xxmalloc): Print error message before calling abort().
+
+       * infrun.c (wait_for_inferior): Check for {stop,prev}_func_name
+       null before passing to strcmp.
+
+Wed Sep 13 12:34:15 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * sparc-opcode.h: New field delayed.
+       sparc-pinsn.c (is_delayed_branch): New function.
+       (print_insn): Check for delayed branches.
+
+       * stack.c (print_frame_info): Use misc_function_vector in
+       case where ar truncates file names.
+
+Tue Sep 12 00:16:14 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * convex-dep.c (psw_info): Move "struct pswbit *p" with declarations.
+
+Mon Sep 11 14:59:57 1989  Jim Kingdon  (kingdon at spiff)
+
+       * convex-dep.c (core_file_command): Delete redundant printing
+       of "Program %s".
+
+       * m-convex.h (ENTRY_POINT): New macro.
+
+       * m-convex.h (FRAME_CHAIN_VALID): Change outside_first_object_file
+       to outside_startup_file
+
+       * main.c: #if 0 out catch_termination and related code.
+
+       * command.c (lookup_cmd_1): Consider underscores part of
+       command names.
+
+Sun Sep 10 09:20:12 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * printcmd.c: Change asdump_command to disassemble_command
+       (_initialize_printcmd): Change asdump to diassemble.
+
+       * main.c (main): Exit with code 0 if we hit the end of a batch
+       file.
+
+       * Makefile.dist (libreadline.a): Fix syntax of "CC=${CC}".
+
+Sat Sep  9 01:07:18 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * values.c (history_info): Renamed to value_history_info.
+       Command renamed to "info value" (with "info history" still
+       accepted).
+
+       * sparc-pinsn.c (print_insn): Extend symbolic address printing
+       to cover "sethi" following by an insn which uses 1+i.
+
+Fri Sep  8 14:24:01 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * m-hp9k320.h, m-hp300bsd.h, m-altos.h, m-sparc.h, m-sun3.h
+       (READ_GDB_SYMSEGS): Remove.
+       dbxread.c [READ_GDB_SYMSEGS]: Remove code to read symsegs.
+
+       * sparc-pinsn.c (print_insn): Detect "sethi-or" pairs and
+       print symbolic address.
+
+       * sparc-opcode.h (sethi, set): Change lose from 0xc0000000 to
+       0xc0c00000000. 
+
+       * remote.c (remote_desc): Initialize to -1.
+
+       * Makefile.dist (libreadline.a): Pass CC='${CC}' to readline makefile.
+
+Thu Sep  7 00:07:17 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (read_struct_type): Check for static member functions.
+       values.c, eval.c, valarith.c, valprint.c, valops.c: Merge changes
+       from Tiemann for static member functions.
+
+       * sparc-opcode.h (tst): Fix all 3 patterns.
+
+       * Makefile.dist (gdb1): New rule.
+
+       * sparc-opcode.h: Change comment about what the disassembler
+       does with the order of the opcodes.
+
+       * sparc-pinsn.c (compare_opcodes): Put 1+i before i+1.
+       Also fix mistaken comment about preserving order of original table.
+
+       * sparc-opcode.h (clr, mov): Fix incorrect lose entries.
+
+       * m-symmetry.h (FRAME_NUM_ARGS): Add check to deal with code that
+       GCC sometimes generates.
+
+       * config.gdb: Change all occurances of "skip" to "/dev/null".
+
+       * README (about languages other than C): Update comments about
+       Pascal and FORTRAN.
+
+       * sparc-opcode.h (nop): Change lose from 0xae3fffff to 0xfe3fffff.
+
+       * values.c (value_virtual_fn_field): #if 0-out assignment to
+       VALUE_TYPE(vtbl).
+
+Wed Sep  6 12:19:22 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * utils.c (fatal_dump_core): New function.
+       Makefile.dist (MALLOC_FLAGS): use -Dbotch=fatal_dump_core
+
+Tue Sep  5 15:47:18 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * breakpoint.c (enable_command): With no arg, enable all bkpts.
+
+       * Makefile.dist (Makefile): Remove \"'s around $(MD).
+
+       * Makefile.dist: In "cd readline; make . . ." change first
+       SYSV_DEFINE to SYSV.
+
+       * m68k-pinsn.c (_initialize_pinsn): Use alternate assembler
+       syntax #ifdef HPUX_ASM
+
+Sat Sep  2 23:24:43 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * values.c (history_info): Don't check num_exp[0] if num_exp
+       is nil (just like recent editing_info change).
+
+Fri Sep  1 19:19:01 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * gdb.texinfo (inc-history, inc-readline): Copy in the inc-* files
+       because people might not have makeinfo.
+
+       * README (xgdb): Strengthen nasty comments.
+
+       * gdb.texinfo: Change @setfilename to "gdb.info".
+
+Thu Aug 31 17:23:50 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * main.c (editing_info): Don't check arg[0] if arg is null.
+
+       * m-vax.h: Add comment about known sigtramp bug.
+
+       * sun3-dep.c, sparc-dep.c (IS_OBJECT_FILE, exec_file_command):
+       Get right text & data addresses for .o files.
+
+Wed Aug 30 13:54:19 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * utils.c (tilde_expand): Remove function (it's in readline).
+
+       * sparc-opcode.h (call): Change "8" to "9" in first two
+       patterns (%g7->%o7).
+
+Tue Aug 29 16:44:41 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * printcmd.c (whatis_command): Change 4th arg to type_print
+       from 1 to -1.
+
+Mon Aug 28 12:22:41 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c (psymtab_to_symtab_1): In "and %s ..." change
+       pst->filename to pst->dependencies[i]->filename.
+
+       * blockframe.c (FRAMELESS_LOOK_FOR_PROLOGUE): New macro
+       made from FRAMELESS_FUNCTION_INVOCATION from m-sun3.h except
+       that it checks for zero return from get_pc_function_start.
+       m-hp9k320.h, m-hp300bsd.h, m-i386.h, m-isi.h, m-altos.h,
+       m-news.h, m-sparc.h, m-sun2.h, m-sun3.h, m-symmetry.h
+       (FRAMELESS_FUNCTION_INVOCATION): Use FRAMELESS_LOOK_FOR_PROLOGUE.
+
+       * dbxread.c (read_struct_type): Give warning and ignore field
+       if bitpos and bitsize are zero.
+
+Sun Aug 27 04:55:20 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (psymtab_to_symtab{,_1}): Print message about
+       reading in symbols before reading stringtab, not after.
+
+Sat Aug 26 02:01:53 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c (IS_OBJECT_FILE, ADDR_OF_TEXT_SEGMENT): New macros.
+       (read_dbx_symtab): Use text_addr & text_size to set end_of_text_addr.
+       (symbol_file_command): pass text_addr & text_size to read_dbx_symtab.
+
+Fri Aug 25 23:08:13 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * valprint.c (value_print): Try to give the name of function
+       pointed to when printing a function pointer.
+
+Thu Aug 24 23:18:40 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * core.c (xfer_core_file): In cases where MEMADDR is above the
+       largest address that makes sense, set i to len.
+
+Thu Aug 24 16:04:17 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+       * valprint.c (print_string): New function to print a character
+       string, doing array-max limiting and repeat count processing.
+       (val_print, value_print): Use print_string.
+       (REPEAT_COUNT_THRESHOLD): New #define, the max number of elts to print
+       without using a repeat count.  Set to ten.
+       (value_print, val_print): Use REPEAT_COUNT_THRESHOLD.
+
+       * utils.c (printchar): Use {fputs,fprintf}_filtered.
+
+       * valprint.c (val_print): Pass the repeat count arg to the
+       fprintf_filtered call for "<repeats N times>" messages.
+
+Wed Aug 23 22:53:47 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+       * utils.c: Include <pwd.h>.
+
+       * main.c: Declare free.
+
+Wed Aug 23 05:05:59 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * utils.c, defs.h: Add tilde_expand.
+       source.c (directory_command),
+       main.c (cd_command),
+       main.c (set_history_filename),
+       dbxread.c (symbol_file_command),
+       coffread.c (symbol_file_command),
+       dbxread.c (add_file_command),
+       symmisc.c (print_symtabs),
+       *-dep.c (exec_file_command, core_file_command),
+       main.c (source_command): Use tilde_expand.
+
+       * dbxread.c (read_type): When we get a cross-reference, resolve
+       it immediately if possible, only calling add_undefined_type if
+       necessary.
+
+       * gdb.texinfo: Uncomment @includes and put comment at start
+       of file telling people to use makeinfo.
+
+       * valprint.c (type_print_base): Print the right thing for
+       bitfields.
+
+       * config.gdb (sun3os3): Set paramfile and depfile.
+
+Tue Aug 22 05:38:36 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c (symbol_file_command):  Pass string table size to
+       read_dbx_symtab().
+       (read_dbx_symtab): Before indexing into string table, check
+       string table index for reasonableness.
+       (psymtab_to_symtab{,_1}, read_ofile_symtab): Same.
+
+Tue Aug 22 04:04:39 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+       * m68k-pinsn.c: Replaced many calls to fprintf and fputs with
+       calls to fprintf_filtered and fputs_filtered.
+       (print_insn_arg): Use normal MIT 68k syntax for postincrement,
+       predecrement, and register indirect addressing modes.
+
+Mon Aug 21 10:08:02 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * main.c (initialize_signals): Set signal handler for SIGQUIT
+       and SIGHUP to do_nothing.
+
+       * ns32k-opcode.h (ord): Change 1D1D to 1D2D.
+
+       * ns32k-pinsn.c (print_insn_arg, print_insn): Handle index
+       bytes correctly.
+
+       * ns32k-opcode.h: Add comments.
+
+       * dbxread.c (read_type): Put enum fields in type.fields in order
+       that they were found in the debugging symbols (not reverse order).
+
+Sun Aug 20 21:17:13 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * main.c (source_command): Read .gdbinit if run without argument.
+
+       * source.c (directory_command): Only print "foo already in path"
+       if from_tty.
+
+       * version.c: Change version number to 3.2.xxx
+
+Sat Aug 19 00:24:08 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * m-news.h: Define HAVE_WAIT_STRUCT.
+
+       * m-isi.h, isi-dep.c: Replace with new version from Adam de Boor.
+       config.gdb: Remove isibsd43.
+
+       * main.c (catch_termination): Don't say we have written
+       .gdb_history until after we really have.
+
+       * convex-dep.c (attach): Add "sleep (1)".
+       (write_vector_register): Use "LL" with long long constant.
+       (wait): Close comment.
+       (wait): Change "unix 7.1 bug" to "unix 7.1 feature" & related
+       changes in comment.
+       (scan_stack): And fp with 0x80000000 in while loop test.
+       (core_file_command): Move code to set COREFILE.
+       (many places): Change printf to printf_filtered.
+       (psw_info): Allow argument giving value to print as a psw.
+       (_initialize_convex_dep): Update docstrings.
+
+       * m-convex.h (WORDS_BIG_ENDIAN): Correct typo ("WRODS")
+       define NO_SIGINTERRUPT.
+       define SET_STACK_LIMIT_HUGE.
+       add "undef BUILTIN_TYPE_LONGEST" before defining it.
+       Use "LL" after constants in CALL_DUMMY.
+
+       * dbxread.c: In the 3 places it says error "ridiculous string
+       table size"... delete extra parameter to error.
+
+       * dbxread.c (scan_file_globals): Check for FORTRAN common block.
+       Allow multiple references for the sake of common blocks.
+
+       * main.c (initialize_main): Set history_filename to include
+       current directory.
+
+       * valprint.c (decode_format): Don't return a defaulted size
+       field if osize is zero.
+
+       * gdb.texinfo (Compilation): Update information on -gg symbols.
+       Document problem with ar.
+
+Fri Aug 18 19:45:20 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * valprint.c (val_print, value_print): Add "<repeats %d times>" code.
+       Also put "..." outside quotes for strings.
+
+       * main.c (initialize_main): Add comment about history output file
+       being different from history input file.
+
+       * m-newsos3.h: Undefine NO_SIGINTERRUPT.  Rearrange a few comments.
+
+       * m-newsos3.h (REGISTER_U_ADDR): Use new version from Hikichi.
+
+       * sparc-opcode.h: Add comment clarifying meaning of the order of
+       the entries in sparc_opcodes.
+
+       * eval.c (evaluate_subexp, case UNOP_IND): Deal with deferencing
+       things that are not pointers.
+
+       * valops.c (value_ind): Make dereferencing an int give a LONGEST.
+
+       * expprint.c (print_subexp): Add (int) cast in OP_LAST case.
+
+       * dbxread.c (read_array_type): Set lower and upper if adjustable.
+
+       * symtab.c (lookup_symbol): Don't abort if symbol found in psymtab
+       but not in symtab.
+
+Thu Aug 17 15:51:20 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * config.gdb: Changed "Makefile.c" to "Makefile.dist".
+
+Thu Aug 17 01:58:04 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+       * sparc-opcode.h (or): Removed incorrect lose bit 0x08000000.
+       [many]: Changed many `lose' entries to have the 0x10 bit set, so
+       they don't think %l0 is %g0.
+
+Wed Aug 16 00:30:44 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * m-symmetry.h (STORE_STRUCT_RETURN): Also write reg 0.
+       (EXTRACT_RETURN_VALUE): Call symmetry_extract_return_value.
+       symmetry-dep.c (symmetry_extract_return_value): New fn.
+
+       * main.c (symbol_completion_function): Deal with changed
+       result_list from lookup_cmd_1 for ambiguous return.
+       command.c (lookup_cmd): Same.
+
+       * inflow.c [TIOCGETC]: Move #include "param.h" back before
+       system #includes.  Change all #ifdef TIOCGETC to
+       #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+       m-i386-sysv3.2.h, m-i386gas-sysv3.2.h: Remove "#undef TIOCGETC"
+       and add "#define TIOCGETC_BROKEN".
+
+       * command.c (lookup_cmd_1): Give the correct result_list in the
+       case of an ambiguous return where there is a partial match
+       (e.g. "info a").  Add comment clarifying what is the correct
+       result_list.
+
+       * gdb.texinfo (GDB History): Document the two changes below.
+
+       * main.c (command_line_input): Make history expansion not
+       just occur at the beginning of a line.
+
+       * main.c (initialize_main): Make history expansion off by default.
+
+       * inflow.c: Move #include "param.h" after system #includes.
+
+       * i386-dep.c (i386_float_info): Use U_FPSTATE macro.
+
+       * m-i386-sysv3.2.h, m-i386gas-sysv3.2.h: New files.
+       Makefile.dist, config.gdb: Know about these new files.
+
+Tue Aug 15 21:36:11 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * symtab.c (lookup_struct_elt_type): Use type_print rather
+       than assuming type has a name.
+
+Tue Aug 15 02:25:43 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+       * sparc-opcode.h (mov): Removed bogus "or i,0,d" pattern.
+
+       * sparc-opcode.h (mov, or): Fixed incorrect `lose' members.
+
+       * sparc-dep.c: Don't include "sparc-opcode.h".
+       (skip_prologue, isanulled): Declare special types to recognize
+       instructions, and use them.
+
+       * sparc-pinsn.c (print_insn): Sign-extend 13-bit immediate args.
+       If they are less than +9, print them in signed decimal instead
+       of unsigned hex.
+
+       * sparc-opcode.h, sparc-pinsn.c: Completely rewritten to share an
+       opcode table with gas, and thus produce disassembly that looks
+       like what the assembler accepts.
+
+Tue Aug 15 16:20:52 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * symtab.c (find_pc_psymbol): Move best_pc=psymtab->textlow-1
+       after test for psymtab null.
+
+       * main.c (editing_info): Remove variable retval.
+
+       * config.gdb (sun3, isi): Comment out obsolete message about telling
+       it whether you have an FPU (now that it detects it).
+
+       * config.gdb (sun3): Accept sun3os3.
+
+       * m68k-insn.h: Include <signal.h>.
+
+       * m68k-pinsn.h (convert_{to,from}_68881): Add have_fpu code
+
+       * m-newsos3.h: Undefine USE_PCB.  That code didn't seem to work.
+
+       * sparc-dep.c: Put in insn_fmt and other stuff from the old
+       sparc-opcode.h.
+
+       * sparc-opcode.h, sparc-pinsn.c: Correct copyright notice.
+
+       * sparc-opcode.h, sparc-pinsn.c: Replace the old ones with the new
+       ones by roland.
+
+Tue Aug 15 02:25:43 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+       * Makefile.dist: Don't define CC at all.
+
+       * Makefile.dist (Makefile): Remove tmp.c after preprocessing.
+       Use $(MD) instead of M_MAKEDEFINE in the cc command.
+
+       * Makefile.dist: Don't define RL_LIB as
+       "${READLINE}/libreadline.a", since READLINE is a list of files.
+
+Mon Aug 14 23:49:29 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * main.c (print_version): Change 1988 to 1989.
+
+       * main.c (copying_info, initialize_main): Remove #if 0'd code.
+
+Tue Aug  1 14:44:56 1989  Hikichi  (hikichi at sran203)
+
+       * m-newsos3.h
+           (NO_SIGINTERRUPT): have SIGINTERRUPT on NEWS os 3.
+
+       * m-news.h(FRAME_FIND_SAVED_REGS): use the sun3's instead of old
+       one.
+
+Mon Aug 14 15:27:01 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * m-news.h, m-newsos3.h, news-dep.c: Merge additional changes
+       by Hikichi (ChangeLog entries above).
+
+       * Makefile.dist (READLINE): List readline files individually
+       so we don't accidently get random files from the readline
+       directory.
+
+       * m-news.h (STORE_RETURN_VALUE, EXTRACT_RETURN_VALUE):
+       Expect floating point returns to be in fp0.
+
+       * gdb.texinfo (Format options): New node.
+
+       * gdb.texinfo: Comment out "@include"s until bfox fixes the
+       readline & history docs.
+
+       * dbxread.c (read_addl_syms): Set startup_file_* if necessary at
+       the end (as well as when we hit ".o").
+
+       * printcmd.c (decode_format): Set val.format & val.size to '?' at
+       start and set defaults at end.
+
+       * symtab.c (decode_line_1): Check for class_name null.
+
+       * valops.c: Each place where it compares against field names,
+       check for null field names.  (new t_field_name variables).
+
+       * utils.c (fputs_filtered): Check for linebuffer null before
+       checking whether to call fputs.  Remove later check for linebuffer
+       null.  
+
+Sun Aug 13 15:56:50 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * m-isi.h, m-sun3.h ({PUSH,POP}_FP_REGS):  New macros.
+       m-sun3.h (NUM_REGS): Conditionalize on FPU.
+       config.gdb (sun3, isi): Add message about support for machines
+       without FPU.
+
+       * main.c (catch_termination, initialize_signals): new functions.
+
+       * main.c (editing_info): Add "info editing n" and "info editing +".
+       Rewrite much of this function.
+       gdb.texinfo (GDB Readline): Document it.
+
+       * values.c (history_info): Add "info history +".  Also add code to
+       do "info history +" when command is repeated.
+       gdb.texinfo (Value History): Document "info history +".
+
+       * expprint.c (print_subexp): Add OP_THIS to case stmt.
+
+       * config.gdb (sun4os4): Put quotes around make define.
+
+       * config.gdb: Canonicalize machine name at beginning.
+
+Sat Aug 12 00:50:59 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * config.gdb: define M_MAKEDEFINE
+       Makefile (Makefile, MD): Be able to re-make Makefile.
+
+       * main.c (command_line_input): Add comments to
+       the command history.
+
+       * Makefile.dist (Makefile): Add /bin/false.
+
+Fri Aug 11 14:35:33 1989  Jim Kingdon  (kingdon at spiff)
+
+       * Makefile.dist: Comment out .c.o rule and add TARGET_ARCH.
+
+       * m-altos.h: Include sys/page.h & sys/net.h
+
+       * m-altos.h (FRAME_CHAIN{,_VALID}):  Use outside_startup_file.
+
+       * config.gdb (altos, altosgas): Add M_SYSV & M_BSD_NM and remove
+       M_ALLOCA=alloca.o from makedefine.
+
+       * coffread.c (complete_symtab): Change a_entry to entry.
+
+       * m-altosgas.h: New file.
+
+       * m-symmetry (REGISTER_BYTE): Fix dumb mistake.
+
+Fri Aug 11 06:39:49 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+       * utils.c (set_screensize_command): Check for ARG being nil, since
+       that's what execute_command will pass if there's no argument.
+
+       * expread.y (yylex): Recognize "0x" or "0X" as the beginning of a
+       number.
+
+Thu Aug 10 15:43:12 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * config.gdb, Makefile.dist: Rename Makefile.c to Makefile.dist.
+
+       * m-altos.h: Add comment about porting to USGR2.
+
+       * config.gdb (sparc): Add -Usparc.
+
+Wed Aug  9 14:20:39 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * m-sun3os4.h: Define BROKEN_LARGE_ALLOCA.
+
+       * values.c (modify_field): Check for value too large to fit in
+       bitfield. 
+
+       * utils.c (fputs_filtered): Allow LINEBUFFER to be NULL.
+
+       * breakpoint.c (condition_command): Check for attempt to specify
+       non-numeric breakpoint number.
+
+       * config.gdb, Makefile, m-altos.h, altos-dep.c: Merge Altos
+       port.
+
+       * README: Change message about editing Makefile.
+
+       * config.gdb: Edit Makefile.
+       Copied Makefile to Makefile.c and changed to let config.gdb
+       run us through the C preprocessor.
+
+       * expread.y (yylex): Test correctly for definition of number.
+
+Wed Aug  9 11:56:05 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): Put bracketing of entry point in
+       test case for .o symbols so that it will be correct even without
+       debugging symbols.
+       (end_psymtab): Took bracketing out.
+
+       * blockframe.c (outside_startup_file): Reverse the sense of the
+       return value to make the functionality implied by the name
+       correct. 
+
+Tue Aug  8 11:48:38 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * coffread.c (symbol_file_command): Do  not assume presence of a.out
+       header. 
+
+       * blockframe.c: Replace first_object_file_end with
+       startup_file_{start,end}
+       (outside_startup_file): New function.
+       dbxread.c (read_addl_syms, read_dbx_symtab, end_psymbol): set
+       startup_file_*.  Delete first_object_file_end code.
+       Add entry_point and ENTRY_POINT
+       coffread.c (complete_symtab): Set startup_file_*.
+       (first_object_file_end): Add as static.
+       m-*.h (FRAME_CHAIN, FRAME_CHAIN_VALID): Call outside_startup_file
+       instead of comparing with first_object_file_end.
+
+       * breakpoint.c (breakpoint_1): Change -1 to (CORE_ADDR)-1.
+
+       * config.gdb (i386, i386gas): Add missing quotes at end of "echo"
+
+       * source.c (directory_command): Add dont_repeat ();
+
+Mon Aug  7 18:03:51 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * dbxread.c (read_addl_syms): Change strcmp to strncmp and put 3rd
+       arg back.
+
+       * command.h (struct cmd_list_element): Add comment clarifying
+       purpose of abbrev_flag.
+
+Mon Aug  7 12:51:03 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * printcmd.c (_initialize_printcmd): Changed "undisplay" not to
+       have abbrev flag set; it isn't an abbreviation of "delete
+       display", it's an alias.
+
+Mon Aug  7 00:25:15 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * symtab.c (lookup_symtab_1): Remove filematch (never used).
+
+       * expread.y [type]: Add second argument to 2 calls to
+       lookup_member_type which were missing them.
+
+       * dbxread.c (symbol_file_command): Add from_tty arg.
+       Check it before calling query.
+
+       * infcmd.c (tty_command): Add from_tty arg.
+
+       * eval.c (evaluate_subexp): Remove 3rd argument from
+       calls to value_x_unop.
+
+       * dbxread.c (read_addl_syms): Remove 3rd argument from
+       call to strcmp.
+
+       * gdb.texinfo (Command editing): @include inc-readline.texinfo
+       and inc-history.texinfo and reorganize GDB-specific stuff.
+
+       * Makefile: Add line MAKE=make.
+
+       * README (second paragraph): Fix trivial errors.
+
+       * dbxread.c (read_struct_type): Make sure p is initialized.
+
+       * main.c (symbol_completion_function): Complete correctly
+       on the empty string.
+
+Sun Aug  6 21:01:59 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * symmetry-dep.c: Remove "long" from definition of i386_follow_jump.
+
+       * gdb.texinfo (Backtrace): Document "where" and "info stack".
+
+       * dbxread.c (cleanup_undefined_types): Strip off "struct "
+       or "union " from type names before doing comparison
+
+Sat Aug  5 02:05:36 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * config.gdb (i386, i386gas): Improve makefile editing instructions.
+
+       * Makefile: Fix typo in CLIBS for SYSV.
+
+       * dbxread.c (read_dbx_symtab): Deal with N_GSYM typedefs.
+
+       * dbxread.c (add_file_command): Do not free name.  We didn't
+       allocate it; it just points into arg_string.
+
+       * Makefile, m-*.h: Change LACK_VPRINTF to HAVE_VPRINTF.
+
+Fri Jul 28 00:07:48 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * valprint.c (val_print): Made sure that all returns returned a
+       value (usually 0, indicating no memory printed).
+
+       * core.c (read_memory): Changed "return" to "return 0".
+
+       * expread.y (parse_number): Handle scientific notation when the
+       string does not contain a '.'.
+
+Thu Jul 27 15:14:03 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * infrun.c (signals_info): Error if signal number passed is out of
+       bounds. 
+
+       * defs.h: Define alloca to be __builtin_alloca if compiling with
+       gcc and localized inclusion of alloca.h on the sparc with the
+       other alloca stuff.
+       * command.c: Doesn't need to include alloca.h on the sparc; defs.h
+       does it for you.
+
+       * printcmd.c (print_frame_args): Changed test for call to
+       print_frame_nameless_args to check i to tell if any args had been
+       printed.
+
+Thu Jul 27 04:40:56 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+       * blockframe.c (find_pc_partial_function): Always check that NAME
+       and/or ADDRESS are not nil before storing into them.
+
+Wed Jul 26 23:41:21 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+       * m-newsos3.h: Define BROKEN_LARGE_ALLOCA.
+       * dbxread.c (symbol_file_command, psymtab_to_symtab):
+       Use xmalloc #ifdef BROKEN_LARGE_ALLOCA.
+
+Tue Jul 25 16:28:18 1989  Jay Fenlason  (hack at apple-gunkies.ai.mit.edu)
+
+       * m68k-opcode.h: moved some of the fmovem entries so they're
+       all consecutive.  This way the assembler doesn't bomb.
+
+Mon Jul 24 22:45:54 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * symtab.c (lookup_symbol): Changed error to an informational (if
+       not very comforting) message about internal problems.  This will
+       get a null symbol returned to decode_line_1, which should force
+       things to be looked up in the misc function vector.
+
+Wed Jul 19 13:47:34 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symtab.c (lookup_symbol): Changed "fatal" to "error" in
+       external symbol not found in symtab in which it was supposed to be
+       found.  This can be reached because of a bug in ar.
+
+Tue Jul 18 22:57:43 1989  Randy Smith  (roland at hobbes.ai.mit.edu)
+
+       * m-news.h [REGISTER_U_ADDR]: Decreased the assumed offset of fp0
+       by 4 to bring it into (apparently) appropriate alignment with
+       reality. 
+
+Tue Jul 18 18:14:42 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * Makefile: pinsn.o should depend on opcode.h
+
+       * m68k-opcode.h: Moved fmovemx with register lists to before other
+       fmovemx. 
+
+Tue Jul 18 11:21:42 1989  Jim Kingdon  (kingdon at susie)
+
+       * Makefile, m*.h: Only #define vprintf (to _doprnt or printf,
+       depends on the system) if the library lacks it (controlled by
+       LACK_VPRINTF_DEFINE in makefile).  Unpleasant, but necessary to
+       make this work with the GNU C library.
+
+Mon Jul 17 15:17:48 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * breakpoint.c (breakpoint_1): Change addr-b->address to
+       b->address-addr.
+
+Sun Jul 16 16:23:39 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * eval.c (evaluate_subexp): Change error message printed when
+       right operand of '@' is not an integer to English.
+
+       * infcmd.c (registers_info): Fix call to print_spaces_filtered
+       to specify right # of arguments.
+
+       * gdb.texinfo (Command Editing): Document info editing command.
+
+       * coffread.c (read_file_hdr): Add MC68MAGIC.
+
+       * source.c (select_source_symtab): Change MAX to max.
+
+Fri Jul 14 21:19:11 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * infcmd.c (registers_info): Clean up display to look good with long
+       register names, to say "register" instead of "reg", and to put the
+       "relative to selected stack frame" bit at the top.
+
+Fri Jul 14 18:23:09 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (record_misc_function): Put parens around | to force
+       correct evaluation.
+
+Wed Jul 12 12:25:53 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * m-newsos3, m-news, infrun.c, Makefile, config.gdb, news-dep.c:
+       Merge in Hikichi's changes for Sony/News-OS 3 support.
+
+Tue Jul 11 21:41:32 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * utils.c (fputs_filtered): Don't do any filtering if output is
+       not to stdout, or if stdout is not a tty.
+       (fprintf_filtered): Rely on fputs_filtered's check for whether to
+       do filtering.
+
+Tue Jul 11 00:33:58 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * GDB 3.2 Released.
+
+       * valprint.h: Deleted.
+
+       * utils.c (fputs_filtered): Don't do any filtering if filtering is
+       disabled (lines_per_page == 0).
+
+Mon Jul 10 22:27:53 1989  Randy Smith  (roland at hobbes.ai.mit.edu)
+
+       * expread.y [typebase]: Added "unsigned long int" and "unsigned
+       short int" to specs.
+
+Mon Jul 10 21:44:55 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * main.c (main): Make -cd use cd_command to avoid
+       current_directory with non-absolute pathname.
+
+Mon Jul 10 00:34:29 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (symbol_file_command): Catch errors from stat (even
+       though they should never happen).
+
+       * source.c (openp): If the path is null, use the current
+       directory. 
+
+       * dbxread.c (read_dbx_symtab): Put N_SETV symbols into the misc
+       function vector ...
+       (record_misc_function): ... as data symbols.
+
+       * utils.c (fprintf_filtered): Return after printing if we aren't
+       going to do filtering.
+
+       * Makefile: Added several things for make clean to take care of.
+
+       * expread.y: Lowered "@" in precedence below +,-,*,/,%.
+
+       * eval.c (evaluate_subexp): Return an error if the rhs of "@"
+       isn't integral.
+
+       * Makefile: Added removal of core and gdb[0-9] files to clean
+       target. 
+
+       * Makefile: Made a new target "distclean", which cleans things up
+       correctly for making a distribution.
+
+Sun Jul  9 23:21:27 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * dbxread.c: Surrounded define of gnu symbols with an #ifndef
+       NO_GNU_STABS in case you don't want them on some machines.
+       * m-npl.h, m-pn.h: Defined NO_GNU_STABS.
+
+Sun Jul  9 19:25:22 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * utils.c (fputs_filtered): New function.
+       (fprintf_filtered): Use fputs_filtered.
+       utils.c (print_spaces_filtered),
+       command.c (help_cmd,help_cmd_list),
+       printcmd.c (print_frame_args),
+       stack.c (print_block_frame_locals, print_frame_arg_vars),
+       valprint.c (many functions): Use fputs_filtered instead of
+       fprintf_filtered to avoid arbitrary limit.
+
+       * utils.c (fprintf_filtered): Fix incorrect comment.
+
+Sat Jul  8 18:12:01 1989  Randy Smith  (randy at hobbes.ai.mit.edu)
+
+       * valprint.c (val_print): Changed assignment of pretty to use
+       prettyprint as a conditional rather than rely on values of the
+       enum. 
+
+       * Projects: Cleaned up a little for release.
+
+       * main.c (initialize_main): Initialize
+       rl_completion_entry_function instead of completion_entry_function. 
+
+       * Makefile: Modified to use the new readline library setup.
+
+       * breakpoint.c (break_command_1, delete_breakpoint,
+       enable_breakpoint, disable_breakpoint): Put in new printouts for
+       xgdb usage triggered off of xgdb_verbose.
+       * main.c (main): Added check for flag to set xgdb_verbose.
+       * stack.c (frame_command): Set frame_changed when frame command
+       used. 
+
+Fri Jul  7 16:20:58 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * Remove valprint.h and move contents to value.h (more logical).
+
+Fri Jul  7 02:28:06 1989  Randall Smith  (randy at rice-chex)
+
+       * m68k-pinsn.c (print_insn): Included a check for register list;
+       if there is one, make sure to start p after it.
+
+       * breakpoint.c (break_command_1, delete_breakpoint,
+       enable_breakpoint, disable_breakpoint): #ifdef'd out changes
+       below; they produce unwanted output in gdb mode in gnu-emacs.
+
+       * gdb.texinfo: Spelled.  Also removed index references from
+       command editing section; the relevance/volume ratio was too low.
+       Removed all references to the function index.
+
+       * ns32k-opcode.h, ns32k-pinsn.c: Backed out changes of June 24th;
+       haven't yet received legal papers.
+
+       * .gdbinit: Included message telling the user what it is doing.
+
+       * symmetry-dep.c: Added static decls for i386_get_frame_setup,
+       i386_follow_jump.
+       * values.c (unpack_double): Added a return (double)0 at the end to
+       silence a compiler warning.
+
+       * printcmd.c (containing_function_bounds, asdump_command): Created
+       to dump the assembly code of a function (support for xgdb and a
+       useful hack).
+       (_initialize_printcmd): Added this to command list.
+       * gdb.texinfo [Memory]: Added documentation for the asdump
+       command.
+       * breakpoint.c (break_command_1, delete_breakpoint,
+       enable_breakpoint, disable_breakpoint): Added extra verbosity for
+       xgdb conditionalized on the new external frame_full_file_name.
+       * source.c (identify_source_line): Increase verbosity of fullname
+       prointout to include pc value.
+       * stack.c: Added a new variable; "frame_changed" to indicate when
+       a frame has been changed so that gdb can print out a frame change
+       message when the frame only changes implicitly.
+       (print_frame_info): Check the new variable in determining when to
+       print out a new message and set it to zero when done.
+       (up_command): Increment it.
+       (down_command): Decrement it.
+
+       * m68k-pinsn.c (print_insn_arg [lL]): Modified cases for register
+       lists to reset the point to point to after the word from which the
+       list is grabbed *if* that would cause point to point farther than
+       it currently is.
+
+Thu Jul  6 14:28:11 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * valprint.c (val_print, value_print): Add parameter to control
+       prettyprinting.
+       valprint.h: New file containing constants used for passing
+       prettyprinting parameter to val{,ue}_print.
+       expprint.c, infcmd.c, printcmd.c, valprint.c, values.c:
+       Change all calls to val{,ue}_print to use new parameter.
+       
+Mon Jul  3 22:38:11 1989  Randy Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (,process_one_symbol): Moved extern declaration for
+       index out of function to beginning of file.
+
+Mon Jul  3 18:40:14 1989  Jim Kingdon  (kingdon at hobbes.ai.mit.edu)
+
+       * gdb.texinfo (Registers): Add "ps" to list of standard registers.
+
+Sun Jul  2 23:13:03 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * printcmd.c (enable_display): Change d->next to d = d->next so
+       that "enable display" without args works.
+
+Fri Jun 30 23:42:04 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * source.c (list_command):  Made error message given when no
+       symtab is loaded clearer.
+
+       * valops.c (value_assign): Make it so that when assigning to an
+       internal variable, the type of the assignment exp is the type of
+       the value being assigned.
+
+Fri Jun 30 12:12:43 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c (verbose_info): Created.
+       (initialize_main): Put "info verbose" into command list.
+
+       * utils.c (screensize_info): Created.
+       (_initialize_utils): Defined "info screensize" as a normal command.
+
+       * valprint.c (format_info): Added information about maximum number
+       of array elements to function.
+
+       * blockframe.c (find_pc_partial_function): Again.
+
+       * blockframe.c (find_pc_partial_function): Replaced a "shouldn't
+       happen" (which does) with a zero return.
+
+       * main.c (dont_repeat): Moved ahead of first use.
+
+Thu Jun 29 19:15:08 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * vax-opcode.h: Made minor modifications (moved an instruction and
+       removed a typo) to bring this into accord with gas' table; also
+       changed copyright to reflect it being part of both gdb and gas.
+
+       * m68k-opcode.h: Added whole scads and bunches of new stuff for
+       the m68851 and changed the coptyrightto recognize that the file
+       was shared between gdb and gas.
+
+       * main.c (stop_sig): Use "dont_repeat ()" instead of *line = 0;
+
+       * core.c (read_memory): Don't do anything if length is 0.
+
+       * Makefile: Added readline.c to the list of files screwed by
+       having the ansi ioctl.h compilation with gcc.
+
+       * config.gdb: Added sun4os3 & sun4-os3 as availible options.
+
+Wed Jun 28 02:01:26 1989  Jim Kingdon  (kingdon at apple-gunkies.ai.mit.edu)
+
+       * command.c (lookup_cmd): Add ignore_help_classes argument.
+       (lookup_cmd_1): Add ignore_help_classes argument.
+       command.c, main.c: Change callers of lookup_cmd{,_1} to supply
+        value for ignore_help_classes.
+
+Tue Jun 27 18:01:31 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * utils.c (print_spaces_filtered): Made more efficient.
+       * defs.h: Declaration.
+       * valprint.c (val_print): Used in a couple of new places.
+
+Mon Jun 26 18:27:28 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * m68k-pinsn.c (print_insn_arg ['#', '^']): Combined them into one
+       case which always gets the argument from the word immediately
+       following the instruction.
+       (print_insn_arg ["[lL]w"]): Make sure to always get the register
+       mask from the word immediately following the instruction.
+
+Sun Jun 25 19:14:56 1989  Randall Smith  (randy at galapas.ai.mit.edu)
+
+       * Makefile: Added hp-include back in as something to distribute.
+
+       * stack.c (print_block_frame_locals): Return value changed from
+       void to int; return 1 if values printed.  Use _filtered.
+       (print_frame_local_vars): Use return value from
+       print_block_frame_locals to mention if nothing printed; mention
+       lack of symbol table, use _filtered.
+       (print_frame_arg_vars): Tell the user if no symbol table
+       or no values printed.  Use fprintf_filtered instead of fprintf.
+       * blockframe.c (get_prev_frame_info): Check for no inferior or
+       core file before crashing.
+
+       * inflow.c (inferior_died): Set current frame to zero to keep from
+       looking like we're in start.
+
+Sat Jun 24 15:50:53 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * stack.c (frame_command): Added a check to make sure that there
+       was an inferior or a core file.
+
+       * expread.y (yylex): Allow floating point numbers of the form ".5"
+       to be parsed.
+
+        Changes by David Taylor at TMC:
+       * ns32k-pinsn.c: Added define for ?floating point coprocessor? and
+       tables for register names to be used for each of the possibilities.
+       (list_search): Created; searches a list of options for a specific
+       value.
+       (print_insn_arg): Added 'Q', 'b', 'M', 'P', 'g', and 'G' options
+       to the value location switch.
+       * ns32k-opcode.h: Added several new location flags.
+       [addr, enter, exit, ext[bwd], exts[bwd], lmr, lpr[bwd], restore,
+       rett, spr[bwd], smr]: Improved insn format output.
+
+       * symtab.c (list_symbols): Rearrange printing to produce readable
+       output for "info types".
+
+       * eval.c (evaluate_subexp_for_address): Fixed typo.
+
+       * dbxread.c (read_type): Don't output an error message when
+       there isn't a ',' after a cross-reference.
+
+       * dbxread.c (read_dbx_symtab): #if'd out N_FN case in
+       read_dbx_symtab if it has the EXT bit set (otherwise multiple
+       cases with the same value).
+
+Fri Jun 23 13:12:08 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * symmisc.c: Changed decl of print_spaces from static to extern
+       (since it's defined in utils.c).
+
+       * remote.c (remote_open): Close remote_desc if it's already been
+       opened. 
+
+       * Remote_Makefile, remote_gutils.c, remote_inflow.c,
+       remote_server.c, remote_utils.c: Combined into remote-multi.shar.
+       * remote-multi.shar: Created (Vikram Koka's remote stub).
+       * remote-sa.m68k.shar: Created (Glenn Engel's remcom.c).
+       * README: Updated to reflect new organization of remote stubs.
+
+       * dbxread.c (read_dbx_symtab): Put an N_FN in with N_FN | N_EXT to
+       account for those machines which don't use the external bit here.
+       Sigh. 
+
+       * m-symmetry.h: Defined NO_SIGINTERRUPT.
+
+Thu Jun 22 12:51:37 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * printcmd.c (decode_format): Make sure characters are printed
+       using a byte size.
+
+       * utils.c (error): Added a terminal_ours here.
+
+       * stack.c (locals_info): Added check for selected frame.
+
+       * dbxread.c (read_type): Checked to make sure that a "," was
+       actually found in the symbol to end a cross reference.
+
+Wed Jun 21 10:30:01 1989  Randy Smith  (randy at tartarus.uchicago.edu)
+
+       * expread.y (parse_number, [exp]): Allowed for the return of a
+       number marked as unsigned; this will allow inclusion of unsigned
+       constants. 
+
+       * symtab.h: Put in default definitions for BUILTIN_TYPE_LONGEST
+       and BUILTIN_TYPE_UNSIGNED_LONGEST.
+
+       * expread.y (parse_number): Will now accept integers suffixed with
+       a 'u' (though does nothing special with it).
+
+       * valarith.c (value_binop): Added cases to deal with unsigned
+       arithmetic correctly.
+
+Tue Jun 20 14:25:54 1989  Randy Smith  (randy at tartarus.uchicago.edu)
+
+       * dbxread.c (psymtab_to_symtab_1): Changed reading in info message
+       to go through printf_filtered.
+
+       * symtab.c (list_symbols): Placed header message after all calls
+       to psymtab_to_symtab. 
+
+       * symtab.c (smash_to_{function, reference, pointer}_type): Carried
+       attribute of permanence for the type being smashed over the bzero
+       and allowed any type to point at this one if it is permanent.
+
+       * symtab.c (smash_to_{function, reference, pointer}_type): Fix
+       typo: check flags of to_type instead of type.
+
+       * m-hp9k320.h: Changed check on __GNU__ predefine to __GNUC__.
+
+       * Makefile: Made MUNCH_DEFINE seperate and based on SYSV_DEFINE;
+       they aren't the same on hp's.
+
+Mon Jun 19 17:10:16 1989  Randy Smith  (randy at tartarus.uchicago.edu)
+
+       * Makefile: Fixed typo.
+
+       * valops.c (call_function): Error if the inferior has not been
+       started. 
+
+       * ns32k-opcode.h [check[wc], cmpm[bwd], movm[bwd], skpsb]: Fixed
+       typos. 
+
+Fri Jun  9 16:23:04 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-news.h [NO_SIGINTERRUPT]: Defined.
+
+       * dbxread.c (read_type): Start copy of undefined structure name
+       past [sue] defining type of cross ref.
+
+       * dbxread.c (process_one_symbol): Changed strchr to index.
+
+       * ns32k-opcode.h, ns32k-pinsn.c: More changes to number of
+       operands, addition of all of the set condition opcodes, addition
+       of several flag letters, all patterned after the gas code.
+
+       * ns32k-opcode.h [mov{su,us}[bwd], or[bwd]]: Changed number of
+       operands from 1 to 2.
+
+Wed Jun  7 15:04:24 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symseg.h [TYPE_FLAG_STUB]: Created.
+       * dbxread.c (read_type): Set flag bit if type is stub.
+       (cleanup_undefined_types): Don't mark it as a stub if it's been
+       defined since we first learned about it.
+       * valprint.c (val_print): Print out a message to that effect if
+       this type is encountered.
+
+       * symseg.h, symtab.h: Moved the definition of TYPE_FLAG_PERM over
+       to symseg.h so that all such definitions would be in the same place.
+
+       * valprint.c (val_print): Print out <No data fields> for a
+       structure if there aren't any.
+
+       * dbxread.c (read_type): Set type name of a cross reference type
+       to "struct whatever" or something.
+
+Tue Jun  6 19:40:52 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * breakpoint.c (breakpoint_1): Print out symbolic location of
+       breakpoints for which there are no debugging symbols.
+
+Mon Jun  5 15:14:51 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * command.c (help_cmd_list): Made line_size static.
+
+Sat Jun  3 17:33:45 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * Makefile: Don't include the binutils hp-include directory in the
+       distribution anymore; refer the users to the binutils distribution.
+
+Thu Jun  1 16:33:07 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * printcmd.c (disable_display_command): Fixed loop iteration for
+       no arg case.
+
+       * printcmd.c (disable_display_command): Added from_tty parameter
+       to function.
+
+       * valops.c (value_of_variable): Call read_var_value with 0 cast to
+       FRAME instead of CORE_ADDR.
+
+       * eval.c (evaluate_subexp): Corrected number of args passed to
+       value_subscript (to 2).
+
+       * infrun.c (wait_for_inferior), symtab.c (decode_line_1),
+       m-convex.h: Changed name of FIRSTLINE_DEBUG_BROKEN to
+       PROLOGUE_FIRSTLINE_OVERLAP. 
+
+       * m-merlin.h: Fixed typo.
+       * ns32k-opcode.h: Added ns32381 opcodes and "cinv" insn, and fixed
+       errors in movm[wd], rett, and sfsr.
+
+       * eval.c (evaluate_subexp, evaluate_subexp_for_address), valops.c
+       (value_zero): Change value_zero over to taking two arguments
+       instead of three.
+
+       * eval.c (evaluate_subexp)
+         [OP_VAR_VALUE]: Get correct lval type for AVOID_SIDE_EFFECTS for
+         all types of symbols.
+         [BINOP_DIV]: Don't divide if avoiding side effects; just return
+         an object of the correct type.
+         [BINOP_REPEAT]: Don't call value_repeat, just allocate a
+         repeated value.
+       (evaluete_subexp_for_address) [OP_VAR_VALUE]: Just return a thing
+       of the right type (after checking to make sure that we are allowed
+       to take the address of whatever variable has been passed).
+
+Mon May 29 11:01:02 1989  Randall Smith  (randy at galapas.ai.mit.edu)
+
+       * breakpoint.c (until_break_command): Set the breakpoint with a
+       frame specification so that it won't trip in inferior calls to the
+       function.  Also set things up so that it works based on selected
+       frame, not current one.
+
+Sun May 28 15:05:33 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * eval.c (evalue_subexp): Change subscript case to use value_zero
+       in EVAL_AVOID_SIDE_EFFECTS case.
+
+Fri May 26 12:03:56 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (read_addl_syms, psymtab_to_symtab): Removed
+       cleanup_undefined_types; this needs to be done on a symtab basis.
+       (end_symtab): Called cleanup_undefined_types from here.
+       (cleanup_undefined_types): No longer uses lookup_symbol (brain
+       dead idea; oh, well), now it searches through file_symbols.
+
+Wed May 24 15:52:43 1989  Randall Smith  (randy at galapas)
+
+       * source.c (select_source_symtab): Only run through
+       partial_symtab_list if it exists.
+
+       * coffread.c (read_coff_symtab): Don't unrecord a misc function
+       when a function symbol is seen for it.
+
+       * expread.y [variable]: Make sure to write a type for memvals if
+       you don't get a mft you recognize.
+
+Tue May 23 12:15:57 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * dbxread.c (read_ofile_symtab, psymtab_to_symtab): Moved cleanup
+       of undefined types to psymtab_to_symtab.  That way it will be
+       called once for all readins (which will, among other things,
+       help reduce infinite loops).
+
+       * symtab.h [misc_function_type]: Forced mf_unknown to 0.
+       * dbxread.c (record_misc_function): Cast enum to unsigned char (to
+       fit).
+       * expread.y [variable]: Cast unsigned char back to enum to test.
+
+Mon May 22 13:08:25 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+        Patches by John Gilmore for dealing well with floating point:
+       * findvar.c (value_from_register, locate_var_value): Used
+       BYTES_BIG_ENDIAN instead of an inline test.
+       * m-sparc.h [IEEE_FLOAT]: Created to indicate that the sparc is
+       IEEE compatible.
+       * printcmd.c (print_scalar_formatted): Use BYTES_BIG_ENDIAN and
+       the stream argument for printing; also modify default type for
+       'f'.  Change handling of invalid floats; changed call syntax for
+       is_nan.
+       (print_command): Don't print out anything indicating that
+       something was recorded on the history list if it wasn't.
+       * valprint.c (val_print): Fixed to deal properley with new format
+       of is_nan and unpacking doubles without errors occuring.
+       (is_nan): Changed argument list and how it figures big endianness
+       (uses macros).
+       * values.c (record_latest_value): Return -1 and don't record if
+       it's an invalid float.
+       (value_as_double): Changed to use new unpack_double calling
+       convention.
+       (unpack_double): Changed not to call error if the float was
+       invalid; simply to set invp and return.  Changed calling syntax.
+       (unpack_field_as_long, modify_field): Changed to use
+       BITS_BIG_ENDIAN to determine correct action.
+
+       * m-hp9k320.h [HP_OS_BUG]: Created; deals with problem where a
+       trap happens after a continue.
+       * infrun.c (wait_for_inferior): Used.
+
+       * m-convex.h [FIRSTLINE_DEBUG_BROKEN]: Defined a flag to indicate
+       that the debugging symbols output by the compiler for the first
+       line of a function were broken.
+       * infrun.c (wait_for_inferior), symtab.c (decode_line_1): Used.
+       
+       * gdb.texinfo [Data, Memory]: Minor cleanups of phrasing.
+
+Fri May 19 00:16:59 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (add_undefined_type, cleanup_undefined_types): Created
+       to keep a list of cross references to as yet undefined types.
+       (read_type): Call add_undefined_type when we run into such a case.
+       (read_addl_syms, read_ofile_symtab): Call cleanup_undefined_types
+       when we're done.
+
+       * dbxread.c (psymtab_to_symtab, psymtab_to_symtab_1): Broke
+       psymtab_to_symtab out into two routines; made sure the string
+       table was only readin once and the globals were only scanned once,
+       for any number of dependencies.
+
+Thu May 18 19:59:18 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-*.h: Defined (or not, as appropriate per machine)
+       BITS_BIG_ENDIAN, BYTES_BIG_ENDIAN, and WORDS_BIG_ENDIAN.
+
+Wed May 17 13:37:45 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c (symbol_completion_function): Always complete on result
+       command list, even if exact match found.  If it's really an exact
+       match, it'll find it again; if there's something longer than it,
+       it'll get the right result.
+
+       * symtab.c (make_symbol_completion_function): Fixed typo; strcmp
+       ==> strncmp.
+
+       * dbxread.c (read_dbx_symtab): Change 'G' case to mark symbols as
+       LOC_EXTERNAL. 
+
+       * expread.y [variables]: Changed default type of text symbols to
+       function returning int so that one can use, eg. strcmp.
+
+       * infrun.c (wait_for_inferior): Include a special flag indicating
+       that one shouldn't insert the breakpoints on the next step for
+       returning from a sigtramp and forcing at least one move forward. 
+
+       * infrun.c (wait_for_inferior): Change test for nexting into a
+       function to check for current stack pointer inner than previous
+       stack pointer.
+
+       * infrun.c (wait_for_inferior): Check for step resume break
+       address before dealing with normal breakpoints.
+
+       * infrun.c (wait_for_inferior): Added a case to deal with taking
+       and passing along a signal when single stepping past breakpoints
+       before inserting breakpoints.
+
+       * infrun.c (wait_for_inferior): Inserted special case to keep
+       going after taking a signal we are supposed to be taking.  
+
+Tue May 16 12:49:55 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * inflow.c (terminal_ours_1): Cast result of signal to (int
+       (*)()). 
+
+       * gdb.texinfo: Made sure that references to the program were in
+       upper case.  Modify description of the "set prompt" command.
+       [Running]: Cleaned up introduction.
+       [Attach]: Cleaned up.
+       [Stepping]: Change "Proceed" to "Continue running" or "Execute".
+       Minor cleanup.
+       [Source Path]: Cleaned up intro.  Cleared up distinction between
+       the executable search path and the source path.  Restated effect
+       of the "directory" command with no arguments.
+       [Data]: Fixed typos and trivial details.
+       [Stepping]: Fixed up explanation of "until".
+
+       * source.c (print_source_lines): Print through filter.
+
+       * printcmd.c (x_command): If the format with which to print is
+       "i", use the address of anything that isn't a pointer instead of
+       the value.  This is for, eg. "x/10i main".
+
+       * gdb.texinfo: Updated last modification date on manual.
+
+Mon May 15 12:11:33 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symtab.c (lookup_symtab): Fixed typo (name ==> copy) in call to
+       lookup_symtab_1. 
+
+       * gdb.texinfo: Added documentation for "break [+-]n" and for new
+       actions of "directory" command (taking multiple directory names at
+       the same time).
+
+       * m68k-opcode.h: Replaced the version in gdb with an up-to-date
+       version from the assembler directory.
+       * m68k-pinsn.c (print_insn_arg): Added cases 'l' & 'L' to switch
+       to print register lists for movem instructions.
+
+       * dbxread.c, m-convex.h: Moved convex dependent include files over
+       from dbxread.c to m-convex.h.
+
+       * printcmd.c (disable_display, disable_display_command): Changed
+       name of first to second, and created first which takes an int as
+       arg rather than a char pointer.  Changed second to use first.
+       (_initialize_printcmd): Changed to use second as command to call.
+       (delete_current_display, disable_current_display): Changed name of
+       first to second, and changed functionality to match.
+       * infrun.c (normal_stop), main.c (return_to_top_level): Changed to 
+       call disable_current_display.
+
+       * dbxread.c (process_one_symbol, read_dbx_symtab): Changed N_FN to
+       be N_FN | N_EXT to deal with new Berkeley define; this works with
+       either the old or the new.
+
+       * Remote_Makefile, remote_gutils.c, remote_inflow.c,
+       remote_server.c, remote_utils.c: Created.
+       * Makefile: Included in tag and tar files.
+       * README: Included a note about them.
+
+       * printcmd.c (print_address): Use find_pc_partial_function to
+       remove need to readin symtabs for symbolic addresses.  
+
+       * source.c (directory_command): Replaced function with new one
+       that can accept lists of directories seperated by spaces or :'s.
+
+       * inflow.c (new_tty): Replaced calls to dup2 with calls to dup.
+
+Sun May 14 12:33:16 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * stack.c (args_info): Make sure that you have an inferior or core
+       file before taking action.
+
+       * ns32k-opcode.h [deiw, deid]: Fixed machine code values for these
+       opcodes.
+
+       * dbxread.c (scan_file_globals): Modified to use misc function
+       vector instead of file itself.  Killed all arguments to the
+       funciton; no longer needed.
+       (psymtab_to_symtab): Changed call for above to reflect new (void)
+       argument list.
+
+       * dbxread.c (read_dbx_symtab, ): Moved HASH_OFFSET define out of
+       read_dbx_symtab. 
+
+       * expread.y [variable]: Changed default type of misc function in
+       text space to be (void ()).
+
+       * Makefile: Modified for proper number of s/r conflicts (order is
+       confusing; the mod that necessitated this change was on May 12th,
+       not today). 
+
+       * expread.y (yylex): Added SIGNED, LONG, SHORT, and INT keywords.
+       [typename]: Created.
+       [typebase]: Added rules for LONG, LONG INT, SHORT, SHORT INT,
+       SIGNED name, and UNSIGNED name (a good approximation of ansi
+       standard).      
+
+       * Makefile: Included .c.o rule to avoid sun's make from throwing
+       any curves at us.
+
+       * blockframe.c: Included <obstack.h>
+
+       * command.c (lookup_cmd): Clear out trailing whitespace.
+
+       * command.c (lookup_cmd_1): Changed malloc to alloca.  
+       
+Fri May 12 12:13:12 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * printcmd.c (print_frame_args): Only print nameless args when you
+       know how many args there are supposed to be and when you've
+       printed fewer than them.  Don't print nameless args between
+       printed args.
+
+       * symtab.c (make_symbol_completion_function): Fixed typo (= ==>
+       ==). 
+
+       * remote.c (remote_open): ifdef'd out siginterrupt call by #ifndef
+       NO_SIGINTERRUPT.
+       * m-umax.h: Defined NO_SIGINTERRUPT.
+
+       * expread.y [ptype, array_mod, func_mod, direct_abs_decl,
+       abs_decl]:  Added rules for parsing and creating arbitrarily
+       strange types for casts and sizeofs.
+
+       * symtab.c, symtab.h (create_array_type): Created.  Some minor
+       misfeatures; see comments for details (main one being that you
+       might end up creating two arrays when you only needed one).
+
+Thu May 11 13:11:49 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * valops.c (value_zero): Add an argument for type of lval.
+       * eval.c (evaluate_subexp_for_address): Take address properly in
+       the avoid side affects case (ie. keep track of whether we have an
+       lval in memory and we can take the address).
+       (evaluate_subexp): Set the lval type of expressions created with
+       value_zero properley.
+
+       * valops.c, value.h (value_zero): Created--will return a value of
+       any type with contents filled with zero.
+       * symtab.c, symtab.h (lookup_struct_elt_type): Created.
+       * eval.c (evaluate_subexp): Modified to not read memory when
+       called with EVAL_AVOID_SIDE_EFFECTS.
+
+       * Makefile: Moved dbxread.c ahead of coffread.c in the list of
+       source files. 
+
+Wed May 10 11:29:19 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * munch: Make sure that sysv version substitutes for the whole
+       line. 
+
+       * symtab.h: Created an enum misc_function_type to hold the type of
+       the misc function being recorded.
+       * dbxread.c (record_misc_function): Branched on dbx symbols to
+       decide which type to assign to a misc function.
+       * coffread.c (record_misc_function): Always assign type unknown.
+       * expread.y [variable]: Now tests based on new values.
+
+Tue May  9 13:03:54 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symtab.c: Changed inclusion of <strings.h> (doesn't work on
+       SYSV) to declaration of index.
+
+       * Makefile: Changed last couple of READLINE_FLAGS SYSV_DEFINE
+
+       * source.c ({forward, reverse}_search_command): Made a default
+       search file similar to for the list command.
+
+Mon May  8 18:07:51 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * printcmd.c (print_frame_args): If we don't know how many
+       arguments there are to this function, don't print the nameless
+       arguments.  We don't know enough to find them.
+
+       * printcmd.c (print_frame_args): Call print_frame_nameless_args
+       with proper arguments (start & end as offsets from addr).
+
+       * dbxread.c (read_addl_syms): Removed cases to deal with global
+       symbols; this should all be done in scan_global_symbols.
+
+Sun May  7 11:36:23 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * Makefile: Added copying.awk to ${OTHERS}.
+
+Fri May  5 16:49:01 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * valprint.c (type_print_varspec_prefix): Don't pass
+       passed_a_pointer onto children.
+
+       * valprint.c (type_print_varspec_suffix): Print "array of" with
+       whatever the "of" is after tha array brackets.
+
+       * valprint.c (type_print_varspec_{prefix,suffix}): Arrange to
+       parenthesisze pointers to arrays as well as pointers to other
+       objects. 
+
+       * valprint.c (type_print_varspec_suffix): Make sure to print
+       subscripts of multi-dimensional arrays in the right order.
+
+       * infcmd.c (run_command): Fixed improper usages of variables
+       within remote debugging branch.
+
+       * Makefile: Added Convex.notes to the list of extra files to carry
+       around. 
+
+       * dbxread.c (symbol_file_command): Made use of alloca or malloc
+       dependent on macro define.
+
+Thu May  4 15:47:04 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * Makefile: Changed READLINE_FLAGS to SYSV_DEFINE and called munch
+       with it also.
+       * munch: Check first argument for -DSYSV and be looser about
+       picking up init routines if you find it.
+
+       * coffread.c: Made fclose be of type int.
+
+       * breakpoint.c (_initialize_breakpoint): Put "unset" into class
+       alias. 
+
+Wed May  3 14:09:12 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-sparc.h [STACK_END_ADDR]: Parameterized off of
+       machine/vmparam.h (as per John Gilmore's suggestion).
+
+       * blockframe.c (get_prev_frame_info): Changed this function back
+       to checking frameless invocation first before checking frame
+       chain.  This means that a backtrace up from start will produce the
+       wrong value, but that a backtrace from a frameless function called
+       in main will show up correctly.
+
+       * breakpoint.c (_initialize_breakpoint): Added entry in help for
+       delete that indicates that unset is an alias for it.
+
+       * main.c (symbol_completion_function): Modified recognition of
+       being within a single command.
+
+Tue May  2 15:13:45 1989  Randy Smith  (randy at gnu)
+
+       * expread.y [variable]: Add some parens to get checking of the
+       misc function vector right.
+
+Mon May  1 13:07:03 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * default-dep.c (core_file_command): Made reg_offset unsigned.
+
+       * default-dep.c (core_file_command): Improved error messages for
+       reading in registers.
+
+       * expread.y: Allowed a BLOCKNAME to be ok for a variable name (as
+       per C syntax). 
+
+       * dbxread.c (psymtab_to_symtab): Flushed stdout after printing
+       starting message about reading in symbols.
+
+       * printcmd.c (print_frame_args): Switched starting place for
+       printing of frameless args to be sizeof int above last real arg
+       printed. 
+
+       * printcmd.c (print_frame_args): Modified final call to
+       print_nameless_args to not use frame slots used array if none had
+       been used. 
+
+       * infrun.c (wait_for_inferior):  Take FUNCTION_START_OFFSET into
+       account when dealing with comparison of pc values to function
+       addresses. 
+
+       * Makefile: Added note about compiling gdb on a Vax running 4.3.
+
+Sun Apr 30 12:59:46 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * command.c (lookup_cmd): Got correct error message on bad
+       command.  
+
+       * m-sun3.h [ABOUT_TO_RETURN]: Modified to allow any of the return
+       instructions, including trapv and return from interupt.
+
+       * command.c (lookup_cmd): If a command is found, use it's values
+       for error reporting and determination of needed subcommands.
+
+       * command.c (lookup_cmd): Use null string for error if cmdtype is
+       null; pass *line to error instead of **.
+
+       * command.c (lookup_cmd_1): End of command marked by anything but
+       alpha numeric or '-'.  Included ctype.h.
+
+Fri Apr 28 18:30:49 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * source.c (select_source_symtab): Kept line number from ever
+       being less than 1 in main decode.
+
+Wed Apr 26 13:03:20 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * default-dep.c (core_file_command): Fixed typo.
+
+       * utils.c (fprintf_filtered): Don't use return value from
+       numchars. 
+
+       * main.c, command.c (complete_on_cmdlist): Moved function to
+       command.c. 
+
+       * command.c (lookup_cmd): Modified to use my new routine.  Old
+       version is still there, ifdef'd out.
+
+       * command.c, command.h (lookup_cmd_1): Added a routine to do all
+       of the work of lookup_cmd with no error reporting and full return
+       of information garnered in search.
+
+Tue Apr 25 12:37:54 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * breakpoint.c (_initialize_breakpoint): Change "delete
+       breakpionts" to be in class alias and not have the abbrev flag
+       set. 
+
+       * main.c (symbol_completion_function): Fix to correctly complete
+       things that correspond to multiword aliases.
+
+       * main.c (complete_on_cmdlist): Don't complete on something if it
+       isn't a command or prefix (ie. if it's just a help topic).
+
+       * main.c (symbol_completion_function): Set list index to be 0 if
+       creating a list with just one element.
+
+       * main.c (complete_on_cmdlist): Don't allow things with
+       abbrev_flag set to be completion values.
+       (symbol_completion_function): Don't accept an exact match if the
+       abbrev flag is set.
+
+       * dbxread.c (read_type): Fixed typo in comparision to check if
+       type number existed.
+
+       * dbxread.c (read_type): Made sure to only call dbx_lookup_type on
+       typenums if typenums were not -1.
+
+Mon Apr 24 17:52:12 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symtab.c: Added strings.h as an include file.
+
+Fri Apr 21 15:28:38 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symtab.c (lookup_partial_symtab): Changed to only return a match
+       if the name match is exact (which is what I want in all cases in
+       which this is currently used.
+
+Thu Apr 20 11:12:34 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * m-isi.h [REGISTER_U_ADDR]: Installed new version from net.
+       * default-dep.c: Deleted inclusion of fcntl.h; apparently not
+       necessary.
+       * Makefile: Added comment about compiling on isi under 4.3.
+
+       * breakpoint.c (break_command_1): Only give decode_line_1 the
+       default_breakpoint_defaults if there's nothing better (ie. make
+       the default be off of the current_source notes if at all
+       possible). 
+
+       * blockframe.c (get_prev_frame_info): Clean up comments and
+       delete code ifdefed out around FRAMELESS_FUNCTION_INVOCATION test. 
+
+       * remote.c: Added a "?" message to protocol.
+       (remote_open): Used at startup.
+       (putpkt): Read whatever garbage comes over the line until we see a
+       '+' (ie. don't treat garbage as a timeout).
+
+       * valops.c (call_function): Eliminated no longer appropriate
+       comment.
+
+       * infrun.c (wait_for_inferior): Changed several convex conditional
+       compilations to be conditional on CANNOT_EXECUTE_STACK.
+
+Wed Apr 19 10:18:17 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * printcmd.c (print_frame_args): Added code to attempt to deal
+       with arguments that are bigger than an int.
+
+       Continuation of Convex/Fortran changes:
+       * printcmd.c (print_scalar_formatted): Added leading zeros to
+       printing of large integers.
+       (address_info, print_frame_args): Added code to deal with
+       LOC_REF_ARG.
+       (print_nameless_args): Allow param file to specify a routine with
+       which to print typeless integers.
+       (printf_command): Deal with long long values well.
+       * stack.c (print_frame_arg_vars): Change to deal with LOC_REF_ARG.
+       * symmisc.c (print_symbol): Change to deal with LOC_REF_ARG.
+       * symseg.h: Added LOC_REF_ARG to enum address_class.
+       * symtab.c (lookup_block_symbol): Changed to deal with
+       LOC_REF_ARG.
+       * valarith.c (value_subscripted_rvalue): Created.
+       (value_subscript): Used above when app.
+       (value_less, value_equal): Change to cast to (char *) before doing
+       comparison, for machines where that casting does something.
+       * valops.c (call_function): Setup to deal with machines where you
+       cannot execute code on the stack segment.
+       * valprint.c (val_print): Make sure that array element size isn't
+       zero before printing.  Set address of default array to address of
+       first element.  Put in a couple of int cast.  Removed some convex
+       specific code. Added check for endianness of machine in case of a
+       packed structure.  Added code for printing typeless integers and
+       for LONG LONG's.
+       (set_maximum_command): Change to use parse_and_eval_address to get
+       argument (so can use expressions there).
+       * values.c (value_of_internalvar, set_internalvar_component,
+       set_internalvar, convenience_info): Add in hooks for trapped
+       internal vars.
+       (unpack_long): Deal with LONG_LONG.
+       (value_field): Remove LONGEST cast.
+       (using_struct_return): Fixed typo ENUM ==> UNION.
+       * xgdb.c (_initialize_xgdb): Make sure that specify_exec_file_hook
+       is not called unless we are setting up a windowing environ.
+
+Tue Apr 18 13:43:37 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       Various changes involved in 1) getting gdb to work on the convex,
+       and 2) Getting gdb to work with fortran (due to convex!csmith):
+       * convex-dep.c, convex-opcode.h, m-convex.h, convex-pinsn.c:
+       Created (or replaced with new files).
+       * Makefile: Add convex dependent files.  Changed default flags to
+       gnu malloc to be CFLAGS.
+       * config.gdb: Added convex to list of machines.
+       * core.c (files_info): Added a FILES_INFO_HOOK to be used if
+       defined.
+       (xfer_core_file): Conditionalized compilation of xfer_core_file on
+       the macro XFER_CORE_FILE.
+       * coffread.c (record_misc_function): Made sure it zerod type field
+       (which is now being used; see next).
+       * dbxread.c: Included some convex dependent include files.
+       (copy_pending, fix_common_blocks): Created.
+       [STAB_REG_REGNUM, BELIEVE_PCC_PROMOTION]: Created default values;
+       may be overridden in m-*.h.
+       Included data structures for keeping track of common blocks.
+       (dbx_alloc_type): Modified; if called with negative 1's will
+       create a type without putting it into the type vector.
+       (read_dbx_symtab, read_addl_syms): Modified calls to
+       record_misc_function to include the new information.
+       (symbol_file_command, psymtab_to_symtab, add_file_command):
+       Modified reading in of string table to adapt to machines which
+       *don't* store the size of the string table in the first four bytes
+       of the string table.
+       (read_dbx_symtab, scan_file_globals, read_ofile_symtab,
+       read_addl_syms): Modified assignment of namestring to accept null
+       index into symtab as ok.
+       (read_addl_syms): Modified readin of a new object file to fiddle
+       with common blocks correctly.
+       (process_one_symbol): Fixed incorrect comment about convex.  Get
+       symbols local to a lexical context from correct spot on a per
+       machine basis.  Catch a bug in pcc which occaisionally puts an SO
+       where there should be an SOL.  Seperate sections for N_BCOMM &
+       N_ECOMM.
+       (define_symbol): Ignore symbols with no ":".  Use
+       STAB_REG_TO_REGNUM.  Added support for function args calling by
+       reference.
+       (read_type): Only read type number if one is there.  Remove old
+       (#if 0'd out) array code.
+       (read_array_type): Added code for dealing with adjustable (by
+       parameter) arrays half-heartedly.
+       (read_enum_type): Allow a ',' to end a list of values.
+       (read_range_type): Added code to check for long long.
+       * expread.y: Modified to use LONGEST instead of long where
+       necessary.  Modified to use a default type of int for objects that
+       weren't in text space.
+       * findvar.c (locate_var_value, read_var_value): Modified to deal
+       with args passed by reference.
+       * inflow.c (create_inferior): Used CREATE_INFERIOR_HOOK if it
+       exists.
+       * infrun.c (attach_program): Run terminal inferior when attaching.
+       (wait_for_inferior): Removed several convex dependencies.
+       * main.c (float_handler): Created.
+       Made whatever signal indicates a stop configurable (via macro
+       STOP_SIGNAL).
+       (main): Setup use of above as a signal handler.  Added check for
+       "-nw" in args already processed.
+       (command_line_input): SIGTSTP ==>STOP_SIGNAL.
+
+       * expread.y: Added token BLOCKNAME to remove reduce/reduce
+       conflict.
+       * Makefile: Change message to reflect new grammar.
+
+Mon Apr 17 13:24:59 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * printcmd.c (compare_ints): Created.
+       (print_frame_args): Modified to always print arguments in the
+       order in which they were found in the symbol table.  Figure out
+       what apots are missing on the fly.
+
+       * stack.c (up_command): Error if no inferior or core file.
+
+       * m-i386.h, m-symmetry.h [FRAMELESS_FUNCTION_INVOCATION]: Created;
+       same as m68k.
+
+       * dbxread.c (define_symbol): Changed "desc==0" test to
+       "processing_gcc_compilation", which is the correct way to do it.
+
+Sat Apr 15 17:18:38 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * expread.y: Added precedence rules for arglists, ?:, and sizeof
+       to eliminate some shift-reduce conflicts.
+       * Makefile: Modified "Expect" message to conform to new results.
+
+Thu Apr 13 12:29:26 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * inflow.c (terminal_init_inferior): Fixed typo in recent diff
+       installation; TIOGETC ==> TIOCGETC.
+
+       * m-vax.h, m-sun2.h, m-sun3.h, m-sparc.h, m-hp*.h, m-isi.h,
+       m-news.h [FRAMELESS_FUNCTION_INVOCATION]: Created macro with
+       appropriate definition.
+
+Wed Apr 12 15:30:29 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * blockframe.c (get_prev_frame_info): Added in a macro to specify
+       when a "frame" is called without a frame pointer being setup.
+
+       * Makefile [clean]: Made sure to delete gnu malloc if it was being
+       used. 
+
+Mon Apr 10 12:43:49 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (process_one_symbol): Reset within_function to 0 after
+       last RBRAC of a function.
+
+       * dbxread.c (read_struct_type): Changed check for filling in of
+       TYPE_MAIN_VARIANT of type.
+
+       * inflow.c (create_inferior): Conditionalized fork so that it
+       would be used if USG was defined and HAVE_VFORK was not defined.
+
+       * defs.h: Added comment about enum command_class element
+       class_alias. 
+
+       * dbxread.c (process_one_symbol): Fixed a typo with interesting
+       implications for associative processing in the brain (':' ==> 'c').
+
+       * sparc-dep.c (isabranch): Changed name to isannulled, modified to
+       deal with coprocessor branches, and improved comment.
+       (single_step): Changed to trap at npc + 4 instead of pc +8 on
+       annulled branches.  Changed name in call to isabranch as above.
+
+       * m-sun4os4.h (STACK_END_ADDRESS): Changed it to 0xf8000000 under
+       os 4.0.
+
+Sat Apr  8 17:04:07 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (process_one_symbol): In the case N_FUN or N_FNAME the
+       value being refered to is sometimes just a text segment variable.
+       Catch this case.
+
+       * infrun.c (wait_for_inferior), breakpoint.c
+       (breakpoint_stop_status): Move the selection of the frame to
+       inside breakpoint_stop_status so that the frame only gets selected
+       (and the symbols potentially read in) if the symbols are needed.
+
+       * symtab.c (find_pc_psymbol): Fixed minor misthough (pc >=
+       fucntion start, not >).
+
+       * breakpoint.c (_initialize_breakpoint): Change "delete" internal
+       help entry to simply refer to it being a prefix command (since the
+       list of subcommands is right there on a "help delete").
+
+Fri Apr  7 15:22:18 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * blockframe.c (find_pc_partial_function): Created; figures out
+       what function pc is in (name and address) without reading in any
+       new symbols.
+       * symtab.h: Added decl for above.
+       * infrun.c (wait_for_inferior): Used instead of
+       find_pc_function_start.
+       * stack.c (print_frame_info): Used instead of hand coding for same
+       thing. 
+
+       * dbxread.c (psymtab_to_symtab): No longer patch readin pst's out
+       of the partial_symtab_list; need them there for some checks.
+       * blockframe.c (block_for_pc), source.c (select_source_symtab),
+       symtab.c (lookup_symbol, find_pc_symtab, list_symbols): Made extra
+       sure not to call psymtab_to_symtab with ->readin == 1, since these
+       psymtab now stay on the list.
+       * symtab.c (sources_info): Now distinguishes between psymtabs with
+       readin set and those with it not set.
+
+       * symtab.c (lookup_symtab): Added check through partial symtabs
+       for name with .c appended.
+
+       * source.c (select_source_symtab): Changed semantics a little so
+       that the argument means something.
+       * source.c (list_command), symtab.c (decode_line_1): Changed call
+       to select_source_symtab to match new conventions.
+
+       * dbxread.c (add_file_command): This command no longer selects a
+       symbol table to list from.
+
+       * infrun.c (wait_for_inferior): Only call find_pc_function (to
+       find out if we have debugging symbols for a function and hence if
+       we should step over or into it) if we are doing a "step".
+
+Thu Apr  6 12:42:28 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c (command_line_input): Added a local buffer and only
+       copied information into the global main.c buffer when it is
+       appropriate for it to be saved (and repeated).
+       (dont_repeat): Only nail line when we are reading from stdin
+       (otherwise null lines won't repeat and what's in line needs to be
+       saved).
+       (read_command_lines): Fixed typo; you don't what to repeat when
+       reading command lines from the input stream unless it's standard
+       input. 
+
+        John Gilmore's (gnu@toad.com) mods for USG gdb:
+       * inflow.c: Removed inclusion of sys/user.h; no longer necessary.
+       (, terminal_init_inferior, terminal_inferior, terminal_ours_1,
+       term_status_command, _initialize_inflow) Seperated out declaration
+       and usage of terminal mode structures based on the existence of
+       the individual ioctls.
+       * utils.c (request_quit): Restore signal handler under USG.  If
+       running under USG initialize sys_siglist at run time (too much
+       variation between systems).
+
+Wed Apr  5 13:47:24 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+        John Gilmore's (gnu@toad.com) mods for USG gdb:
+       * default-dep.c: Moved include of sys/user.h to after include of
+       a.out.h.
+       (store_inferior_registers): Fixed error message.
+       (core_file_command): Improved error messages from reading in of
+       u area in core file.  Changed calculation of offset of registers
+       to account for some machines putting it in as an offset rather
+       than an absolute address.  Changed error messages for reading of
+       registers from core file.
+
+       * coffread.c (read_file_hdr): Added final check for BADMAG macro
+       to use if couldn't recognize magic number.
+       * Makefile: Added explicit directions for alloca addition.
+       Included alloca.c in list of possible library files. Cleaned up
+       possible library usage.  Included additional information on gcc
+       and include files.  
+
+       * source.c, remote.c, inflow.c, dbxread.c, core.c, coffread.c:
+       Changed include of sys/fcntl.h to an include of fcntl.h (as per
+       posix; presumably this will break fewer machines.  I hopw).
+       * README: Added a pointer to comments at top of Makefile.
+       * Makefile: Added a comment about machines which need fcntl.h in
+       sys. 
+
+Tue Apr  4 11:29:04 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * valprint.c (set_prettyprint_command, set_unionprint_command,
+       format_info): Created.
+       (_initialize_valprint): Added to lists of commands.
+
+       * gdb.texinfo [Backtrace]: Added a section describing the format
+       if symbols have not yet been read in.
+
+       * valprint.c (val_print): Added code to prettyprint structures if
+       "prettyprint" is set and only to print unions below the top level
+       if "unionprint" is set.
+
+       * infcmd.c (registers_info), valprint.c (value_print, val_print):
+       Added argument to call to val_print indicating deptch of recursion.
+
+       * symtab.[ch] (find_pc_psymbol): Created; finds static function
+       psymbol with value nearest to but under value passed.
+       * stack.c (print_frame_info): Used above to make sure I have best
+       fit to pc value.
+
+       * symseg.h (struct partial_symbol): Added value field.
+       * dbxread.c (read_dbx_symtab): Set value field for partial symbols
+       saved (so that we can lookup static symbols).
+
+       * symtab.[ch] (find_pc_symtab): Changed to external.
+       * stack.c (select_frame): Call above to make sure that symbols for
+       a selected frame is readin.
+
+Mon Apr  3 12:48:16 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * stack.c (print_frame_info): Modified to only print out full
+       stack frame info on symbols whose tables have been read in.
+       * symtab.c, symtab.h (find_pc_psymtab): Made function external;
+       above needed it.
+
+       * main.c (,set_verbose_command, initialize_main): Created a
+       variable "info_verbose" which says to talk it up in various and
+       sundry places.  Added command to set this variable.
+       * gdb.texinfo (GDB Output): Added documentation on "set verbose"
+       and changed the name of the "Screen Output" section to "GDB
+       Output".
+       * dbxread.c (psymtab_to_symtab): Added information message about
+       symbol readin.  Conditionalized on above.
+
+       * dbxread.c (define_symbol): Made an "i" constant be of class
+       LOC_CONST and an "r" constant be of class LOC_CONST_BYTES.
+
+       * README: Made a note about modifications which may be necessary
+       to the manual for this version of gdb.
+
+       * blockframe.c (get_prev_frame_info): Now we get saved address and
+       check for validity before we check for leafism.  This means that
+       we will catch the fact that we are in start, but we will miss any
+       fns that start calls without an fp.  This should be fine.
+
+       * m-*.h (FRAME_CHAIN): Modified to return 0 if we are in start.
+       This is usually a test for within the first object file.
+       * m-sparc.h (FRAME_CHAIN): The test here is simply if the fp saved
+       off the the start sp is 0.
+
+       * blockframe.c (get_prev_frame_info): Removed check to see if we
+       were in start.  Screws up sparc.  
+
+       * m-sparc.h (FRAME_FIND_SAVED_REGISTERS): Changed test for dummy
+       frame to not need frame to be innermost.
+
+       * gdb.texinfo: Added section on frameless invocations of functions
+       and when gdb can and can't deal with this.
+
+       * stack.c (frame_info): Disallowed call if no inferior or core
+       file; fails gracefully if truely bad stack specfication has been
+       given (ie. parse_frame_specification returns 0).
+
+Fri Mar 31 13:59:33 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * infrun.c (normal_stop): Changed references to "unset-env" to
+       "delete env".
+
+       * infcmd.c (_initialize_infcmd): Change reference to set-args in
+       help run to "set args".
+
+       * remote.c (getpkt): Allow immediate quit when reading from
+       device; it could be hung.
+
+       * coffread.c (process_coff_symbol): Modify handling of REG
+       parameter symbols.
+
+Thu Mar 30 15:27:23 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (symbol_file_command): Use malloc to allocate the
+       space for the string table in symbol_file_command (and setup a
+       cleanup for this).  This allows a more graceful error failure if
+       there isn't any memory availible (and probably allows more memory
+       to be avail, depending on the machine).
+
+       Additional mods for handling GNU C++ (from Tiemann):
+       * dbxread.c (read_type): Added case for '#' type (method type, I
+       believe).
+       (read_struct_type): If type code is undefined, make the main
+       variant for the type be itself.  Allow recognition of bad format
+       in reading of structure fields.
+       * eval.c (evaluate_subexp): Modify evaluation of a member of a
+       structure and pointer to same to make sure that the syntax is
+       being used correctly and that the member is being accessed correctly.
+       * symseg.h: Added TYPE_CODE_METHOD to enum type_code.  Add a
+       pointer to an array of argument types to the type structure.
+       * symtab.c (lookout_method_type, smash_to_method_type): Created.
+       * symtab.h (TYPE_ARG_TYPES): Created.
+       * valops.c (call_function): Modified handling of methods to be the
+       same as handling of functions; no longer check for members.
+       * valprint.c (val_print, type_print_varspec_{prefix,suffix},
+       type_print_base): Added code to print method args correctly.
+       * values.c (value_virtual_fn_field): Modify access to virtual
+       function table.
+
+Wed Mar 29 13:19:34 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * findvar.c: Special cases for REGISTER_WINDOWS: 1) Return 0 if we
+       are the innermost frame, and 2) return the next frame in's value
+       if the SP is being looked for.
+
+       * blockframe.c (get_next_frame): Created; returns the next (inner)
+       frame of the called frame.
+       * frame.h: Extern delcaration for above.
+
+       * main.c (command_line_input): Stick null at end before doing
+       history expansion.
+
+Tue Mar 28 17:35:50 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): Added namestring assignment to
+       N_DATA/BSS/ABS case.  Sigh.
+
+Sat Mar 25 17:49:07 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * expread.y: Defined YYDEBUG.
+
+Fri Mar 24 20:46:55 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symtab.c (make_symbol_completion_list): Completely rewrote to
+       never call psymtab_to_symtab, to do a correct search (no
+       duplicates) through the visible symbols, and to include structure
+       and union fields in the things that it can match.
+
+Thu Mar 23 15:27:44 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (dbx_create_type): Created; allocates and inits space
+       for a type without putting it on the type vector lists.
+       (dbx_alloc_type): Uses above.
+
+       * Makefile: xgdb.o now produced by default rules for .o.c.
+
+Fri Mar 17 14:27:50 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * infrun.c: Fixed up inclusion of aouthdr.h on UMAX_PTRACE.
+
+       * Makefile, config.gdb: Added hp300bsd to potential
+       configurations.
+       * hp300bsd-dep.c, m-hp300bsd.h: Created.
+
+       * infrun.c (wait_for_inferior): Rewrote to do no access to
+       inferior until we make sure it's still there.
+
+       * inflow.c (inferior_died): Added a select to force the selected
+       frame to null when inferior dies.
+
+       * dbxread.c (symbol_file_command): free and zero symfile when
+       discarding symbols.
+
+       * core.c (xfer_core_file): Extended and cleaned up logic in
+       interpeting memory address.
+
+       * core.c (xfer_core_file): Extended opening comment.
+
+Thu Mar 16 15:39:42 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * coffread.c (symbol_file_command): Free symfile name when freeing
+       contents.
+
+       * blockframe.c (get_prev_frame_info): Added to fatal error message
+       to indicate that it should never happen.
+
+       * stack.c (frame_info): Printed out value of "saved" sp seperately
+       to call attention to the fact that it isn't stored in memory
+       anywhere; the actual previous frames address is printed.
+
+       * m-sparc.h (FRAME_FIND_SAVED_REGS): Set address of sp saved in
+       frame to value of fp (rather than value of sp in current frame).
+
+       * expread.y: Allow "unsigned" as a type itself, as well as a type
+       modifier. 
+
+       * coffread.c: Added declaration for fclose
+
+Fri Mar 10 17:22:31 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c (command_line_input): Checked for -1 return from
+       readline; indicates EOF.
+
+Fri Mar  3 00:31:27 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * remote.c (remote_open): Cast return from signal to (void (*)) to
+       avoid problems on machines where the return type of signal is (int
+       (*)). 
+
+       * Makefile: Removed deletion of version control from it (users
+       will need it for their changes).
+
+Thu Mar  2 15:32:21 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symmetry-dep.c (print_1167_regs): Print out effective doubles on
+       even number regs.
+       (fetch_inferior_registers): Get the floating point regs also.
+
+       * xgdb.c (do_command): Copied command before calling execute
+       command (so that execute_command wouldn't write into text space).
+
+       * copying.awk: Created (will produce copying.c as output when
+       given COPYING as input).
+       * Makefile: Used above to create copying.c.
+       * main.c: Took out info_warranty and info_copying.
+
+       * *.*: Changed copyright notice to use new GNU General Public
+       License (includes necessary changes to manual).
+
+       * xgdb.c (create_text_widget): Created text_widget before I create
+       the source and sink.
+       (print_prompt): Added fflush (stdout).
+
+       * Makefile: Added -lXmu to the compilation line for xgdb.  Left
+       the old one there incase people still had R2.
+
+       * README: Added note about -gg format.
+
+       * remote.c (getpkt): Fixed typo; && ==> &.
+
+       * Makefile: Added new variable READLINE_FLAGS so that I could
+       force compilation of readline.c and history.c with -DSYSV on
+       system V machines.  Mentioned in Makefile comments at top.
+
+Wed Mar  1 17:01:01 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * hp9k320-dep.c (store_inferior_registers): Fixed typo.
+
+Fri Feb 24 14:58:45 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * hp9k320-dep.c (store_inferior_registers,
+       fetch_inferior_registers): Added support for remote debugging. 
+
+       * remote.c (remote_timer): Created.
+       (remote_open, readchar): Setup to timeout reads if they take
+       longer than "timeout".  This allows one to debug how long such
+       things take.
+       (putpkt): Modified to print a debugging message (if such things
+       are enabled) each time it resends a packet.
+       (getpkt): Modified to make the variable CSUM unsigned and read it
+       CSUM with an & 0xff (presumably to deal with poor sign extension
+       on some machines).  Also made c1 and c2 unsigned.
+       (remote_wait): Changed buffer to unsigned status.
+       (remote_store_registers, remote_write_bytes): Puts a null byte at
+       the end of the control string.
+
+       * infcmd.c (attach_command, detach_command, _initialize_infcmd):
+       Made attach_command and detach_command always availible, but
+       modified them to only allow device file attaches if ATTACH_DETACH
+       is not defined.
+
+       * gdb.texinfo: Added cross reference from attach command to remote
+       debugging. 
+
+Thu Feb 23 12:37:59 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * remote.c (remote_close): Created to close the remote connection
+       and set the remote_debugging flag to 0.
+       * infcmd.c (detach_command): Now calls the above when appropriate. 
+
+       * gdb.texinfo: Removed references to the ``Distribution'' section
+       in the copyright.
+
+       * main.c, utils.c (ISATTY): Created default defintions of this
+       macro which use isatty and fileno.
+       * utils.c (fprintf_filtered, print_spaces_filtered), main.c
+       (command_loop, command_line_input): Used this macro.
+       * m-news.h: Created a definition to override this one.
+
+       * utils.c (fprintf_filtered): Made line_size static (clueless).
+
+       * utils.c (fprintf_filtered): Changed max length of line printed
+       to be 255 chars or twice the format length.
+
+       * symmetry-dep.c, m-symmetry: Fixed typo (^L ==> \f).
+
+       * printcmd.c (do_examine): Fixed typo (\n ==> \t).
+
+Wed Feb 22 16:00:33 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+        Contributed by Jay Vosburgh (jay@mentor.cc.purdue.edu)
+       * m-symmetry.h, symmetry-dep.c: Created.
+       * Makefile: Added above in appropriate lists.
+       * config.gdb: Added "symmetry" target.
+
+       * utils.c (prompt_for_continue): Zero'd chars_printed also.
+
+       * utils.c (fprintf_filtered): Call prompt for continue instead of
+       doing it yourself.
+
+       * dbxread.c (read_dbx_symtab): Added code to conditionalize what
+       symbol type holds to "x.o" or "-lx" symbol that indicates the
+       beginning of a new file.
+
+Tue Feb 21 16:22:13 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * gdb.texinfo: Deleted @ignore block at end of file.
+
+       * findvar.c, stack.c: Changed comments that refered to "frame
+       address" to "frame id".
+
+       * findvar.c (locate_var_value): Modified so that taking the
+       address of an array generates an object whose type is a pointer to
+       the elements of the array.
+
+Sat Feb 18 16:35:14 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * gdb.texinfo: Removed reference to "!" as a shell escape
+       character.  Added a section on controling screen output
+       (pagination); changing "Input" section to "User Interface"
+       section.  Changed many inappropriate subsubsection nodes into
+       subsections nodes (in the readline and history expansion
+       sections). 
+
+Fri Feb 17 11:10:54 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * utils.c (set_screensize_command): Created.
+       (_initialize_utils): Added above to setlist.
+
+       * main.c (main): Added check to see if ~/.gdbinit and .gdbinit
+       were the same file; only one gets read if so.  Had to include
+       sys/stat.h for this.
+
+       * valprint.c (type_print_base): Changed calls to print_spaces to
+       print_spaces_filtered. 
+
+       * main.c (command_line_input): Chaned test for command line
+       editing to check for stdin and isatty.
+
+       * main.c (command_loop): Call reinitialize_more_filter before each
+       command (if reading from stdin and it's a tty).
+       utils.c (initialize_more_filter): Changed name to
+       reinitialize_more_filter; killed arguments.
+       utils.c (_initialize_utils): Created; initialized lines_per_page
+       and chars_per_line here.
+
+       * utils.c (fprintf_filtered): Removed printing of "\\\n" after
+       printing linesize - 1 chars; assume that the screen display will
+       take care of that.  Still watching that overflow.
+
+       * main.c: Created the global variables linesize and pagesize to
+       describe the number of chars per line and lines per page.
+
+Thu Feb 16 17:27:43 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * printcmd.c (do_examine, print_scalar_formatted, print_address,
+       whatis_command, do_one_display, ptype_command), valprint.c
+       (value_print, val_print, type_print_method_args, type_print_1,
+       type_print_derivation_info, type_print_varspec_suffix,
+       type_print_base), breakpoint.c (breakpoints_info, breakpoint_1),
+       values.c (history_info), main.c (editing_info, warranty_info,
+       copying_info), infcmd.c (registers_info), inflow.c
+       (term_status_command), infrun.c (signals_info), stack.c
+       (backtrace_command, print_frame_info), symtab.c (list_symbols,
+       output_source_filename), command.c (help_cmd, help_list,
+       help_command_list): Replaced calls to printf, fprintf, and putc
+       with calls to [f]printf_filtered to handle more processing.
+       Killed local more emulations where I noticed them.
+
+Wed Feb 15 15:27:36 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * defs.h, utils.c (initialize_more_filter, fprintf_filtered,
+       printf_filtered): Created a printf that will also act as a more
+       filter, prompting the user for a <return> whenever the page length
+       is overflowed.
+
+       * symtab.c (list_symbols): Elminated some code inside of an #if 0. 
+
+Tue Feb 14 11:11:24 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * Makefile: Turned off backup versions for this file; it changes
+       too often.
+
+       * command.c (lookup_cmd, _initialize_command): Changed '!' so that
+       it was no longer a shell escape.  "sh" must be used.
+
+       * main.c (command_line_input, set_history_expansion,
+       initialize_main): Turned history expansion on, made it the
+       default, and only execute it if the first character in the line is
+       a '!'.
+
+       * version.c, gdb.texinfo: Moved version to 3.2 (as usual, jumping
+       the gun some time before release).
+
+       * gdb.texinfo: Added sections (adapted from Brian's notes) on
+       command line editing and history expansion.
+
+       * main.c (set_command_editing, initialize_main): Modified name to
+       set_editing and modified command to "set editing".
+
+       * Makefile: Put in dependencies for READLINEOBJS.
+
+       * main.c (history_info, command_info): Combined into new command
+       info; deleted history_info.
+       (initialize_main): Deleted "info history" command; it was
+       interfering with the value history.
+
+       * coffread.c (enter_linenos): Modified to do bit copy instead of
+       pointer dereference, since the clipper machine can't handle having
+       longs on short boundaries.
+       (read_file_hdr): Added code to get number of syms for clipper.
+
+       * stack.c (return_command): Fixed method for checking when all of
+       the necessary frames had been popped.
+
+       * dbxread.c (read_dbx_symtab (ADD_PSYMBOL_TO_LIST)): Fixed typo in
+       allocation length.
+
+Mon Feb 13 10:03:27 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): Split assignment to namestring into
+       several different assignments (so that it wouldn't be done except
+       when it had to be).  Shortened switches and duplicated code to
+       produce the lowest possible execution time.  Commented (at top of
+       switch) which code I duplicated.
+
+       * dbxread.c (read_dbx_symtab): Modified which variables were
+       register and deleted several variables which weren't used.  Also
+       eliminated 'F' choice from subswitch, broke out strcmp's, reversed
+       compare on line 1986, and elminated test for !namestring[0]; it is
+       caught by following test for null index of ':'.
+
+Sun Feb 12 12:57:56 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * main.c (gdb_completer_word_break_characters): Turned \~ into ~.
+
+Sat Feb 11 15:39:06 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * symtab.c (find_pc_psymtab): Created; checks all psymtab's till
+       it finds pc.
+       (find_pc_symtab): Used; fatal error if psymtab found is readin
+       (should have been caught in symtab loop).
+       (lookup_symbol): Added check before scan through partial symtab
+       list for symbol name to be on the misc function vector (only if in
+       VAR_NAMESPACE).  Also made sure that psymtab's weren't fooled with
+       if they had already been read in.
+       (list_symbols): Checked through misc_function_vector for matching
+       names if we were looking for functions.
+       (make_symbol_completion_list): Checked through
+       misc_function_vector for matching names.
+       * dbxread.c (read_dbx_symtab): Don't bother to do processing on
+       global function types; this will be taken care of by the
+       misc_function hack.
+
+       * symtab.h: Modified comment on misc_function structure.
+
+Fri Feb 10 18:09:33 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * symseg.h, dbxread.c (read_dbx_symtab, init_psymbol_list,
+       start_psymtab, end_psymtab), coffread.c (_initialize_coff),
+       symtab.c (lookup_partial_symbol, list_symbols,
+       make_symbol_completion_list): Changed separate variables for
+       description of partial symbol allocation into a specific kind of
+       structure.
+
+       (read_dbx_symtab, process_symbol_for_psymtab): Moved most of
+       process_symbol_for_psymtab up into read_dbx_symtab, moved a couple
+       of symbol types down to the ingore section, streamlined (I hope)
+       code some, modularized access to psymbol lists.
+
+Thu Feb  9 13:21:19 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c (command_line_input): Made sure that it could recognize
+       newlines as indications to repeat the last line.
+
+       * symtab.c (_initialize_symtab): Changed size of builtin_type_void
+       to be 1 for compatibility with gcc.
+
+       * main.c (initialize_main): Made history_expansion the default
+       when gdb is compiled with HISTORY_EXPANSION.
+
+       * readline.c, readline.h, history.c, history.h, general.h,
+       emacs_keymap.c, vi_keymap.c, keymaps.c, funmap.c: Made all of
+       these links to /gp/gnu/bash/* to keep them updated.
+       * main.c (initialize_main): Made default be command editing on. 
+
+Wed Feb  8 13:32:04 1989  & Smith  (randy at hobbes)
+
+       * dbxread.c (read_dbx_symtab): Ignore N_BSLINE on first
+       readthrough. 
+
+       * Makefile: Removed convex-dep.c from list of distribution files.
+
+Tue Feb  7 14:06:25 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c: Added command lists sethistlist and unsethistlist to
+       accesible command lists.
+       (parse_binary_operation): Created to parse a on/1/yes vs. off/0/no
+       spec.
+       (set_command_edit, set_history, set_history_expansion,
+       set_history_write, set_history_size, set_history_filename,
+       command_info, history_info): Created to allow users to control
+       various aspects of command line editing.
+
+       * main.c (symbol_creation_function): Created.
+       (command_line_input, initialize_main): Added rest of stuff
+       necessary for calling bfox' command editing routines under
+       run-time control.
+       * Makefile: Included readline and history source files for command
+       editing; also made arrangements to make sure that the termcap
+       library was available.
+       * symtab.c (make_symbol_completion_list): Created.
+
+Mon Feb  6 16:25:25 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c: Invented variables to control command editing.
+       command_editing_p, history_expansion_p, history_size,
+       write_history_p, history_filename.  Initialized them to default
+       values in initialize_main.
+
+       * infcmd.c (registers_info), infrun.c (signals_info), 
+       * main.c (gdb_read_line): Changed name to command_line_input.
+       (readline): Changed name to gdb_readline; added second argument
+       indicating that the read value shouldn't be saved (via malloc).
+       * infcmd.c (registers_info), infrun.c (signals_info), main.c
+       (copying_info), symtab.c (output_source_filename, MORE,
+       list_symbols): Converted to use gdb_readline in place of
+       gdb_read_line. 
+
+
+Sun Feb  5 17:34:38 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * blockframe.c (get_frame_saved_regs): Removed macro expansion
+       that had accidentally been left in the code.
+
+Sat Feb  4 17:54:14 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * main.c (gdb_read_line, readline): Added function readline and
+       converted gdb_read_line to use it.  This was a conversion to the
+       line at a time style of input, in preparation for full command
+       editing. 
+
+Fri Feb  3 12:39:03 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): Call end_psymtab at the end of
+       read_dbx_symtab if any psymtab still needs to be completed.
+
+       * config.gdb, sun3-dep.c: Brought these into accord with the
+       actual sun2 status (no floating point period; sun3-dep.c unless
+       has os > 3.0).
+       * m-sun2os2.h: Deleted; not needed.
+
+       * config.gdb: Added a couple of aliases for machines in the
+       script. 
+
+       * infrun.c: Added inclusion of aouthdr.h inside of #ifdef UMAX
+       because ptrace needs to know about the a.out header.
+
+       * Makefile: Made dep.o depend on dep.c and config.status only.
+
+       * expread.y: Added declarations of all of the new write_exp_elt
+       functions at the include section in the top.
+
+       * Makefile: Added a YACC definition so that people can use bison
+       if they wish.
+
+       * Makefile: Added rms' XGDB-README to the distribution.
+
+       * Makefile: Added removal of init.o on a "make clean".
+
+Thu Feb  2 16:27:06 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * *-dep.c: Deleted definition of COFF_FORMAT if AOUTHDR was
+       defined since 1) We *may* (recent mail message) want to define
+       AOUTHDR under a basically BSD system, and 2) AOUTHDR is sometimes
+       a typedef in coff encapsulation setups.  Also removed #define's of
+       AOUTHDR if AOUTHDR is already defined (inside of coff format).  
+       * core.c, dbxread.c: Removed #define's of AOUTHDR if AOUTHDR is
+       already defined (inside of coff format).
+
+Tue Jan 31 12:56:01 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * GDB 3.1 released.
+
+       * values.c (modify_field): Changed test for endianness to assign
+       to integer and reference character (so that all bits would be
+       defined). 
+
+Mon Jan 30 11:41:21 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * news-dep.c: Deleted inclusion of fcntl.h; just duplicates stuff
+       found in sys/file.h.
+
+       * i386-dep.c: Included default definition of N_SET_MAGIC for
+       COFF_FORMAT.
+
+       * config.gdb: Added checks for several different operating
+       systems. 
+
+       * coffread.c (read_struct_type): Put in a flag variable so that
+       one could tell when you got to the end of a structure.
+
+       * sun3-dep.c (core_file_command): Changed #ifdef based on SUNOS4
+       to ifdef based on FPU.
+
+       * infrun.c (restore_inferior_status): Changed error message to
+       "unable to restore previously selected frame".
+
+       * dbxread.c (read_dbx_symtab): Used intermediate variable in error
+       message reporting a bad symbol type.  (scan_file_globals,
+       read_ofile_symtab, read_addl_syms): Data type of "type" changed to
+       unsigned char (which is what it is).
+       * i386-dep.c: Removed define of COFF_FORMAT if AOUTHDR is defined.
+       Removed define of a_magic to magic (taken care of by N_MAGIC).
+       (core_file_command): Zero'd core_aouthdr instead of setting magic
+       to zero.
+       * i386-pinsn.c: Changed jcxz == jCcxz in jump table.
+       (putop): Added a case for 'C'.
+       (OP_J): Added code to handle possible masking of PC value on
+       certain kinds of data.
+       m-i386gas.h: Moved COFF_ENCAPSULATE to before inclusion of
+       m-i386.h and defined NAMES_HAVE_UNDERSCORE.
+
+       * coffread.c (unrecrod_misc_function, read_coff_symtab): Added
+       symbol number on which error occured to error output.
+
+Fri Jan 27 11:55:04 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * Makefile: Removed init.c in make clean.  Removed it without -f
+       and with leading - in make ?gdb.
+
+Thu Jan 26 15:08:03 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       Changes to get it to work on gould NP1.
+       * dbxread.c (read_dbx_symtab): Included cases for N_NBDATA and
+       N_NBBSS.
+       (psymtab_to_symtab): Changed declaration of hdr to
+       DECLARE_FILE_HEADERS.  Changed access to use STRING_TABLE_SIZE and
+       SYMBOL_TABLE_SIZE.
+       * gld-pinsn.c (findframe): Added declaration of framechain() as
+       FRAME_ADDR. 
+
+       * coffread.c (read_coff_symtab): Avoided treating typedefs as
+       external symbol definitions.
+
+Wed Jan 25 14:45:43 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * Makefile: Removed reference to alloca.c.  If they need it, they
+       can pull alloca.o from the gnu-emacs directory.
+
+       * version.c, gdb.texinfo: Updated version to 3.1 (jumping the gun
+       a bit so that I won't forget when I release).
+
+       * m-sun2.h, m-sun2os2.h, m-sun3os4.h, config.gdb: Modified code so
+       that default includes new sun core, ptrace, and attach-detach.
+       Added defaults for sun 2 os 2.
+
+       Modifications to reset stack limit back to what it used to be just
+       before exec.  All mods inside of #ifdef SET_STACK_LIMIT_HUGE.
+       * main.c: Added global variable original_stack_limit.
+       (main): Set original_stack_limit to original stack limit.
+       * inflow.c: Added inclusion of necessary files and external
+       reference to original_stack_limit.
+       (create_inferior): Reset stack limit to original_stack_limit.
+
+       * dbxread.c (read_dbx_symtab): Killed PROFILE_SYMBOLS ifdef.
+
+       * sparc-dep.c (isabranch): Multiplied offset by 4 before adding it
+       to addr to get target.
+
+       * Makefile: Added definition of SHELL to Makefile.
+
+       * m-sun2os4.h: Added code to define NEW_SUN_PTRACE, NEW_SUN_CORE,
+       and ATTACH_DETACH.
+       * sun3-dep.c: Added code to avoid fp regs if we are on a sun2.
+
+Tue Jan 24 17:59:14 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (read_array_type): Added function.
+       (read_type): Added call to above instead of inline code.
+
+       * Makefile: Added ${GNU_MALLOC} to the list of dependencies for
+       the executables.
+
+Mon Jan 23 15:08:51 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * gdb.texinfo: Added paragraph to summary describing languages
+       with which gdb can be run.  Also added descriptions of the
+       "info-methods" and "add-file" commands.
+
+       * symseg.h: Commented a range type as having TYPE_TARGET_TYPE
+       pointing at the containing type for the range (often int).
+       * dbxread.c (read_range_type): Added code to do actual range types
+       if they are defined.  Assumed that the length of a range type is
+       the length of the target type; this is a lie, but will do until
+       somebody gets back to me as to what these silly dbx symbols mean.
+       
+       * dbxread.c (read_range_type): Added code to be more picky about
+       recognizing builtins as range types, to treat types defined as
+       subranges of themselves to be subranges of int, and to recognize
+       the char type idiom from dbx as a special case.
+
+Sun Jan 22 01:00:13 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-vax.h: Removed definition of FUNCTION_HAS_FRAME_POINTER.
+       * blockframe.c (get_prev_frame_info): Removed default definition
+       and use of above.  Instead conditionalized checking for leaf nodes
+       on FUNCTION_START_OFFSET (see comment in code).
+
+Sat Jan 21 16:59:19 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (read_range_type): Fixed assumption that integer was
+       always type 1.
+
+       * gdb.texinfo: Fixed spelling mistake and added a note in the
+       running section making it clear that users may invoke subroutines
+       directly from gdb.
+
+       * blockframe.c: Setup a default definition for the macro
+       FUNCTION_HAS_FRAME_POINTER.
+       (get_prev_frame_info): Used this macro instead of checking
+       SKIP_PROLOGUE directly.
+       * m-vax.h: Overroad definition; all functions on the vax have
+       frame pointers.
+
+Fri Jan 20 12:25:35 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * core.c: Added default definition of N_MAGIC for COFF_FORMAT.
+
+       * xgdb.c: Installed a fix to keep the thing from dying when there
+       isn't any frame selected.
+
+       * core.c: Made a change for the UMAX system; needs a different
+       file included if using that core format. 
+
+       * Makefile: Deleted duplicate obstack.h in dbxread.c dependency.
+
+       * munch: Modified (much simpler) to cover (I hope) all cases.
+
+       * utils.c (save_cleanups, restore_cleanups): Added functions to
+       allow you to push and pop the chain of cleanups to be done.
+       * defs.h: Declared the new functions.
+       * main.c (catch_errors): Made sure that the only cleanups which
+       would be done were the ones put on the chain *after* the current
+       location. 
+
+       * m-*.h (FRAME_CHAIN_VALID): Removed check on pc in the current
+       frame being valid.
+       * blockframe.c (get_prev_frame_info): Made the assumption that if
+       a frame's pc value was within the first object file (presumed to
+       be /lib/crt0.o), that we shouldn't go any higher.
+
+       * infrun.c (wait_for_inferior): Do *not* execute check for stop pc
+       at step_resume_break if we are proceeding over a breakpoint (ie.
+       if trap_expected != 0).
+
+       * Makefile: Added -g to LDFLAGS.
+
+       * m-news.h (POP_FRAME) Fixed typo.
+
+       * printcmd.c (print_frame_args): Modified to print out register
+       params in order by .stabs entry, not by register number.
+
+       * sparc-opcode.h: Changed declaration of (struct
+       arith_imm_fmt).simm to be signed (as per architecture manual).
+       * sparc-pinsn.c (fprint_addr1, print_insn): Forced a cast to an
+       int, so that we really would get signed behaivior (default for sun
+       cc is unsigned).
+
+       * i386-dep.c (i386_get_frame_setup): Replace function with new
+       function provided by pace to fix bug in recognizing prologue.
+
+Thu Jan 19 11:01:22 1989  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * infcmd.c (run_command): Changed error message to "Program not
+       restarted." 
+
+       * value.h: Changed "frame" field in value structure to be a
+       FRAME_ADDR (actually CORE_ADDR) so that it could survive across
+       calls. 
+
+       * m-sun.h (FRAME_FIND_SAVED_REGS): Fixed a typo.
+
+       * value.h: Added lval: "lval_reg_frame_relative" to indicate a
+       register that must be interpeted relative to a frame.  Added
+       single entry to value structure: "frame", used to indicate which
+       frame a relative regnum is relative to.
+       * findvar.c (value_from_register): Modified to correctly setup
+       these fields when needed.  Deleted section to fiddle with last
+       register copied on little endian machine; multi register
+       structures will always occupy an integral number of registers.
+       (find_saved_register): Made extern.
+       * values.c (allocate_value, allocate_repeat_value): Zero frame
+       field on creation.
+       * valops.c (value_assign): Added case for lval_reg_frame_relative;
+       copy value out, modify it, and copy it back.  Desclared
+       find_saved_register as being external.
+       * value.h: Removed addition of kludgy structure; thoroughly
+       commented file.
+       * values.c (free_value, free_all_values, clear_value_history,
+       set_internalvar, clear_internavars): Killed free_value.
+
+Wed Jan 18 20:09:39 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * value.h: Deleted struct partial_storage; left over from
+       yesterday. 
+
+       * findvar.c (value_from_register): Added code to create a value of
+       type lval_reg_partsaved if a value is in seperate registers and
+       saved in different places.
+
+Tue Jan 17 13:50:18 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * value.h: Added lval_reg_partsaved to enum lval_type and
+       commented enum lval_type.  Commented value structure.
+       Added "struct partial_register_saved" to value struct; added
+       macros to deal with structure to value.h.
+       * values.c (free_value): Created; special cases lval_reg_partsaved
+       (which has a pointer to an array which also needs to be free).
+       (free_all_values, clear_value_history, set_internalvar,
+       clear_internalvars): Modified to use free_values.
+
+       * m-sunos4.h: Changed name to sun3os4.h.
+       * m-sun2os4.h, m-sun4os4.h: Created.
+       * config.gdb: Added configuration entries for each of the above.
+       * Makefile: Added into correct lists.
+
+       * Makefile: Added dependencies on a.out.encap.h.  Made
+       a.out.encap.h dependent on a.out.gnu.h and dbxread.c dependent on
+       stab.gnu.h. 
+
+       * infrun.c, remote.c: Removed inclusion of any a.out.h files in
+       these files; they aren't needed.
+
+       * README: Added comment about bug reporting and comment about
+       xgdb. 
+
+       * Makefile: Added note to HPUX dependent section warning about
+       problems if compiled with gcc and mentioning the need to add
+       -Ihp-include to CFLAGS if you compile on those systems.  Added a
+       note about needing the GNU nm with compilers *of gdb* that use the
+       coff encapsulate feature also.  * hp-include: Made symbolic link
+       over to /gp/gnu/binutils.
+
+       * Makefile: Added TSOBS NTSOBS OBSTACK and REGEX to list of things
+       to delete in "make clean".  Also changed "squeakyclean" target as
+       "realclean". 
+
+       * findvar.c (value_from_register): Added assignment of VALUE_LVAL
+       to be lval_memory when that is appropriate (original code didn't
+       bother because it assumed that it was working with a pre lval
+       memoried value).
+
+       * expread.y (yylex): Changed to only return type THIS if the
+       symbol "$this" is defined in some block superior or equal to the
+       current expression context block.
+
+Mon Jan 16 13:56:44 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-*.h (FRAME_CHAIN_VALID): On machines which check the relation
+       of FRAME_SAVED_PC (thisframe) to first_object_file_end (all except
+       gould), make sure that the pc of the current frame also passes (in
+       case someone stops in _start).
+
+       * findvar.c (value_of_register): Changed error message in case of
+       no inferior or core file.
+
+       * infcmd.c (registers_info): Added a check for inferior or core
+       file; error message if not.
+
+       * main.c (gdb_read_line): Modified to take prompt as argument and
+       output it to stdout.
+       * infcmd.c (registers_info, signals_info), main.c (command_loop,
+       read_command_lines, copying_info), symtab.c (decode_line_2,
+       output_source_filename, MORE, list_symbols): Changed calling
+       convention used to call gdb_read_line.
+
+       * infcmd.c, infrun.c, main.c, symtab.c: Changed the name of the
+       function "read_line" to "gdb_read_line".
+       * breakpoint.c: Deleted external referenced to function
+       "read_line" (not needed by code).
+
+Fri Jan 13 12:22:05 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * i386-dep.c: Include a.out.encap.h if COFF_ENCAPSULATE.
+       (N_SET_MAGIC): Defined if not defined by include file.
+       (core_file_command): Used N_SET_MAGIC instead of assignment to
+       a_magic.
+       (exec_file_command): Stuck in a HEADER_SEEK_FD.
+
+       * config.gdb: Added i386-dep.c as depfile for i386gas choice.
+
+       * munch: Added -I. to cc to pick up things included by the param
+       file. 
+
+       * stab.gnu.def: Changed name to stab.def (stab.gnu.h needs this name).
+       * Makefile: Changed name here also.
+       * dbxread.c: Changed name of gnu-stab.h to stab.gnu.h.
+
+       * gnu-stab.h: Changed name to stab.gnu.h.
+       * stab.gnu.def: Added as link to binutils.
+       * Makefile: Put both in in the distribution.
+
+Thu Jan 12 11:33:49 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c: Made which stab.h is included dependent on
+       COFF_ENCAPSULATE; either <stab.h> or "gnu-stab.h".
+       * Makefile: Included gnu-stab.h in the list of files to include in
+       the distribution.
+       * gnu-stab.h: Made a link to /gp/gnu/binutils/stab.h
+
+       * Makefile: Included a.out.gnu.h and m-i386gas.h in list of
+       distribution files.
+       * m-i386gas.h: Changed to include m-i386.h and fiddle with it
+       instead of being a whole new file.
+       * a.out.gnu.h: Made a link to /gp/gnu/binutils/a.out.gnu.h.
+
+       Chris Hanson's changes to gdb for hp Unix.
+       * Makefile: Modified comments on hpux.
+       * hp9k320-dep.c: #define'd WOPR & moved inclusion of signal.h
+       * inflow.c: Moved around declaratiosn of <sys/fcntl.h> and
+       <sys/ioctl.h> inside of USG depends and deleted all SYSV ifdef's
+       (use USG instead).
+       * munch: Modified to accept any number of spaces between the T and
+       the symbol name.
+
+       Pace's changes to gdb to work with COFF_ENCAPSULATE (robotussin):
+       * config.gdb: Added i386gas to targets.
+       * default-dep.c: Include a.out.encap.h if COFF_ENCAPSULATE.
+       (N_SET_MAGIC): Defined if not defined by include file.
+       (core_file_command): Used N_SET_MAGIC instead of assignment to a_magic.
+       (exec_file_command): Stuck in a HEADER_SEEK_FD.
+       * infrun.c, remote.c: Added an include of a.out.encap.h if
+       COFF_ENCAPSULATE defined.  This is commented out in these two
+       files, I presume because the definitions aren't used.
+       * m-i386gas.h: Created.
+       * dbxread.c: Included defintions for USG.
+       (READ_FILE_HEADERS): Now uses HEADER_SEEK_FD if it exists.
+       (symbol_file_command): Deleted use of HEADER_SEEK_FD.
+       * core.c: Deleted extra definition of COFF_FORMAT.
+       (N_MAGIC): Defined to be a_magic if not already defined.
+       (validate_files): USed N_MAGIC instead of reading a_magic.
+
+Wed Jan 11 12:51:00 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * remote.c: Upped PBUFSIZ.
+       (getpkt): Added zeroing of c inside loop in case of error retry.
+
+       * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Removed
+       code to not put stuff with debugging symbols in the misc function
+       list.  Had been ifdef'd out.
+
+       * gdb.texinfo: Added the fact that the return value for a function
+       is printed if you use return.
+
+       * infrun.c (wait_for_inferior): Removed test in "Have we hit
+       step_resume_breakpoint" for sp values in proper orientation.  Was
+       in there for recursive calls in functions without frame pointers
+       and it was screwing up calls to alloca.  
+
+       * dbxread.c: Added #ifdef COFF_ENCAPSULATE to include
+       a.out.encap.h.
+       (symbol_file_command): Do HEADER_SEEK_FD when defined.
+       * dbxread.c, core.c: Deleted #ifdef ROBOTUSSIN stuff.
+       * robotussin.h: Deleted local copy (was symlink).
+       * a.out.encap.h: Created symlink to
+       /gp/gnu/binutils/a.out.encap.h.
+       * Makefile: Removed robotussin.h and included a.out.encap.h in
+       list of files.
+
+       * valprint.c (val_print, print_scalar_formatted): Changed default
+       precision of printing float value; now 6 for a float and 16 for a
+       double.
+
+       * findvar.c (value_from_register): Added code to deal with the
+       case where a value is spread over several registers.  Still don't
+       deal with the case when some registers are saved in memory and
+       some aren't.
+
+Tue Jan 10 17:04:04 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * xgdb.c (xgdb_create_window): Removed third arg (XtDepth) to
+       frameArgs.  
+
+       * infrun.c (handle_command): Error if signal number is less or
+       equal to 0 or greater or equal to NSIG or a signal number is not
+       provided.
+
+       * command.c (lookup_cmd): Modified to not convert command section
+       of command line to lower case in place (in case it isn't a
+       subcommand, but an argument to a command).
+
+Fri Jan  6 17:57:34 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c: Changed "text area" to "data area" in comments on
+       N_SETV. 
+
+Wed Jan  4 12:29:54 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c: Added definitions of gnu symbol types after inclusion
+       of a.out.h and stab.h.
+
+Mon Jan  2 20:38:31 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * eval.c (evaluate_subexp): Binary logical operations needed to
+       know type to determine whether second value should be evaluated.
+       Modified to discover type before binup_user_defined_p branch.
+       Also commented "enum noside".
+
+       * Makefile: Changed invocations of munch to be "./munch".
+
+       * gdb.texinfo: Updated to refer to current version of gdb with
+       January 1989 last update.
+
+       * coffread.c (end_symtab): Zero context stack when finishing
+       lexical contexts.
+       (read_coff_symtab): error if context stack 0 in ".ef" else case.
+
+       * m-*.h (FRAME_SAVED_PC): Changed name of argument from "frame" to
+       "FRAME" to avoid problems with replacement of "->frame" part of
+       macro. 
+
+       * i386-dep.c (i386_get_frame_setup): Added codestream_get() to
+       move codestream pointer up to the correct location in "subl $X,
+       %esp" case.
+
+Sun Jan  1 14:24:35 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * valprint.c (val_print): Rewrote routine to print string pointed
+       to by char pointer; was producing incorrect results when print_max
+       was 0.
+
+Fri Dec 30 12:13:35 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Put
+       everything on the misc function list.
+
+       * Checkpointed distribution.
+
+       * Makefile: Added expread.tab.c to the list of things slated for
+       distribution. 
+
+Thu Dec 29 10:06:41 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * stack.c (set_backtrace_limit_command, backtrace_limit_info,
+       bactrace_command, _initialize_stack): Removed modifications for
+       limit on backtrace.  Piping the backtrace through an interuptable
+       "more" emulation is a better way to do it.
+
+Wed Dec 28 11:43:09 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * stack.c
+       (set_backtrace_limit_command): Added command to set a limit to the
+       number of frames for a backtrace to print by default.
+       (backtrace_limit_info): To print the current limit.
+       (backtrace_command): To use the limit.
+       (_initialize_stack): To initialize the limit to its default value
+       (30), and add the set and info commands onto the appropriate
+       command lists.
+
+       * gdb.texinfo: Documented changes to "backtrace" and "commands"
+       commands.
+
+       * stack.c (backtrace_command): Altered so that a negative argument
+       would show the last few frames on the stack instead of the first
+       few.
+       (_initialize_stack): Modified help documentation.
+
+       * breakpoint.c (commands_command): Altered so that "commands" with
+       no argument would refer to the last breakpoint set.
+       (_initialize_breakpoint): Modified help documentation.
+
+       * infrun.c (wait_for_inferior): Removed ifdef on Sun4; now you can
+       single step through compiler generated sub calls and will die if
+       you next off of the end of a function.
+
+       * sparc-dep.c (single_step): Fixed typo; "break_insn" ==> "sizeof
+       break_insn". 
+
+       * m-sparc.h (INIT_EXTRA_FRAME_INFO): Set the bottom of a stack
+       frame to be the bottom of the stack frame inner from this, if that
+       inner one is a leaf node.
+
+       * dbxread.c (read_dbx_symtab): Check to make sure we don't add a
+       psymtab to it's own dependency list.
+
+       * dbxread.c (read_dbx_symtab): Modified check for duplicate
+       dependencies to catch them correctly.
+
+Tue Dec 27 17:02:09 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-*.h (FRAME_SAVED_PC): Modified macro to take frame info
+       pointer as argument.
+       * stack.c (frame_info), blockframe.c (get_prev_frame_info),
+       gld-pinsn.c (findframe), m-*.h (SAVED_PC_AFTER_CALL,
+       FRAME_CHAIN_VALID, FRAME_NUM_ARGS): Changed usage of macros to
+       conform to above.
+       * m-sparc.h (FRAME_SAVED_PC), sparc-dep.c (frame_saved_pc):
+       Changed frame_saved_pc to have a frame info pointer as an
+       argument. 
+
+       * m-vax.h, m-umax.h, m-npl.h, infrun.c (wait_for_inferior),
+       blockframe.c (get_prev_frame_info): Modified SAVED_PC_AFTER_CALL
+       to take a frame info pointer as an argument.
+
+       * blockframe.c (get_prev_frame_info): Altered the use of the
+       macros FRAME_CHAIN, FRAME_CHAIN_VALID, and FRAME_CHAIN_COMBINE to
+       use frame info pointers as arguments instead of frame addresses.
+       * m-vax.h, m-umax.h, m-sun3.h, m-sun3.h, m-sparc.h, m-pn.h,
+       m-npl.h, m-news.h, m-merlin.h, m-isi.h, m-hp9k320.h, m-i386.h:
+       Modified definitions of the above macros to suit.
+       * m-pn.h, m-npl.h, gould-dep.c (findframe): Modified findframe to
+       use a frame info argument; also fixed internals (wouldn't work
+       before).
+
+       * m-sparc.h: Cosmetic changes; reordered some macros and made sure
+       that nothing went over 80 lines.
+
+Thu Dec 22 11:49:15 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * Version 3.0 released.
+
+       * README: Deleted note about changing -lobstack to obstack.o.
+
+Wed Dec 21 11:12:47 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-vax.h (SKIP_PROLOGUE): Now recognizes gcc prologue also.
+
+       * blockframe.c (get_prev_frame_info): Added FUNCTION_START_OFFSET
+       to result of get_pc_function_start.
+       * infrun.c (wait_for_inferior): Same.
+
+       * gdb.texinfo: Documented new "step" and "next" behavior in
+       functions without line number information.
+
+Tue Dec 20 18:00:45 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * infcmd.c (step_1): Changed behavior of "step" or "next" in a
+       function witout line number information.  It now sets the step
+       range around the function (to single step out of it) using the
+       misc function vector, warns the user, and continues.
+
+       * symtab.c (find_pc_line): Zero "end" subsection of returned
+       symtab_and_line if no symtab found.
+
+Mon Dec 19 17:44:35 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * i386-pinsn.c (OP_REG): Added code from pace to streamline
+       disassembly and corrected types.
+       * i386-dep.c
+       (i386_follow_jump): Code added to follow byte and word offset
+       branches.
+       (i386_get_frame_setup): Expanded to deal with more wide ranging
+       function prologue.
+       (i386_frame_find_saved_regs, i386_skip_prologue): Changed to use
+       i386_get_frame_setup. 
+       
+
+Sun Dec 18 11:15:03 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-sparc.h: Deleted definition of SUN4_COMPILER_BUG; was designed
+       to avoid something that I consider a bug in our code, not theirs,
+       and which I fixed earlier.  Also deleted definition of
+       CANNOT_USE_ARBITRARY_FRAME; no longer used anywhere.
+       FRAME_SPECIFICATION_DYADIC used instead.
+
+       * infrun.c (wait_for_inferior): On the sun 4, if a function
+       doesn't have a prologue, a next over it single steps into it.
+       This gets around the problem of a "call .stret4" at the end of
+       functions returning structures.
+       * m-sparc.h: Defined SUN4_COMPILER_FEATURE.
+
+       * main.c (copying_info): Seperated the last printf into two
+       printfs.  The 386 compiler will now handle it.
+
+       * i386-pinsn.c, i386-dep.c: Moved print_387_control_word,
+       print_387_status_word, print_387_status, and i386_float_info to
+       dep.c  Also included reg.h in dep.c.
+
+Sat Dec 17 15:31:38 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * main.c (source_command): Don't close instream if it's null
+       (indicating execution of a user-defined command).
+                (execute_command): Set instream to null before executing
+                commands and setup clean stuff to put it back on error.
+
+       * inflow.c (terminal_inferior): Went back to not checking the
+       ioctl returns; there are some systems when this will simply fail.
+       It seems that, on most of these systems, nothing bad will happen
+       by that failure.
+
+       * values.c (value_static_field): Fixed dereferencing of null
+       pointer. 
+
+       * i386-dep.c (i386_follow_jump): Modified to deal with
+       unconditional byte offsets also.
+
+       * dbxread.c (read_type): Fixed typo in function type case of switch.
+
+       * infcmd.c (run_command): Does not prompt to restart if command is
+       not from a tty.
+
+Fri Dec 16 15:21:58 1988  Randy Smith  (randy at calvin)
+
+       * gdb.texinfo: Added a third option under the "Cannot Insert
+       Breakpoints" workarounds.
+
+       * printcmd.c (display_command): Don't do the display unless there
+       is an active inferior; only set it.
+
+       * findvar.c (value_of_register): Added an error check for calling
+       this when the inferior isn't active and a core file isn't being
+       read. 
+
+       * config.gdb: Added reminder about modifying REGEX in the
+       makefile for the 386.
+
+       * i386-pinsn.c, i386-dep.c: Moved m-i386.h helper functions over
+       to i386-dep.c.b
+
+Thu Dec 15 14:04:25 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * README: Added a couple of notes about compiling gdb with itself.
+
+       * breakpoint.c (set_momentary_breakpoint): Only takes FRAME_FP of
+       frame if frame is non-zero.
+
+       * printcmd.c (print_scalar_formatted): Implemented /g size for
+       hexadecimal format on machines without an 8 byte integer type.  It
+       seems to be non-trivial to implement /g for other formats.
+       (decode_format): Allowed hexadecimal format to make it through /g
+       fileter. 
+
+Wed Dec 14 13:27:04 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * expread.y: Converted all calls to write_exp_elt from the parser
+       to calls to one of write_exp_elt_{opcode, sym, longcst, dblcst,
+       char, type, intern}.  Created all of these routines.  This gets
+       around possible problems in passing one of these things in one ear
+       and getting something different out the other.  Eliminated
+       SUN4_COMPILER_BUG ifdef's; they are now superfluous.
+
+       * symmisc.c (free_all_psymtabs): Reinited partial_symtab_list to 0.
+                   (_initialize_symmisc): Initialized both symtab_list and
+                   partial_symtab_list.
+
+       * dbxread.c (start_psymtab): Didn't allocate anything on
+       dependency list.
+       (end_psymtab): Allocate dependency list on psymbol obstack from
+       local list.
+       (add_psymtab_dependency): Deleted.
+       (read_dbx_symtab): Put dependency on local list if it isn't on it
+       already.
+
+       * symtab.c: Added definition of psymbol_obstack.
+       * symtab.h: Added declaration of psymbol_obstack.
+       * symmisc.c (free_all_psymtabs): Added freeing and
+       reinitionaliztion of psymbol_obstack.
+       * dbxread.c (free_all_psymbols): Deleted.
+                   (start_psymtab, end_psymtab,
+                   process_symbol_for_psymtab):  Changed most allocation
+                   of partial symbol stuff to be off of psymbol_obstack.
+
+       * symmisc.c (free_psymtab, free_all_psymtabs): Deleted
+       free_psymtab subroutine.
+
+       * symtab.h: Removed num_includes and includes from partial_symtab
+       structure; no longer needed now that all include files have their
+       own psymtab.
+       * dbxread.c (start_psymtab): Eliminated initialization of above.
+                   (end_psymtab): Eliminated finalization of above; get
+                   includes from seperate list.
+                   (read_dbx_symtab): Moved includes from psymtab list to
+                   their own list; included in call to end_psymtab.
+       * symmisc.c (free_psymtab): Don't free includes.
+
+Tue Dec 13 14:48:14 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * i386-pinsn.c: Reformatted entire file to correspond to gnu
+       software indentation conventions.
+
+       * sparc-dep.c (skip_prologue): Added capability of recognizign
+       stores of input register parameters into stack slots. 
+
+       * sparc-dep.c: Added an include of sparc-opcode.h.
+       * sparc-pinsn.c, sparc-opcode.h: Moved insn_fmt structures and
+       unions from pinsn.c to opcode.h.
+       * sparc-pinsn.c, sparc-dep.c (isabranch, skip_prologue): Moved
+       this function from pinsn.c to dep.c.
+
+       * Makefile: Put in warnings about compiling with gcc (non-ansi
+       include files) and compiling with shared libs on Sunos 4.0 (can't
+       debug something that's been compiled that way).
+
+       * sparc-pinsn.c: Put in a completely new file (provided by
+       Tiemann) to handle floating point disassembly, load and store
+       instructions, and etc. better.  Made the modifications this file
+       (ChangeLog) list for sparc-pinsn.c again.
+
+       * symtab.c (output_source_filename): Included "more" emulation hack.
+
+       * symtab.c (output_source_filename): Initialized COLUMN to 0.
+                  (sources_info): Modified to not print out a line for
+                  all of the include files within a partial symtab (since
+                  they have pst's of their own now).  Also modified to
+                  make a distinction between those pst's read in and
+                  those not.
+
+       * infrun.c: Included void declaration of single_step() if it's
+       going to be used.
+       * sparc-dep.c (single_step): Moved function previous to use of it.
+
+       * Makefile: Took removal of expread.tab.c out of make clean entry
+       and put it into a new "squeakyclean" entry.
+
+Mon Dec 12 13:21:02 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * sparc-pinsn.c (skip_prologue): Changed a struct insn_fmt to a
+       union insn_fmt.
+
+       * inflow.c (terminal_inferior): Checked *all* return codes from
+       ioctl's and fcntl's in routine.
+
+       * inflow.c (terminal_inferior): Added check for sucess of
+       TIOCSPGRP ioctl call.  Just notifies if bad.
+
+       * dbxread.c (symbol_file_command): Close was getting called twice;
+       once directly and once through cleanup.  Killed the direct call.  
+
+Sun Dec 11 19:40:40 1988  & Smith  (randy at hobbes.ai.mit.edu)
+
+       * valprint.c (val_print): Deleted spurious printing of "=" from
+       TYPE_CODE_REF case.
+
+Sat Dec 10 16:41:07 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c: Changed allocation of psymbols from using malloc and
+       realloc to using obstacks.  This means they aren't realloc'd out
+       from under the pointers to them.
+
+Fri Dec  9 10:33:24 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * sparc-dep.c inflow.c core.c expread.y command.c infrun.c
+       infcmd.c dbxread.c symmisc.c symtab.c printcmd.c valprint.c
+       values.c source.c stack.c findvar.c breakpoint.c blockframe.c
+       main.c: Various cleanups inspired by "gcc -Wall" (without checking
+       for implicit declarations).
+
+       * Makefile: Cleaned up some more.
+
+       * valops.c, m-*.h (FIX_CALL_DUMMY): Modified to take 5 arguments
+       as per what sparc needs (programming for a superset of needed
+       args).
+
+       * dbxread.c (process_symbol_for_psymtab): Modified to be slightly
+       more picky about what it puts on the list of things *not* to be
+       put on the misc function list.  When/if I shift everything over to
+       being placed on the misc_function_list, this will go away.
+
+       * inferior.h, infrun.c: Added fields to save in inferior_status
+       structure. 
+
+       * maketarfile: Deleted; functionality is in Makefile now.
+
+       * infrun.c (wait_for_inferior): Modified algorithm for determining
+       whether or not a single-step was through a subroutine call.  See
+       comments at top of file.
+
+       * dbxread.c (read_dbx_symtab): Made sure that the IGNORE_SYMBOL
+       macro would be checked during initial readin.
+
+       * dbxread.c (read_ofile_symtab): Added macro GCC_COMPILED_FLAG_SYMBOL
+       into dbxread.c to indicate what string in a local text symbol will
+       indicate a file compiled with gcc.  Defaults to "gcc_compiled.".
+
+Thu Dec  8 11:46:22 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-sparc.h (FRAME_FIND_SAVED_REGS): Cleaned up a little to take
+       advantage of the new frame cache system.
+
+       * inferior.h, infrun.c, valops.c, valops.c, infcmd.c:  Changed
+       mechanism to save inferior status over calls to inferior (eg.
+       call_function); implemented save_inferior_info and
+       restore_inferior_info.
+
+       * blockframe.c (get_prev_frame): Simplified this by a direct call
+       to get_prev_frame_info.
+
+       * frame.h, stack.c, printcmd.c, m-sparc.h, sparc-dep.c: Removed
+       all uses of frame_id_from_addr.  There are short routines like it
+       still in frame_saved_pc (m-sparc.h) and parse_frame_spec
+       (stack.c).  Eventually the one in frame_saved_pc will go away.
+
+       * infcmd.c, sparc-dep.c: Implemented a new mechanism for
+       re-selecting the selected frame on return from a call.
+
+       * blockframe.c, stack.c, findvar.c, printcmd.c, m-*.h:  Changed
+       all routines and macros that took a "struct frame_info" as an
+       argument to take a "struct frame_info *".  Routines: findarg,
+       framechain, print_frame_args, FRAME_ARGS_ADDRESS,
+       FRAME_STRUCT_ARGS_ADDRESS, FRAME_LOCALS_ADDRESS, FRAME_NUM_ARGS,
+       FRAME_FIND_SAVED_REGS.
+
+       * frame.h, stack.c, printcmd.c, infcmd.c, findvar.c, breakpoint.c,
+       blockframe.c, xgdb.c, i386-pinsn.c, gld-pinsn.c, m-umax.h,
+       m-sun2.h, m-sun3.h, m-sparc.h, m-pn.h, m-npl.h, m-news.h,
+       m-merlin.h, m-isi.h, m-i386.h, m-hp9k320.h:  Changed routines to
+       use "struct frame_info *" internally.
+
+Wed Dec  7 12:07:54 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * frame.h, blockframe.c, m-sparc.h, sparc-dep.c: Changed all calls
+       to get_[prev_]frame_cache_item to get_[prev_]frame_info.
+
+       * blockframe.c: Elminated get_frame_cache_item and
+       get_prev_frame_cache_item; functionality now taken care of by
+       get_frame_info and get_prev_frame_info.
+
+       * blockframe.c: Put allocation on an obstack and eliminated fancy
+       reallocation routines, several variables, and various nasty
+       things. 
+
+       * frame.h, stack.c, infrun.c, blockframe.c, sparc-dep.c: Changed
+       type FRAME to be a typedef to "struct frame_info *".  Had to also
+       change routines that returned frame id's to return the pointer
+       instead of the cache index.
+
+       * infcmd.c (finish_command): Used proper method of getting from
+       function symbol to start of function.  Was treating a symbol as a
+       value. 
+
+       * blockframe.c, breakpoint.c, findvar.c, infcmd.c, stack.c,
+       xgdb.c, i386-pinsn.c, frame.h, m-hp9k320.h, m-i386.h, m-isi.h,
+       m-merlin.h, m-news.h, m-npl.h, m-pn.h, m-sparc.h, m-sun2.h,
+       m-sun3.h, m-umax.h: Changed get_frame_info and get_prev_frame_info
+       to return pointers instead of structures.
+
+       * blockframe.c (get_pc_function_start): Modified to go to misc
+       function table instead of bombing if pc was in a block without a
+       containing function.
+
+       * coffread.c: Dup'd descriptor passed to read_coff_symtab and
+       fdopen'd it so that there wouldn't be multiple closes on the same
+       fd.  Also put (fclose, stream) on the cleanup list.
+
+       * printcmd.c, stack.c: Changed print_frame_args to take a
+       frame_info struct as argument instead of the address of the args
+       to the frame.
+
+       * m-i386.h (STORE_STRUCT_RETURN): Decremented sp by sizeof object
+       to store (an address) rather than 1.
+
+       * dbxread.c (read_dbx_symtab): Set first_object_file_end in
+       read_dbx_symtab (oops).
+
+       * coffread.c (fill_in_vptr_fieldno): Rewrote TYPE_BASECLASS as
+       necessary. 
+
+Tue Dec  6 13:03:43 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * coffread.c: Added fake support for partial_symtabs to allow
+       compilation and execution without there use.
+       * inflow.c: Added a couple of minor USG mods.
+       * munch: Put in appropriate conditionals so that it would work on
+       USG systems.
+       * Makefile: Made regex.* handled same as obstack.*; made sure tar
+       file included everything I wanted it to include (including
+       malloc.c).
+
+       * dbxread.c (end_psymtab): Create an entry in the
+       partial_symtab_list for each subfile of the .o file just read in.
+       This allows a "list expread.y:10" to work when we haven't read in
+       expread.o's symbol stuff yet.
+
+       * symtab.h, dbxread.c (psymtab_to_symtab): Recognize pst->ldsymlen
+       == 0 as indicating a dummy psymtab, only in existence to cause the
+       dependency list to be read in.
+
+       * dbxread.c (sort_symtab_syms): Elminated reversal of symbols to
+       make sure that register debug symbol decls always come before
+       parameter symbols.  After mod below, this is not needed.
+
+       * symtab.c (lookup_block_symbol): Take parameter type symbols
+       (LOC_ARG or LOC_REGPARM) after any other symbols which match.
+
+       * dbxread.c (read_type): When defining a type in terms of some
+       other type and the other type is supposed to have a pointer back
+       to this specific kind of type (pointer, reference, or function),
+       check to see if *that* type has been created yet.  If it has, use
+       it and fill in the appropriate slot with a pointer to it.
+
+Mon Dec  5 11:25:04 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * symmisc.c: Eliminated existence of free_inclink_symtabs and
+       init_free_inclink_symtabs; they aren't called from anywhere, and
+       if they were they could disrupt gdb's data structure badly
+       (elimination of struct type's which values that stick around past
+       elimination of inclink symtabs).
+
+       * dbxread.c (symbol_file_command): Fixed a return pathway out of
+       the routine to do_cleanups before it left.
+
+       * infcmd.c (set_environment_command), gdb.texinfo: Added
+       capability to set environmental variable values to null.
+
+       * gdb.texinfo: Modified doc on "break" without args slightly.
+
+Sun Dec  4 17:03:16 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c (symbol_file_command): Added check; if there weren't
+       any debugging symbols in the file just read, the user is warned.
+
+       * infcmd.c: Commented set_environment_command (a little).
+
+       * createtags: Cleaned up and commented.
+
+       * Makefile: Updated depen_memory and write_inferior_memory in that errno is
+       checked after each ptrace and returned to the caller.  Used in
+       value_at to detect references to addresses which are out of
+       bounds.  Also core.c (xfer_core_file): return 1 if invalid
+       address, 0 otherwise.
+
+       * inflow.c, <machine>-infdep.c: removed all calls to ptrace from
+       inflo, m-sun3.h:  Cleaned up dealings with
+       functions returning structu0 19:19:36 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * symmisc.c: (read_symsegs) Accept only format number 2.  Since
+       the size of the type structure changed when C++ support was added,
+       format 1 can no longer be used.
+
+       * core.c, m-sunos4.h: (core_file_command) support for SunOS 4.0.
+       Slight change in the core structure.  #ifdef SUNOS4.  New file
+       m-sunos4.h.  May want to change config.gdb also.
+
+Fri Jul  8 19:59:49 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * breakpoint.c: (break_command_1) Allow `break if condition'
+       rather than parsing `if' as a function name and returning an
+       error.
+
+Thu Jul  7 22:22:47 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * C++: valops.c, valprint.c, value.h, values.c: merged code to deal
+       with C++ expressions.
+
+Wed Jul  6 03:28:18 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+        * C++: dbxread.c: (read_dbx_symtab, condense_misc_bunches,
+       add_file_command)  Merged code to read symbol information from
+       an incrementally linked file.  symmisc.c:
+       (init_free_inclink_symtabs, free_inclink_symtabs) Cleanup
+       routines.
+
+Tue Jul  5 02:50:41 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * C++: symtab.c, breakpoint.c, source.c:  Merged code to deal with
+       ambiguous line specifications.  In C++ one can have overloaded
+       function names, so that `list classname::overloadedfuncname'
+       refers to several different lines, possibly  sure currently configured machine
+       dependent files come first in e at corn-chex.ai.mit.edu)
+
+       * C++: symtab.c: replaced lookup_symtab_1 and lookup_symtab_2 with
+       a modified lookup_symbol which checks for fields of the current
+       implied argument `this'.  printcmd.c, source.c, symtab.c,
+       valops.c: Need to change callers once callers are
+       installed. 
+
+Wed Jun 29 01:26:56 1988  Peter TerMaat  (pete at frosted-flakes.ai.mit.edu)
+
+       * C++: eval.c, expprint.c, expread.y, expression.h, valarith.c, 
+       Merged code to deal with evaluation of user-defined operators,
+       member functions, and virtual functions.
+       binop_must_be_user_defined tests for user-defined binops, 
+       value_x_binop calls the appropriate operator function. 
+
+Tue Jun 28 02:56:42 1988  Peter TerMaat  (pete at frosted-flakes.ai.mit.edu)
+
+       * C++: Makefile: changed the echo: expect 101 shift/reduce conflicts 
+       and 1 reduce/reduce conflict.
+
+\f
+Local Variables:
+mode: indented-text
+eval: (auto-fill-mode 1)
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
+\0ng destructors and
+               constructors, and flags being defined via public and via
+               virtual paths.  Added fields NEXT_VARIANT, N_BASECLASSES,
+               and BASECLASSES to this type (tr: Changed types from
+               having to be derived from a single baseclass to a multiple
+               base class).
+       * symtab.h: Added macros to access new fields defined in symseg.h.
+               Added decl for lookup_basetype_type.
+       * dbxread.c 
+       (condense_addl_misc_bunches): Function added to condense the misc
+               function bunches added by reading in a new .o file.
+       (read_addl_syms): Function added to read in symbols
+               from a new .o file (incremental linking).
+       (add_file_command): Command interface function to indicate
+               incrmental linking of a new .o file; this now calls
+               read_addl_syms and condense_addl_misc_bunches.
+       (define_symbol): Modified code to handle types defined from base
+               types which were not known when the derived class was
+               output.
+       (read_struct_type): Modified to better handle description of
+               struct types as derived types.  Possibly derived from
+               several different base classes.  Also added new code to
+               mark definitions via virtual paths or via public paths.
+               Killed seperate code to handle classes with destructors
+               but without constructors and improved marking of classes
+               as having destructors and constructors.
+       * infcmd.c: Modified call to val_print (one more argument).
+       * symtab.c (lookup_member_type): Modified to deal with new
+               structure in symseg.h.
+       (lookup_basetype_type): Function added to find or construct a type
+               ?derived? from the given type.
+       (decode_line_1): Modified to deal with new type data structures.
+               Modified to deal with new number of args for
+               decode_line_2.
+       (decode_line_2): Changed number of args (?why?).
+       (init_type): Added inits for new C++ fields from
+               symseg.h.
+       *valarith.c
+       (value_x_binop, value_binop): Added cases for BINOP_MIN &
+               BINOP_MAX.
+       * valops.c
+       (value_struct_elt, check_field, value_struct_elt_for_address):
+               Changed to deal with multiple possible baseclasses.
+       (value_of_this): Made SELECTED_FRAME an extern variable.
+       * valprint.c
+       (val_print): Added an argument DEREF_REF to dereference references
+               automatically, instead of printing them like pointers.
+               Changed number of arguments in recursive calls to itself.
+               Changed to deal with varibale numbers of base classes.
+       (value_print): Changed number of arguments to val_print.  Print
+               type of value also if value is a reference.
+       (type_print_derivation_info): Added function to print out
+               derivation info a a type.
+       (type_print_base): Modified to use type_print_derivation_info and
+               to handle multiple baseclasses.
+       
+Mon Nov 21 10:32:07 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * inflow.c (term_status_command): Add trailing newline to output. 
+
+       * sparc-dep.c (do_save_insn, do_restore_insn): Saved
+       "stop_registers" over the call for the sake of normal_stop and
+       run_stack_dummy.
+
+       * m-sparc.h (EXTRACT_RETURN_VALUE): Put in parenthesis to force
+       addition of 8 to the int pointer, not the char pointer.
+
+       * sparc-pinsn.c (print_addr1): Believe that I have gotten the
+       syntax right for loads and stores as adb does it.
+
+       * symtab.c (list_symbols): Turned search for match on rexegp into
+       a single loop.
+
+       * dbxread.c (psymtab_to_symtab): Don't read it in if it's already
+       been read in.
+
+       * dbxread.c (psymtab_to_symtab): Changed error to fatal in
+       psymtab_to_symtab. 
+
+       * expread.y (parse_number): Fixed bug which treated 'l' at end of
+       number as '0'.
+
+Fri Nov 18 13:57:33 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Was
+       being foolish and using pointers into an array I could realloc.
+       Converted these pointers into integers.
+
+Wed Nov 16 11:43:10 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-sparc.h (POP_FRAME): Made the new frame be PC_ADJUST of the
+       old frame.
+
+       * i386-pinsn.c, m-hp9k320.h, m-isi.h, m-merlin.h, m-news.h,
+       m-npl.h, m-pn.h, m-sparc.h, m-sun2.h, m-sun3.h, m-umax.h, m-vax.h:
+       Modified POP_FRAME to use the current frame instead of
+       read_register (FP_REGNUM) and to flush_cached_frames before
+       setting the current frame.  Also added a call to set the current
+       frame in those POP_FRAMEs that didn't have it.
+
+       * infrun.c (wait_for_inferior): Moved call to set_current_frame up
+       to guarrantee that the current frame will always be set when a
+       POP_FRAME is done.  
+
+       * infrun.c (normal_stop): Added something to reset the pc of the
+       current frame (was incorrect because of DECR_PC_AFTER_BREAK).
+
+       * valprint.c (val_print): Changed to check to see if a string was
+       out of bounds when being printed and to indicate this if so.
+
+       * convex-dep.c (read_inferior_memory): Changed to return the value
+       of errno if the call failed (which will be 0 if the call
+       suceeded). 
+
+Tue Nov 15 10:17:15 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * infrun.c (wait_for_inferior): Two changes: 1) Added code to
+       not trigger the step breakpoint on recursive calls to functions
+       without frame info, and 2) Added calls to distinguish recursive
+       calls within a function without a frame (which next/nexti might
+       wish to step over) from jumps to the beginning of a function
+       (which it generally doesn't).
+
+       * m-sparc.h (INIT_EXTRA_FRAME_INFO): Bottom set correctly for leaf
+       parents. 
+
+       * blockframe.c (get_prev_frame_cache_item): Put in mod to check
+       for a leaf node (by presence or lack of function prologue).  If
+       there is a leaf node, it is assumed that SAVED_PC_AFTER_CALL is
+       valid.  Otherwise, FRAME_SAVED_PC or read_pc is used.
+
+       * blockframe.c, frame.h: Did final deletion of unused routines and
+       commented problems with getting a pointer into the frame cache in
+       the frame_info structure comment.
+
+       * blockframe.c, frame.h, stack.c: Killed use of
+       frame_id_from_frame_info; used frame_id_from_addr instead.
+
+       * blockframe.c, frame.h, stack.c, others (oops): Combined stack
+       cache and frame info structures.
+
+       * blockframe.c, sparc-dep.c, stack.c: Created the function
+       create_new_frame and used it in place of bad calls to
+       frame_id_from_addr. 
+
+       * blockframe.c, inflow.c, infrun.c, i386-pinsn.c, m-hp9k320.h,
+       m-npl.h, m-pn.h, m-sparc.h, m-sun3.h, m-vax.h, default-dep.c,
+       convex-dep.c, gould-dep.c, hp9k320-dep.c, news-dep.c, sparc-dep.c,
+       sun3-dep.c, umax-dep.c: Killed use of
+       set_current_Frame_by_address.  Used set_current_frame
+       (create_new_frame...) instead.
+
+       * frame.h: Killed use of FRAME_FP_ID.
+
+       * infrun.c, blockframe.c: Killed select_frame_by_address.  Used
+       select_frame (get_current_frame (), 0) (which was correct in all
+       cases that we need to worry about.
+
+Mon Nov 14 14:19:32 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * frame.h, blockframe.c, stack.c, m-sparc.h, sparc-dep.c: Added
+       mechanisms to deal with possible specification of frames
+       dyadically. 
+
+Sun Nov 13 16:03:32 1988  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
+
+       * ns32k-opcode.h: Add insns acbw, acbd.
+
+Sun Nov 13 15:09:58 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * breakpoint.c: Changed breakpoint structure to use the address of
+       a given frame (constant across inferior runs) as the criteria for
+       stopping instead of the frame ident (which varies across inferior
+       calls). 
+
+Fri Nov 11 13:00:22 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * gld-pinsn.c (findframe): Modified to work with the new frame
+       id's.  Actually, it looks as if this routine should be called with
+       an address anyway.
+
+       * findvar.c (find_saved_register): Altered bactrace loop to work
+       off of frames and not frame infos.
+
+       * frame.h, blockframe.c, stack.c, sparc-dep.c, m-sparc.h: Changed
+       FRAME from being the address of the frame to being a simple ident
+       which is an index into the frame_cache_item list.
+       * convex-dep.c, default-dep.c, gould-dep.c, hp9k320-dep.c,
+       i386-pinsn.c, inflow.c, infrun.c, news-dep.c, sparc-dep.c,
+       sun3-dep.c, umax-dep.c, m-hp9k320.h, m-npl.h, m-pn.h, m-sparc.h,
+       m-sun3.h, m-vax.h: Changed calls of the form set_current_frame
+       (read_register (FP_REGNUM)) to set_current_frame_by_address (...). 
+
+Thu Nov 10 16:57:57 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * frame.h, blockframe.c, gld-pinsn.c, sparc-dep.c, stack.c,
+       infrun.c, findvar.c, m-sparc.h: Changed the FRAME type to be
+       purely an identifier, using FRAME_FP and FRAME_FP_ID to convert
+       back and forth between the two.  The identifier is *currently*
+       still the frame pointer value for that frame.
+
+Wed Nov  9 17:28:14 1988  Chris Hanson  (cph at kleph)
+
+       * m-hp9k320.h (FP_REGISTER_ADDR): Redefine this to return
+       difference between address of given FP register, and beginning of
+       `struct user' that it occurs in.
+
+       * hp9k320-dep.c (core_file_command): Fix sign error in size
+       argument to myread.  Change buffer argument to pointer; was
+       copying entire structure.
+       (fetch_inferior_registers, store_inferior_registers): Replace
+       occurrences of `FP_REGISTER_ADDR_DIFF' with `FP_REGISTER_ADDR'.
+       Flush former definition.
+
+Wed Nov  9 12:11:37 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * xgdb.c: Killed include of initialize.h.
+
+       * Pulled in xgdb.c from the net.
+
+       * Checkpointed distribution (to provide to 3b2 guy).
+
+       * coffread.c, dbxread.c, symmisc.c, symtab.c, symseg.h: Changed
+       format of table of line number--pc mapping information.  Can
+       handle negative pc's now.
+
+       * command.c: Deleted local copy of savestring; code in utils.c is
+       identical. 
+
+Tue Nov  8 11:12:16 1988  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * gdb.texinfo: Added documentation for shell escape.
+
+Mon Nov  7 12:27:16 1988  Randall Smith  (randy at sugar-bombs.ai.mit.edu)
+
+       * command.c: Added commands for shell escape.
+
+       * core.c, dbxread.c: Added ROBOTUSSIN mods.
+
+       * Checkpointed distribution.
+
+       * printcmd.c (x_command): Yanked error if there is no memory to
+       examine (could be looking at executable straight).
+
+       * sparc-pinsn.c (print_insn): Amount to leftshift sethi imm by is
+       now 10 (matches adb in output).
+
+       * printcmd.c (x_command): Don't attempt to set $_ & $__ if there
+       is no last_examine_value (can happen if you did an x/0).
+
+Fri Nov  4 13:44:49 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * printcmd.c (x_command): Error if there is no memory to examine.
+
+       * gdb.texinfo: Added "cont" to the command index.
+
+       * sparc-dep.c (do_save_insn): Fixed typo in shift amount.
+
+       * m68k-opcode.h: Fixed opcodes for 68881.
+
+       * breakpoint.c, infcmd.c, source.c: Changed defaults in several
+       places for decode_line_1 to work off of the default_breakpoint_*
+       values instead of current_source_* values (the current_source_*
+       values are off by 5 or so because of listing defaults).
+
+       * stack.c (frame_info): ifdef'd out FRAME_SPECIFCATION_DYADIC in
+       the stack.c module.  If I can't do this right, I don't want to do
+       it at all.  Read the comment there for more info.
+
+Mon Oct 31 16:23:06 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * gdb.texinfo: Added documentation on the "until" command.
+
+Sat Oct 29 17:47:10 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * breakpoint.c, infcmd.c: Added UNTIL_COMMAND and subroutines of
+       it. 
+
+       * breakpoint.c, infcmd.c, infrun.c: Added new field to breakpoint
+       structure (silent, indicating a silent breakpoint), and modified
+       breakpoint_stop_status and things that read it's return value to
+       understand it.
+
+Fri Oct 28 17:45:33 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c, symmisc.c: Assorted speedups for readin, including
+       special casing most common symbols, and doing buffering instead of
+       calling malloc.  
+
+Thu Oct 27 11:11:15 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * stack.c, sparc-dep.c, m-sparc.h: Modified to allow "info frame"
+       to take two arguments on the sparc and do the right thing with
+       them. 
+
+       * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Put
+       stuff to put only symbols that didn't have debugging info on the
+       misc functions list back in.
+
+Wed Oct 26 10:10:32 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * valprint.c (type_print_varspec_suffix): Added check for
+       TYPE_LENGTH(TYPE_TARGET_TYPE(type)) > 0 to prevent divide by 0.
+
+       * printcmd.c (print_formatted): Added check for VALUE_REPEATED;
+       value_print needs to be called for that.
+
+       * infrun.c (wait_for_inferior): Added break when you decide to
+       stop on a null function prologue rather than continue stepping.
+
+       * m-sun3.h: Added explanatory comment to REGISTER_RAW_SIZE.
+
+       * expread.y (parse_c_1): Initialized paren_depth for each parse.
+
+Tue Oct 25 14:19:38 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * valprint.c, coffread.c, dbxread.c: Enum constant values in enum
+       type now accessed through TYPE_FIELD_BITPOS.
+
+       * dbxread.c (process_symbol_for_psymtab): Added code to deal with
+       possible lack of a ":" in a debugging symbol (do nothing).
+
+       * symtab.c (decode_line_1): Added check in case of all numbers for
+       complete lack of symbols.
+
+       * source.c (select_source_symtab): Made sure that this wouldn't
+       bomb on complete lack of symbols.
+
+Mon Oct 24 12:28:29 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-sparc.h, findvar.c: Ditched REGISTER_SAVED_UNIQUELY and based
+       code on REGISTER_IN_WINDOW_P and HAVE_REGISTER_WINDOWS.  This will
+       break when we find a register window machine which saves the
+       window registers within the context of an inferior frame.
+
+       * sparc-dep.c (frame_saved_pc): Put PC_ADJUST return back in for
+       frame_saved_pc.  Seems correct.
+
+       * findvar.c, m-sparc.h: Created the macro REGISTER_SAVED_UNIQUELY
+       to handle register window issues (ie. that find_saved_register
+       wasn't checking the selected frame itself for shit). 
+
+       * sparc-dep.c (core_file_command): Offset target of o & g register
+       bcopy by 1 to hit correct registers.
+
+       * m-sparc.h: Changed STACK_END_ADDR.
+
+Sun Oct 23 19:41:51 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * sparc-dep.c (core_file_command): Added in code to get the i & l
+       registers from the stack in the corefile, and blew away some wrong
+       code to get i & l from inferior.
+
+Fri Oct 21 15:09:19 1988  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+       * m-sparc.h (PUSH_DUMMY_FRAME): Saved the value of the RP register
+       in the location reserved for i7 (in the created frame); this way
+       the rp value won't get lost.  The pc (what we put into the rp in
+       this routine) gets saved seperately, so we loose no information.
+
+       * sparc-dep.c (do_save_insn & do_restore_insn): Added a wrapper to
+       preserve the proceed status state variables around each call to
+       proceed (the current frame was getting munged because this wasn't
+       being done).
+
+       * m-sparc.h (FRAME_FIND_SAVED_REGS): Fix bug: saved registers
+       addresses were being computed using absolute registers number,
+       rather than numbers relative to each group of regs.
+
+       * m-sparc.h (POP_FRAME): Fixed a bug (I hope) in the context
+       within which saved reg numbers were being interpetted.  The
+       values to be restored were being gotten in the inferior frame, and
+       the restoring was done in the superior frame.  This means that i
+       registers must be restored into o registers.
+
+       * sparc-dep.c (do_restore_insn): Modified to take a pc as an
+       argument, instead of a raw_buffer.  This matches (at least it
+       appears to match) usage from POP_FRAME, which is the only place
+       from which do_restore_insn is called.
+
+       * sparc-dep.c (do_save_insn and do_restore_insn): Added comments.
+
+       * m-sparc.h (FRAME_FIND_SAVED_REGS): Modified my code to find the
+       save addresses of out registers to use the in regs off the stack
+       pointer when the current frame is 1 from the innermost.
+
+Thu Oct 20 13:56:15 1988  & Smith  (randy at hobbes.ai.mit.edu)
+
+       * blockframe.c, m-sparc.h: Removed code associated with
+       GET_PREV_FRAME_FROM_CACHE_ITEM.  This code was not needed for the
+       sparc; you can always find the previous frames fp from the fp of
+       the current frame (which is the sp of the previous).  It's getting
+       the information associated with a given frame (ie. saved
+       registers) that's a bitch, because that stuff is saved relative to
+       the stack pointer rather than the frame pointer.
+
+       * m-sparc.h (GET_PREV_FRAME_FROM_CACHE_ITEM): Modified to return
+       the frame pointer of the previous frame instead of the stack
+       pointer of same.
+
+       * blockframe.c (flush_cached_frames): Modified call to
+       obstack_free to free back to frame_cache instead of back to zero.
+       This leaves the obstack control structure in finite state (and
+       still frees the entry allocated at frame_cache).
+
+Sat Oct 15 16:30:47 1988  & Smith  (randy at tartarus.uchicago.edu)
+
+       * valops.c (call_function): Suicide material here.  Fixed a typo;
+       CALL_DUMMY_STACK_ADJUST was spelled CAll_DUMMY_STACK_ADJUST on
+       line 530 of the file.  This cost me three days.  I'm giving up
+       typing for lent.
+
+Fri Oct 14 15:10:43 1988  & Smith  (randy at tartarus.uchicago.edu)
+
+       * m-sparc.h: Corrected a minor mistake in the dummy frame code
+       that was getting the 5th argument and the first argument from the
+       same place.
+
+Tue Oct 11 11:49:33 1988  & Smith  (randy at tartarus.uchicago.edu)
+
+       * infrun.c: Made stop_after_trap and stop_after_attach extern
+       instead of static so that code which used proceed from machine
+       dependent files could fiddle with them.
+
+       * blockframe.c, frame.h, sparc-dep.c, m-sparc.h: Changed sense of
+       ->prev and ->next in struct frame_cache_item to fit usage in rest
+       of gdb (oops).
+
+Mon Oct 10 15:32:42 1988  Randy Smith  (randy at gargoyle.uchicago.edu)
+
+       * m-sparc.h, sparc-dep.c, blockframe.c, frame.h: Wrote
+       get_frame_cache_item.  Modified FRAME_SAVED_PC and frame_saved_pc
+       to take only one argument and do the correct thing with it.  Added
+       the two macros I recently defined in blockframe.c to m-sparc.h.
+       Have yet to compile this thing on a sparc, but I've now merged in
+       everything that I received from tiemann, either exactly, or simply
+       effectively. 
+
+       * source.c: Added code to allocated space to sals.sals in the case
+       where no line was specified.
+
+       * blockframe.c, infrun.c: Modified to cache stack frames requested
+       to minimize accesses to subprocess.
+
+Tue Oct  4 15:10:39 1988  Randall Smith  (randy at cream-of-wheat.ai.mit.edu)
+
+       * config.gdb: Added sparc.
+
+Mon Oct  3 23:01:22 1988  Randall Smith  (randy at cream-of-wheat.ai.mit.edu)
+
+       * Makefile, blockframe.c, command.c, core.c, dbxread.c, defs.h,
+       expread.y, findvar.c, infcmd.c, inflow.c, infrun.c, sparc-pinsn.c,
+       m-sparc.h, sparc-def.c, printcmd.c, stack.c, symmisc.c, symseg.h,
+       valops.c, values.c: Did initial merge of sparc port.  This will
+       not compile; have to do stack frame caching and finish port.
+
+       * inflow.c, gdb.texinfo: `tty' now resets the controling terminal. 
+
+Fri Sep 30 11:31:16 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * inferior.h, infcmd.c, infrun.c: Changed the variable
+       stop_random_signal to stopped_by_random signal to fit in better
+       with name conventions (variable is not a direction to the
+       proceed/resume set; it is information from it).
+
+Thu Sep 29 13:30:46 1988  Randall Smith  (randy at cream-of-wheat.ai.mit.edu)
+
+       * infcmd.c (finish_command): Value type of return value is now
+       whatever the function returns, not the type of the function (fixed
+       a bug in printing said value).
+
+       * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab):
+       Put *all* global symbols into misc_functions.  This is what was
+       happening anyway, and we need it for find_pc_misc_function.
+
+       ** This was eventually taken out, but I didn't mark it in the
+       ChangeLog.  Oops.
+
+       * dbxread.c (process_symbol_for_psymtab): Put every debugger
+       symbol which survives the top case except for constants on the
+       symchain.  This means that all of these *won't* show up in misc
+       functions (this will be fixed once I make sure it's broken the way
+       it's supposed to be).
+
+       * dbxread.c: Modified placement of debugger globals onto the hash
+       list; now we exclude the stuff after the colon and don't skip the
+       first character (debugger symbols don't have underscores).
+
+       * dbxread.c: Killed debuginfo stuff with ifdef's.
+
+Wed Sep 28 14:31:51 1988  Randall Smith  (randy at cream-of-wheat.ai.mit.edu)
+
+       * symtab.h, dbxread.c: Modified to deal with BINCL, EINCL, and
+       EXCL symbols produced by the sun loader by adding a list of
+       pre-requisite partial_symtabs that each partial symtab needs.
+
+       * symtab.h, dbxread.c, symtab.c, symmisc.c: Modified to avoid
+       doing a qsort on the local (static) psymbols for each file to
+       speed startup.  This feature is not completely debugged, but it's
+       inclusion has forced the inclusion of another feature (dealing
+       with EINCL's, BINCL's and EXCL's) and so I'm going to go in and
+       deal with them.
+
+       * dbxread.c (process_symbol_for_psymtab): Made sure that the class
+       of the symbol made it into the partial_symbol entry.
+
+Tue Sep 27 15:10:26 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c: Fixed bug; init_psymbol_list was not being called
+       with the right number of arguments (1).
+
+       * dbxread.c: Put ifdef's around N_MAIN, N_M2C, and N_SCOPE to
+       allow compilation on a microvax.
+
+       * config.gdb: Modified so that "config.gdb vax" would work.
+
+       * dbxread.c, symtab.h, symmisc.h, symtab.c, source.c: Put in many
+       and varied hacks to speed up gdb startup including: A complete
+       rewrite of read_dbx_symtab, a modification of the partial_symtab
+       data type, deletion of select_source_symtab from
+       symbol_file_command, and optimiztion of the call to strcmp in
+       compare_psymbols. 
+
+Thu Sep 22 11:08:54 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * dbxread.c (psymtab_to_symtab): Removed call to
+       init_misc_functions. 
+
+       * dbxread.c: Fixed enumeration type clash (used enum instead of
+       integer constant).
+
+       * breakpoint.c: Fixed typo; lack of \ at end of line in middle of
+       string constant. 
+
+       * symseg.h: Fixed typo; lack of semicolon after structure
+       definition. 
+
+       * command.c, breakpoint.c, printcmd.c: Added cmdlist editing
+       functions to add commands with the abbrev flag set.  Changed
+       help_cmd_list to recognize this flag and modified unset,
+       undisplay, and enable, disable, and delete breakpoints to have
+       this flag set.
+
+Wed Sep 21 13:34:19 1988  Randall Smith  (randy at plantaris.ai.mit.edu)
+
+       * breakpoint.c, infcmd.c, gdb.texinfo: Created "unset" as an alias
+       for delete, and changed "unset-environment" to be the
+       "environment" subcommand of "delete".
+
+       * gdb.texinfo, valprint.c: Added documentation in the manual for
+       breaking the set-* commands into subcommands of set.  Changed "set
+       maximum" to "set array-max".
+
+       * main.c, printcmd.c, breakpoint.c: Moved the declaration of
+       command lists into main and setup a function in main initializing
+       them to guarrantee that they would be initialized before calling
+       any of the individual files initialize routines.
+
+       * command.c (lookup_cmd): A null string subcommand is treated as
+       an unknown subcommand rather than an ambiguous one (eg. "set $x =
+       1" will now work).
+
+       * infrun.c (wait_for_inferior): Put in ifdef for Sony News in
+       check for trap by INNER_THAN macro.
+
+       * eval.c (evaluate_subexp): Put in catch to keep the user from
+       attempting to call a non function as a function.
+
+Tue Sep 20 10:35:53 1988  Randall Smith  (randy at oatmeal.ai.mit.edu)
+
+       * dbxread.c (read_dbx_symtab): Installed code to keep track of
+       which global symbols did not have debugger symbols refering to
+       them, and recording these via record_misc_function.
+
+       * dbxread.c: Killed code to check for extra global symbols in the
+       debugger symbol table.
+
+       * printcmd.c, breakpoint.c: Modified help entries for several
+       commands to make sure that abbreviations were clearly marked and
+       that the right commands showed up in the help listings.
+
+       * main.c, command.c, breakpoint.c, infcmd.c, printcmd.c,
+       valprint.c, defs.h: Modified help system to allow help on a class
+       name to show subcommands as well as commands and help on a command
+       to show *all* subcommands of that command.
+
+Fri Sep 16 16:51:19 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
+
+       * breakpoint.c (_initialize_breakpoint): Made "breakpoints"
+       subcommands of enable, disable, and delete use class 0 (ie. they
+       show up when you do a help xxx now).
+
+       * infcmd.c,printcmd,c,main.c,valprint.c: Changed the set-*
+       commands into subcommands of set.  Created "set variable" for use
+       with variables whose names might conflict with other subcommands.
+
+       * blockframe.c, dbxread.c, coffread.c, expread.y, source.c:
+       Fixed mostly minor (and one major one in block_for_pc) bugs
+       involving checking the partial_symtab_list when a scan through the
+       symtab_list fails.
+
+Wed Sep 14 12:02:05 1988  Randall Smith  (randy at sugar-smacks.ai.mit.edu)
+
+       * breakpoint.c, gdb.texinfo: Added enable breakpoints, disable
+       breakpoints and delete breakpoints as synonyms for enable,
+       disable, and delete.  This seemed reasonable because of the
+       immeninent arrival of watchpoints & etc.
+
+       * gdb.texinfo: Added enable display, disable display, and delete
+       display to manual.
+
+Tue Sep 13 16:53:56 1988  Randall Smith  (randy at sugar-smacks.ai.mit.edu)
+
+       * inferior.h, infrun.c, infcmd.c: Added variable
+       stop_random_signal to indicate when a proceed had been stopped by
+       an unexpected signal.  Used this to determine (in normal_stop)
+       whether the current display point should be deleted.
+
+       * valops.c: Fix to value_ind to check for reference before doing a
+       COERCE_ARRAY.
+
+Sun Jul 31 11:42:36 1988  Richard Stallman  (rms at frosted-flakes.ai.mit.edu)
+
+       * breakpoint.c (_initialize_breakpoint): Clean up doc for commands
+       that can now apply also to auto-displays.
+
+       * coffread.c (record_line): Corrected a spazz in editing.
+       Also removed the two lines that assume line-numbers appear
+       only in increasing order.
+
+Tue Jul 26 22:19:06 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * expression.h, eval.c, expprint.c, printcmd.c, valarith.c,
+       valops.c, valprint.c, values.c, m-*.h: Changes for evaluating and
+       displaying 64-bit `long long' integers.  Each machine must define
+       a LONGEST type, and a BUILTIN_TYPE_LONGEST.
+
+       * symmisc.c: (print_symtab) check the status of the fopen and call
+       perror_with_name if needed.
+
+Thu Jul 21 00:56:11 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * Convex: core.c: changes required by Convex's SOFF format were
+       isolated in convex-dep.c.
+
+Wed Jul 20 21:26:10 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * coffread.c, core.c, expread.y, i386-pinsn.c, infcmd.c, inflow.c,
+       infrun.c, m-i386.h, main.c, remote.c, source.c, valops.c:
+       Improvements for the handling of the i386 and other machines
+       running USG.  (Several of these files just needed extra header files
+       such as types.h.) utils.c: added bcopy, bcmp, bzero, getwd, list
+       of signals, and queue routines for USG systems.  Added vfork macro
+       to i386
+
+       * printcmd.c, breakpoint.c: New commands to enable/disable
+       auto-displays.  Also `delete display displaynumber' works like
+       `undisplay displaynumber'.
+
+Tue Jul 19 02:17:18 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * coffread.c: (coff_lookup_type)  Wrong portion of type_vector was
+       being bzero'd after type_vector was reallocated.
+
+       * printcmd.c: (delete_display) Check for a display chain before
+       attempting to delete a display.
+
+       * core.c, *-dep.c (*-infdep moved to *-dep): machine-dependent
+       parts of core.c (core_file_command, exec_file_command) moved to
+       *-dep.c. 
+
+Mon Jul 18 19:45:51 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * dbxread.c: typo in read_struct_type (missing '=') was causing a
+       C struct to be parsed as a C++ struct, resulting in a `invalid
+       character' message.
+
+Sun Jul 17 22:27:32 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * printcmd.c, symtab.c, valops.c, expread.y: When an expression is
+       read, the innermost block required to evaluate the expression is
+       saved in the global variable `innermost_block'.  This information
+       is saved in the `block' field of an auto-display so that
+       expressions with inactive variables can be skipped.  `info display'
+       tells the user which displays are active and which are not.  New
+       fn `contained_in' returns nonzero if one block is contained within
+       another. 
+
+Fri Jul 15 01:53:14 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * infrun.c, m-i386.h: Use macro TRAPS_EXPECTED to set number of
+       traps to skip when sh execs the program.  Default is 2, m-i386.h
+       overrides this and sets to 4.
+
+       * coffread.c, infrun.c: minor changes for the i386.  May be able
+       to eliminate them with more general code.
+
+       * default-infdep.c: #ifdef SYSTEMV, include header file types.h.
+       Also switched the order of signal.h and user.h, since System 5
+       requires signal.h to come first.
+
+       * core.c main.c, remote,c, source.c, inflow.c: #ifdef SYSTEMV,
+       include various header files.  Usually types.h and fcntl.h.
+
+       * utils.c: added queue routines needed by the i386 (and other sys
+       5 machines).
+
+       * sys5.c, regex.c, regex.h: new files for sys 5 systems.  (The
+       regex files are simply links to /gp/gnu/lib.)
+
+Thu Jul 14 01:47:14 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * config.gdb, README: Provide a list of known machines when user
+       enters an invalid machine.  New second arg is operating system,
+       currently only used with `sunos4' or `os4'. Entry for i386 added.
+
+       * news-infdep.c: new file.
+
+       * m-news.h: new version which deals with new bugs in news800's OS.
+
+Tue Jul 12 19:52:16 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * Makefile, *.c, munch, config.gdb, README: New initialization
+       scheme uses nm to find functions whose names begin with
+       `_initialize_'.  Files `initialize.h', `firstfile.c',
+       `lastfile.c', `m-*init.h' no longer needed. 
+
+       * eval.c, symtab.c, valarith.c, valops.c, value.h, values.c: Bug
+       fixes from gdb+ 2.5.4.  evaluate_subexp takes a new arg, type
+       expected. New fn value_virtual_fn_field.
+
+Mon Jul 11 00:48:49 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * core.c (read_memory): xfer_core_file was being called with an
+       extra argument (0) by read_memory.
+
+       * core.c (read_memory), *-infdep.c (read_inferior_memory),
+       valops.c (value_at): read_memory and read_inferior_memory now work
+       like write_memory and write_inferior_memory in that errno is
+       checked after each ptrace and returned to the caller.  Used in
+       value_at to detect references to addresses which are out of
+       bounds.  Also core.c (xfer_core_file): return 1 if invalid
+       address, 0 otherwise.
+
+       * inflow.c, <machine>-infdep.c: removed all calls to ptrace from
+       inflow.c and put them in machine-dependent files *-infdep.c.
+
+Sun Jul 10 19:19:36 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * symmisc.c: (read_symsegs) Accept only format number 2.  Since
+       the size of the type structure changed when C++ support was added,
+       format 1 can no longer be used.
+
+       * core.c, m-sunos4.h: (core_file_command) support for SunOS 4.0.
+       Slight change in the core structure.  #ifdef SUNOS4.  New file
+       m-sunos4.h.  May want to change config.gdb also.
+
+Fri Jul  8 19:59:49 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * breakpoint.c: (break_command_1) Allow `break if condition'
+       rather than parsing `if' as a function name and returning an
+       error.
+
+Thu Jul  7 22:22:47 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * C++: valops.c, valprint.c, value.h, values.c: merged code to deal
+       with C++ expressions.
+
+Wed Jul  6 03:28:18 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+        * C++: dbxread.c: (read_dbx_symtab, condense_misc_bunches,
+       add_file_command)  Merged code to read symbol information from
+       an incrementally linked file.  symmisc.c:
+       (init_free_inclink_symtabs, free_inclink_symtabs) Cleanup
+       routines.
+
+Tue Jul  5 02:50:41 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * C++: symtab.c, breakpoint.c, source.c:  Merged code to deal with
+       ambiguous line specifications.  In C++ one can have overloaded
+       function names, so that `list classname::overloadedfuncname'
+       refers to several different lines, possibly in different files.
+
+Fri Jul  1 02:44:20 1988  Peter TerMaat  (pete at corn-chex.ai.mit.edu)
+
+       * C++: symtab.c: replaced lookup_symtab_1 and lookup_symtab_2 with
+       a modified lookup_symbol which checks for fields of the current
+       implied argument `this'.  printcmd.c, source.c, symtab.c,
+       valops.c: Need to change callers once callers are
+       installed. 
+
+Wed Jun 29 01:26:56 1988  Peter TerMaat  (pete at frosted-flakes.ai.mit.edu)
+
+       * C++: eval.c, expprint.c, expread.y, expression.h, valarith.c, 
+       Merged code to deal with evaluation of user-defined operators,
+       member functions, and virtual functions.
+       binop_must_be_user_defined tests for user-defined binops, 
+       value_x_binop calls the appropriate operator function. 
+
+Tue Jun 28 02:56:42 1988  Peter TerMaat  (pete at frosted-flakes.ai.mit.edu)
+
+       * C++: Makefile: changed the echo: expect 101 shift/reduce conflicts 
+       and 1 reduce/reduce conflict.
+\f
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/Convex.notes b/gdb/Convex.notes
new file mode 100644 (file)
index 0000000..28d336b
--- /dev/null
@@ -0,0 +1,163 @@
+
+@node Convex,,, Top
+@appendix Convex-specific info
+@cindex Convex notes
+
+Scalar registers are 64 bits long, which is a pain since
+left half of an S register frequently contains noise.
+Therefore there are two ways to obtain the value of an S register.
+
+@table @kbd
+@item $s0
+returns the low half of the register as an int
+
+@item $S0
+returns the whole register as a long long
+@end table
+
+You can print the value in floating point by using @samp{p/f $s0} or @samp{p/f $S0}
+to print a single or double precision value.
+
+@cindex vector registers
+Vector registers are handled similarly, with @samp{$V0} denoting the whole
+64-bit register and @kbd{$v0} denoting the 32-bit low half; @samp{p/f $v0}
+or @samp{p/f $V0} can be used to examine the register in floating point.
+The length of the vector registers is taken from @samp{$vl}.  
+
+Individual elements of a vector register are denoted in the obvious way;
+@samp{print $v3[9]} prints the tenth element of register @kbd{v3}, and
+@samp{set $v3[9] = 1234} alters it.
+
+@kbd{$vl} and @kbd{$vs} are int, and @kbd{$vm} is an int vector.
+Elements of @kbd{$vm} can't be assigned to.
+
+@cindex communication registers
+@kindex info comm-registers
+Communication registers have names @kbd{$C0 .. $C63}, with @kbd{$c0 .. $c63}
+denoting the low-order halves.  @samp{info comm-registers} will print them
+all out, and tell which are locked.  (A communication register is
+locked when a value is sent to it, and unlocked when the value is
+received.)  Communication registers are, of course, global to all
+threads, so it does not matter what the currently selected thread is.
+@samp{info comm-reg @var{name}} prints just that one communication
+register; @samp{name} may also be a communication register number
+@samp{nn} or @samp{0xnn}.
+@samp{info comm-reg @var{address}} prints the contents of the resource
+structure at that address.
+
+@kindex info psw
+The command @samp{info psw} prints the processor status word @kbd{$ps}
+bit by bit.
+
+@kindex set base
+GDB normally prints all integers in base 10, but the leading
+@kbd{0x80000000} of pointers is intolerable in decimal, so the default
+output radix has been changed to try to print addresses appropriately.
+The @samp{set base} command can be used to change this.
+
+@table @code
+@item set base 10
+Integer values always print in decimal.
+
+@item set base 16
+Integer values always print in hex.
+
+@item set base
+Go back to the initial state, which prints integer values in hex if they
+look like pointers (specifically, if they start with 0x8 or 0xf in the
+stack), otherwise in decimal.
+@end table
+
+@kindex set pipeline
+When an exception such as a bus error or overflow happens, usually the PC
+is several instructions ahead by the time the exception is detected.
+The @samp{set pipe} command will disable this.
+
+@table @code
+@item set pipeline off
+Forces serial execution of instructions; no vector chaining and no 
+scalar instruction overlap.  With this, exceptions are detected with 
+the PC pointing to the instruction after the one in error.
+
+@item set pipeline on
+Returns to normal, fast, execution.  This is the default.
+@end table
+
+@cindex parallel
+In a parallel program, multiple threads may be executing, each
+with its own registers, stack, and local memory.  When one of them
+hits a breakpoint, that thread is selected.  Other threads do
+not run while the thread is in the breakpoint.
+
+@kindex 1cont
+The selected thread can be single-stepped, given signals, and so
+on.  Any other threads remain stopped.  When a @samp{cont} command is given,
+all threads are resumed.  To resume just the selected thread, use
+the command @samp{1cont}.
+
+@kindex thread
+The @samp{thread} command will show the active threads and the
+instruction they are about to execute.  The selected thread is marked
+with an asterisk.  The command @samp{thread @var{n}} will select thread @var{n},
+shifting the debugger's attention to it for single-stepping,
+registers, local memory, and so on.
+
+@kindex info threads
+The @samp{info threads} command will show what threads, if any, have
+invisibly hit breakpoints or signals and are waiting to be noticed.
+
+@kindex set parallel
+The @samp{set parallel} command controls how many threads can be active.
+
+@table @code
+@item set parallel off
+One thread.  Requests by the program that other threads join in
+(spawn and pfork instructions) do not cause other threads to start up.
+This does the same thing as the @samp{limit concurrency 1} command.
+
+@item set parallel fixed
+All CPUs are assigned to your program whenever it runs.  When it
+executes a pfork or spawn instruction, it begins parallel execution
+immediately.  This does the same thing as the @samp{mpa -f} command.
+
+@item set parallel on
+One or more threads.  Spawn and pfork cause CPUs to join in when and if
+they are free.  This is the default.  It is very good for system
+throughput, but not very good for finding bugs in parallel code.  If you
+suspect a bug in parallel code, you probably want @samp{set parallel fixed.}
+@end table
+
+@subsection Limitations
+
+WARNING: Convex GDB evaluates expressions in long long, because S
+registers are 64 bits long.  However, GDB expression semantics are not
+exactly C semantics.  This is a bug, strictly speaking, but it's not one I
+know how to fix.  If @samp{x} is a program variable of type int, then it
+is also type int to GDB, but @samp{x + 1} is long long, as is @samp{x + y}
+or any other expression requiring computation.  So is the expression
+@samp{1}, or any other constant.  You only really have to watch out for
+calls.  The innocuous expression @samp{list_node (0x80001234)} has an
+argument of type long long.  You must explicitly cast it to int.
+
+It is not possible to continue after an uncaught fatal signal by using
+@samp{signal 0}, @samp{return}, @samp{jump}, or anything else.  The difficulty is with
+Unix, not GDB.
+
+I have made no big effort to make such things as single-stepping a
+@kbd{join} instruction do something reasonable.  If the program seems to
+hang when doing this, type @kbd{ctrl-c} and @samp{cont}, or use
+@samp{thread} to shift to a live thread.  Single-stepping a @kbd{spawn}
+instruction apparently causes new threads to be born with their T bit set;
+this is not handled gracefully.  When a thread has hit a breakpoint, other
+threads may have invisibly hit the breakpoint in the background; if you
+clear the breakpoint gdb will be surprised when threads seem to continue
+to stop at it.  All of these situations produce spurious signal 5 traps;
+if this happens, just type @samp{cont}.  If it becomes a nuisance, use
+@samp{handle 5 nostop}.  (It will ask if you are sure.  You are.)
+
+There is no way in GDB to store a float in a register, as with
+@kbd{set $s0 = 3.1416}.  The identifier @kbd{$s0} denotes an integer,
+and like any C expression which assigns to an integer variable, the
+right-hand side is casted to type int.  If you should need to do
+something like this, you can assign the value to @kbd{@{float@} ($sp-4)}
+and then do @kbd{set $s0 = $sp[-4]}.  Same deal with @kbd{set $v0[69] = 6.9}.
diff --git a/gdb/Makefile.dist b/gdb/Makefile.dist
new file mode 100755 (executable)
index 0000000..7b4e3ce
--- /dev/null
@@ -0,0 +1,506 @@
+##Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Place to install binaries. 
+bindir=/usr/local/bin
+
+# System V: If you compile gdb with a compiler which uses the coff
+# encapsulation feature (this is a function of the compiler used, NOT
+# of the m-?.h file selected by config.gdb), you must make sure that
+# the GNU nm is the one that is used by munch.
+
+# If you are compiling with GCC, make sure that either 1) You use the
+# -traditional flag, or 2) You have the fixed include files where GCC
+# can reach them.  Otherwise the ioctl calls in inflow.c and readline.c 
+# will be incorrectly compiled.  The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+#CC=cc
+#CC=gcc -traditional
+GCC=gcc
+
+VPATH=$(srcdir)
+
+# It is also possible that you will need to add -I/usr/include/sys to the
+# CFLAGS section if your system doesn't have fcntl.h in /usr/include (which 
+# is where it should be according to Posix).
+
+YACC=bison -y
+# YACC=yacc
+SHELL=/bin/sh
+MAKE=make
+
+# Set this up with gcc if you have gnu ld and the loader will print out
+# line numbers for undefinded refs.
+#CC-LD=gcc -static
+CC-LD=${CC}
+
+# define this to be "gmalloc.o" if you want to use the gnu malloc routine
+# (useful for debugging memory allocation problems in gdb).  To use your
+# system malloc, uncomment the following two lines.
+#GNU_MALLOC =
+#MALLOC_CFLAGS = -DNO_MALLOC_CHECK
+GNU_MALLOC = gmalloc.o mcheck.o
+MALLOC_CFLAGS =
+
+# Where is the "include" directory?  Traditionally ../include or ./include
+INCLUDE_DIR =  ${srcdir}/../include
+INCLUDE_DEP = $$(INCLUDE_DIR)
+
+# Where is the BFD library?  Traditionally ../bfd or ./bfd
+BFD_DIR =  ${srcdir}/../bfd
+BFD_DEP = $$(BFD_DIR)
+
+# All the includes used for CFLAGS and for lint.
+# -I. for config files.
+# -I${srcdir} for <obstack.h>, possibly regex.h also.
+INCLUDE_CFLAGS = -I. -I${srcdir} -I$(INCLUDE_DIR) -I${srcdir}/vx-share
+
+# {X,T}M_CFLAGS, if defined, has system-dependent CFLAGS.
+# CFLAGS for both GDB and readline.
+GLOBAL_CFLAGS = -g ${TM_CFLAGS} ${XM_CFLAGS}
+#PROFILE_CFLAGS = -pg
+
+CFLAGS = ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} ${MALLOC_CFLAGS} ${INCLUDE_CFLAGS}
+# None of the things in CFLAGS will do any harm, and on some systems
+#  (e.g. SunOS4) it is important to use the M_CFLAGS.
+LDFLAGS = $(CFLAGS)
+
+# define this to be "obstack.o" if you don't have the obstack library installed
+# so that the dependencies work right.  
+OBSTACK = obstack.o
+
+# Requires GNU getopt_long features.
+GETOPT = getopt.o getopt1.o
+# Where is the getopt directory?  Traditionally ../getopt or ./getopt
+GETOPT_DIR =  ${srcdir}/../getopt
+GETOPT_DEP = $$(GETOPT_DIR)
+
+# Flags that describe where you can find the termcap library.
+# You may need to make other arrangements for USG.
+TERMCAP = -ltermcap
+
+# You must define REGEX and REGEX1 on USG machines.
+# If your sysyem is missing alloca(), or, more likely, it's there but
+# it doesn't work, define ALLOCA & ALLOCA1
+
+# {X,T}M_CLIBS, if defined, has system-dependent libs
+# For example, -lPW for System V to get alloca().
+# FIXME STOPGAP FOR BFD LIBRARY: BFD stuff
+CLIBS = ${TERMCAP} $(XM_CLIBS) ${TM_CLIBS} ${BFD_DIR}/libbfd.a
+CDEPS = ${XM_CDEPS} ${TM_CDEPS} ${BFD_DIR}/libbfd.a
+
+ADD_FILES = ${OBSTACK} ${REGEX} ${ALLOCA} ${GNU_MALLOC} ${GETOPT}
+ADD_DEPS = ${OBSTACK} ${REGEX1} ${ALLOCA1} ${GNU_MALLOC} ${GETOPT}
+
+VERSION = 3.94.2
+DIST=gdb-$(VERSION)
+
+LINT=/usr/5bin/lint
+LINTFLAGS=
+
+# Source files in the main directory.
+# Files which are included via a tconfig/* or xconfig/* file 
+# should *not* be specified here; they're in "ALLDEPFILES".
+SFILES_MAINDIR = \
+        blockframe.c breakpoint.c command.c core.c \
+        environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
+        main.c printcmd.c \
+        remote.c source.c stack.c symmisc.c symtab.c symfile.c \
+        utils.c valarith.c valops.c valprint.c values.c expread.y \
+        signame.c cplus-dem.c mem-break.c target.c inftarg.c \
+        dbxread.c coffread.c \
+        ieee-float.c 
+
+# Source files in subdirectories (which will be handled separately by
+#  'make gdb.tar.Z').
+# Files which are included via a tconfig/* or xconfig/* file 
+# should *not* be specified here; they're in "ALLDEPFILES".
+SFILES_SUBDIR = \
+        ${srcdir}/vx-share/dbgRpcLib.h \
+        ${srcdir}/vx-share/ptrace.h \
+        ${srcdir}/vx-share/reg.h \
+        ${srcdir}/vx-share/vxTypes.h \
+        ${srcdir}/vx-share/vxWorks.h \
+        ${srcdir}/vx-share/wait.h \
+        ${srcdir}/vx-share/xdr_ld.h \
+        ${srcdir}/vx-share/xdr_ptrace.h \
+        ${srcdir}/vx-share/xdr_rdb.h \
+        ${srcdir}/vx-share/xdr_regs.h \
+        ${srcdir}/nindy-share/Makefile \
+        ${srcdir}/nindy-share/VERSION \
+        ${srcdir}/nindy-share/b.out.h \
+        ${srcdir}/nindy-share/block_io.h \
+        ${srcdir}/nindy-share/coff.h \
+        ${srcdir}/nindy-share/demux.h \
+        ${srcdir}/nindy-share/env.h \
+        ${srcdir}/nindy-share/stop.h \
+        ${srcdir}/nindy-share/ttycntl.h
+
+# All source files that go into linking GDB, except config-specified files.
+SFILES = $(SFILES_MAINDIR) $(SFILES_SUBDIR)
+
+# All source files that lint should look at
+LINTFILES = $(SFILES) expread.tab.c init.c
+
+# Any additional files specified on these lines should also be added to
+# the OTHERS = definition below, so they go in the tar files.
+SFILES_STAND = $(SFILES) standalone.c
+SFILES_KGDB  = $(SFILES) stuff.c kdb-start.c
+
+# Header files that are not named in tconfig/* or xconfig/* go here.
+HFILES=        breakpoint.h command.h defs.h environ.h \
+       expression.h frame.h gdbcmd.h gdbcore.h \
+       getpagesize.h ieee-float.h inferior.h param-no-tm.h param.h \
+       signals.h signame.h symfile.h symtab.h \
+       target.h tdesc.h terminal.h tm-68k.h tm-i960.h tm-sunos.h \
+       value.h
+
+OPCODES = pn-opcode.h np1-opcode.h sparc-opcode.h vax-opcode.h m68k-opcode.h \
+         ns32k-opcode.h convex-opcode.h pyr-opcode.h mips-opcode.h \
+         am29k-opcode.h
+
+REMOTE_EXAMPLES = remote-sa.m68k.shar remote-multi.shar
+
+MALLOCSRC = gmalloc.c mcheck.c ansidecl.h stdlib.h gmalloc.h stddef.h
+GETOPTSRC = $(GETOPT_DIR)/getopt.c $(GETOPT_DIR)/getopt1.c
+
+POSSLIBS_MAINDIR = obstack.h obstack.c regex.c regex.h alloca.c \
+       $(MALLOCSRC)
+POSSLIBS = $(POSSLIBS_MAINDIR) $(GETOPTSRC)
+
+TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
+
+# tdesc-lib cannot be named simply tdesc, because if if it were GNU make
+# would try to make it from tdesc.c.
+# tdesc-lib removed from the list due to Motorola copyrights...gnu@cygnus.com
+OTHERS = Makefile.dist depend alldeps.mak Makefile.srcdir \
+        createtags munch config.gdb config.status \
+        ChangeLog ChangeLog-3.x \
+        README TODO TAGS WHATS.NEW \
+        gdb.texinfo gdb-int.texinfo gdbrc.tex threecol.tex \
+       .gdbinit COPYING expread.tab.c stab.def \
+        copying.c Projects Convex.notes copying.awk \
+        saber.suppress standalone.c stuff.c kdb-start.c \
+        hp-include # tests
+
+DEPFILES= ${TDEPFILES} ${XDEPFILES}
+
+SOURCES=$(SFILES) $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${OPCODES} ${ALLPARAM} ${POSSLIBS} 
+TAGFILES_MAINDIR = $(SFILES_MAINDIR) $(ALLDEPFILES_MAINDIR) \
+             ${HFILES} ${OPCODES} ${ALLPARAM} ${POSSLIBS_MAINDIR} 
+TARFILES = ${TAGFILES_MAINDIR} ${OTHERS} ${REMOTE_EXAMPLES}
+
+OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
+    values.o eval.o valops.o valarith.o valprint.o printcmd.o \
+    symtab.o symfile.o symmisc.o infcmd.o infrun.o remote.o \
+    command.o utils.o expread.o expprint.o environ.o version.o \
+    copying.o $(DEPFILES) signame.o cplus-dem.o mem-break.o target.o \
+    inftarg.o ieee-float.o \
+    dbxread.o coffread.o # mipsread.o
+
+RAPP_OBS = rgdb.o rudp.o rserial.o serial.o udp.o $(XDEPFILES)
+
+TSOBS = core.o inflow.o
+
+NTSOBS = standalone.o
+
+TSSTART = /lib/crt0.o
+
+NTSSTART = kdb-start.o
+
+RL_LIB = readline/libreadline.a
+RL_LIB_DEP = $(RL_LIB)
+
+# Prevent Sun make from putting in the machine type.  Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+       ${CC} -c ${CFLAGS} $<
+
+all: gdb
+
+install: gdb
+       cp gdb $(bindir)/gdb.new
+       mv $(bindir)/gdb.new $(bindir)/gdb
+       $(M_INSTALL)
+
+init.c: $(srcdir)/munch $(MUNCH_DEFINE) $(OBS) $(TSOBS)
+       $(srcdir)/munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) > init.c
+
+gdb: $(OBS) $(TSOBS) ${ADD_DEPS} ${RL_LIB_DEP} ${CDEPS} init.o
+       ${CC-LD} $(LDFLAGS) -o gdb init.o $(OBS) $(TSOBS) $(ADD_FILES) \
+       ${RL_LIB} $(CLIBS)
+
+saber_gdb: $(SFILES) $(GETOPTSRC) $(DEPFILES) copying.c obstack.c version.c
+       #setopt load_flags $(CFLAGS) -I$(BFD_DIR)
+       #load ./init.c $(SFILES)
+       #unload ${srcdir}/expread.y
+       #load ${srcdir}/expread.tab.c readline/libreadline.a
+       #load copying.c version.c
+       #load obstack.c $(GETOPTSRC)
+       #load `echo " "$(DEPFILES) | sed -e 's/\.o/.c/g' -e 's, , ../,g'`
+       #load ${BFD_DIR}/libbfd.a -ltermcap 
+       ##void mcheck(a) void (*a)(); { }
+
+
+
+# This is useful when debugging GDB, because some Unix's don't let you run GDB
+# on itself without copying the executable.  So "make gdb1" will make
+# gdb and put a copy in gdb1, and you can run it with "gdb gdb1".
+# Removing gdb1 before the copy is the right thing if gdb1 is open
+# in another process.
+gdb1: gdb
+       rm -f gdb1
+       cp gdb gdb1
+
+# This is a remote stub which runs under unix and starts up an
+# inferior process.  This is at least useful for debugging GDB's
+# remote support.
+rapp: $(RAPP_OBS)
+       rm -f rapp_init.c
+       ${srcdir}/munch ${RAPP_OBS} > rapp_init.c
+       ${CC-LD} $(LDFLAGS) -o $@ rapp_init.c $(RAPP_OBS)
+       
+Makefiles= Makefile.srcdir $(M_MAKEFILE) \
+       ${srcdir}/alldeps.mak ${srcdir}/Makefile.dist
+
+MAKE_MAKEFILE= echo "M_MAKEFILE=$(M_MAKEFILE)" | \
+       cat - ${Makefiles} ${srcdir}/depend >Makefile
+
+Makefile: $(Makefiles)
+       $(MAKE_MAKEFILE)
+
+alldeps.mak: ${srcdir}/tconfig ${srcdir}/xconfig
+       rm -f alldeps.mak alldeps.tmp allparam.tmp allconfig.tmp
+       for i in `ls -d ${srcdir}/tconfig/*[0-9A-Za-z] \
+          ${srcdir}/xconfig/*[0-9A-Za-z] | grep -v RCS` ; do \
+         echo $$i >>allconfig.tmp; \
+         awk <$$i ' \
+           $$1 == "TDEPFILES=" || $$1 == "XDEPFILES=" { \
+             for (i = 2; i <= NF; i++) \
+               print $$i >> "alldeps.tmp" ; \
+            } \
+           $$1 == "TM_FILE=" || $$1 == "XM_FILE=" { \
+             print $$2 >> "allparam.tmp" }' ; \
+       done
+       sort <alldeps.tmp | uniq | \
+         sed -e 's/arm-convert.o/arm-convert.s/' \
+             -e 's!^Onindy.o!nindy-share/Onindy.c!' \
+             -e 's!^nindy.o!nindy-share/nindy.c!' \
+             -e 's!ttybreak.o!nindy-share/ttybreak.c!' \
+             -e 's!ttyflush.o!nindy-share/ttyflush.c!' \
+             -e 's!xdr_ld.o!vx-share/xdr_ld.c!' \
+             -e 's!xdr_ptrace.o!vx-share/xdr_ptrace.c!' \
+             -e 's!xdr_rdb.o!vx-share/xdr_rdb.c!' \
+             -e 's!xdr_regs.o!vx-share/xdr_regs.c!' \
+             -e 's/\.o/.c/' \
+           >alldeps2.tmp
+       echo 'ALLDEPFILES = $$(ALLDEPFILES_MAINDIR) $$(ALLDEPFILES_SUBDIR)' \
+           >>alldeps.mak;
+       grep -v / alldeps2.tmp | \
+         awk 'BEGIN {printf "ALLDEPFILES_MAINDIR="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       grep / alldeps2.tmp | \
+         awk 'BEGIN {printf "ALLDEPFILES_SUBDIR="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       sort <allparam.tmp | uniq | awk 'BEGIN {printf "ALLPARAM="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       sort <allconfig.tmp | uniq | awk 'BEGIN {printf "ALLCONFIG="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       rm -f alldeps.tmp alldeps2.tmp allparam.tmp allconfig.tmp
+
+# The sed script makes everything which depends on {x,t}m.h depend on
+# config.status as well, in case someone reconfigures gdb out from
+# under an already compiled gdb.
+depend: $(SOURCES) Makefile.dist
+       @echo Ignore errors about non-existent system-supplied include files
+       @echo for systems other than the one you are using.
+       @echo "If xm.h and tm.h don't exist, the error messages saying so"
+       @echo can safely be ignored.
+       @echo Also ignore parse errors in valops.c, and any errors in
+       @echo arm-convert.s.
+       -$(GCC) -MM $(CFLAGS) -I$(BFD_DIR) \
+           `ls $(SOURCES) | sort -u` >depend.tmp
+       <depend.tmp sed -e 's/ [xt]m.h/& config.status/g'  \
+         -e 's; vx-share/; $${srcdir}/vx-share/;g'  \
+         -e 's; nindy-share/; $${srcdir}/nindy-share/;g'  \
+         -e 's; $(INCLUDE_DIR)/; $(INCLUDE_DEP)/;g'  \
+         -e 's; [a-z0-9./]*bfd/; $(BFD_DEP)/;g'  \
+         -e 's; [a-z0-9./]*getopt/; $(GETOPT_DEP)/;g'  \
+         -e 's; \./; $${srcdir}/;g'  \
+         >depend
+       $(MAKE_MAKEFILE)
+       rm depend.tmp
+
+config.status:
+       @echo "You must configure gdb.  Look at the README file for details."
+       @false
+
+# These are not generated by "make depend" because they only are there
+# for some machines.
+tm-isi.h tm-sun3.h tm-news.h tm-hp300bsd.h tm-altos.h : tm-68k.h
+tm-hp300hpux.h tm-sun2.h tm-3b1.h : tm-68k.h
+xm-news1000.h : xm-news.h
+xm-i386-sv32.h : xm-i386.h
+tm-i386gas.h: tm-i386.h
+xm-sun4os4.h : xm-sparc.h
+tm-sun4os4.h : tm-sparc.h
+
+kdb : $(NTSSTART) $(OBS) $(NTSOBS) ${ADD_DEPS} ${RL_LIB_DEP}
+       rm -f init.c
+       $(srcdir)/munch ${MUNCH_DEFINE} $(OBS) $(NTSOBS) > init.c
+       $(CC) $(LDFLAGS) -c init.c $(CLIBS) 
+       ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o $(ADD_FILES) \
+       ${RL_LIB} -lc $(CLIBS)
+
+# Put the proper machine-specific files first.
+# createtags will edit the .o in DEPFILES into .c
+TAGS: ${TAGFILES}
+       $(srcdir)/createtags $(TM_FILE) ${XM_FILE} $(DEPFILES) ${TAGFILES}
+tags: TAGS
+
+# FIXME: Get alldeps.mak up to date, config.gdb none, THEN make gdb.tar.Z!
+gdb.tar.Z: ${TARFILES}
+       rm -f gdb.tar; rm -rf $(DIST)
+       cd readline ; make readline.tar
+       mkdir $(DIST)
+       cd $(DIST) ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
+       mkdir $(DIST)/readline
+       cd $(DIST)/readline ; tar xf ../../readline/readline.tar
+       mkdir $(DIST)/xconfig ${DIST}/tconfig
+       cd $(DIST)/tconfig ; \
+         for i in $(ALLCONFIG) ; do ln -s ../../$$i ../$$i ; done
+       mkdir $(DIST)/vx-share $(DIST)/nindy-share
+       cd $(DIST)/tconfig ; \
+         for i in $(SFILES_SUBDIR) $(ALLDEPFILES_SUBDIR); \
+           do ln -s ../../$$i ../$$i ; done
+       tar chf - $(DIST) | compress >gdb.tar.Z
+       rm -rf $(DIST)
+
+clean:
+       rm -f ${OBS} ${TSOBS} ${NTSOBS} ${ADD_FILES}
+       rm -f init.c init.o version.c
+       rm -f gdb core gdb.tar gdb.tar.Z make.log
+       rm -f gdb[0-9]
+       cd readline ; make clean
+
+distclean: clean expread.tab.c TAGS
+       rm -f tm.h xm.h config.status
+       rm -f y.output yacc.acts yacc.tmp
+       rm -f ${TESTS} Makefile
+
+realclean: clean
+       rm -f expread.tab.c TAGS
+       rm -f tm.h xm.h config.status
+       rm -f Makefile
+
+gdb.dvi : gdb.texinfo
+       tex gdb.texinfo
+       texindex gdb.??
+       tex gdb.texinfo
+
+# Make copying.c from COPYING
+copying.c : COPYING copying.awk
+       awk -f copying.awk < COPYING > copying.c
+
+version.c : Makefile.dist
+       echo 'char *version = "$(VERSION)";' >version.c
+
+${srcdir}/expread.tab.c : $(srcdir)/expread.y
+       @echo 'Expect 4 shift/reduce conflict.'
+       ${YACC} $(srcdir)/expread.y
+       mv y.tab.c ${srcdir}/expread.tab.c
+
+expread.o : ${srcdir}/expread.tab.c defs.h param.h symtab.h \
+            frame.h expression.h
+       $(CC) -c ${CFLAGS} `echo ${srcdir}/expread.tab.c | sed 's,^\./,,'`
+       mv expread.tab.o expread.o
+
+# dbxread, coffread, mipsread have dependencies on BFD header files.
+dbxread.o: ${srcdir}/dbxread.c
+       ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/dbxread.c
+
+coffread.o: ${srcdir}/coffread.c
+       ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/coffread.c
+
+mipsread.o: ${srcdir}/mipsread.c
+       ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/mipsread.c
+
+# Drag in the files that are in another directory.
+
+getopt1.o: $(GETOPT_DIR)/getopt1.c
+       ${CC} -c ${CFLAGS} $(GETOPT_DIR)/getopt1.c
+
+getopt.o: $(GETOPT_DIR)/getopt.c
+       ${CC} -c ${CFLAGS} $(GETOPT_DIR)/getopt.c
+
+xdr_ld.o: ${srcdir}/vx-share/xdr_ld.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_ld.c
+
+xdr_ptrace.o: ${srcdir}/vx-share/xdr_ptrace.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_ptrace.c
+
+xdr_rdb.o: ${srcdir}/vx-share/xdr_rdb.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_rdb.c
+
+xdr_regs.o: ${srcdir}/vx-share/xdr_regs.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_regs.c
+
+nindy.o: ${srcdir}/nindy-share/nindy.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/nindy.c
+
+Onindy.o: ${srcdir}/nindy-share/Onindy.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/Onindy.c
+
+ttybreak.o: ${srcdir}/nindy-share/ttybreak.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/ttybreak.c
+
+ttyflush.o: ${srcdir}/nindy-share/ttyflush.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/ttyflush.c
+
+tdesc-lib/libdc.o : force_update
+       cd tdesc-lib ; ${MAKE} "SYSV_DEFINE=${SYSV_DEFINE}"
+
+# In LOCAL_INCLUDES, -I${srcdir} is right if srcdir is an absolute path,
+# and -I../${srcdir} is right if it is relative (e.g. ".."), so search both.
+readline/libreadline.a : force_update
+       cd readline ; ${MAKE} "SYSV=${SYSV_DEFINE}"\
+               "VPATH=${srcdir}/readline:../${srcdir}/readline"\
+               "LOCAL_INCLUDES=-I../ -I${srcdir}/ -I../${srcdir}/"\
+               "DEBUG_FLAGS=${GLOBAL_CFLAGS}" "CC=${CC}" libreadline.a
+
+lint: $(LINTFILES)
+       $(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES)
+
+gdb.cxref: $(SFILES)
+       cxref -I. $(SFILES) >gdb.cxref
+
+force_update :
+
+# When used with GDB, the demangler should never look for leading underscores
+# because GDB strips them off during symbol read-in.  Thus -Dnounderscore.
+cplus-dem.o : cplus-dem.c
+       ${CC} -c -Dnounderscore `echo ${srcdir}/cplus-dem.c | sed 's,^\./,,'`
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
new file mode 100644 (file)
index 0000000..7b4e3ce
--- /dev/null
@@ -0,0 +1,506 @@
+##Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Place to install binaries. 
+bindir=/usr/local/bin
+
+# System V: If you compile gdb with a compiler which uses the coff
+# encapsulation feature (this is a function of the compiler used, NOT
+# of the m-?.h file selected by config.gdb), you must make sure that
+# the GNU nm is the one that is used by munch.
+
+# If you are compiling with GCC, make sure that either 1) You use the
+# -traditional flag, or 2) You have the fixed include files where GCC
+# can reach them.  Otherwise the ioctl calls in inflow.c and readline.c 
+# will be incorrectly compiled.  The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+#CC=cc
+#CC=gcc -traditional
+GCC=gcc
+
+VPATH=$(srcdir)
+
+# It is also possible that you will need to add -I/usr/include/sys to the
+# CFLAGS section if your system doesn't have fcntl.h in /usr/include (which 
+# is where it should be according to Posix).
+
+YACC=bison -y
+# YACC=yacc
+SHELL=/bin/sh
+MAKE=make
+
+# Set this up with gcc if you have gnu ld and the loader will print out
+# line numbers for undefinded refs.
+#CC-LD=gcc -static
+CC-LD=${CC}
+
+# define this to be "gmalloc.o" if you want to use the gnu malloc routine
+# (useful for debugging memory allocation problems in gdb).  To use your
+# system malloc, uncomment the following two lines.
+#GNU_MALLOC =
+#MALLOC_CFLAGS = -DNO_MALLOC_CHECK
+GNU_MALLOC = gmalloc.o mcheck.o
+MALLOC_CFLAGS =
+
+# Where is the "include" directory?  Traditionally ../include or ./include
+INCLUDE_DIR =  ${srcdir}/../include
+INCLUDE_DEP = $$(INCLUDE_DIR)
+
+# Where is the BFD library?  Traditionally ../bfd or ./bfd
+BFD_DIR =  ${srcdir}/../bfd
+BFD_DEP = $$(BFD_DIR)
+
+# All the includes used for CFLAGS and for lint.
+# -I. for config files.
+# -I${srcdir} for <obstack.h>, possibly regex.h also.
+INCLUDE_CFLAGS = -I. -I${srcdir} -I$(INCLUDE_DIR) -I${srcdir}/vx-share
+
+# {X,T}M_CFLAGS, if defined, has system-dependent CFLAGS.
+# CFLAGS for both GDB and readline.
+GLOBAL_CFLAGS = -g ${TM_CFLAGS} ${XM_CFLAGS}
+#PROFILE_CFLAGS = -pg
+
+CFLAGS = ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} ${MALLOC_CFLAGS} ${INCLUDE_CFLAGS}
+# None of the things in CFLAGS will do any harm, and on some systems
+#  (e.g. SunOS4) it is important to use the M_CFLAGS.
+LDFLAGS = $(CFLAGS)
+
+# define this to be "obstack.o" if you don't have the obstack library installed
+# so that the dependencies work right.  
+OBSTACK = obstack.o
+
+# Requires GNU getopt_long features.
+GETOPT = getopt.o getopt1.o
+# Where is the getopt directory?  Traditionally ../getopt or ./getopt
+GETOPT_DIR =  ${srcdir}/../getopt
+GETOPT_DEP = $$(GETOPT_DIR)
+
+# Flags that describe where you can find the termcap library.
+# You may need to make other arrangements for USG.
+TERMCAP = -ltermcap
+
+# You must define REGEX and REGEX1 on USG machines.
+# If your sysyem is missing alloca(), or, more likely, it's there but
+# it doesn't work, define ALLOCA & ALLOCA1
+
+# {X,T}M_CLIBS, if defined, has system-dependent libs
+# For example, -lPW for System V to get alloca().
+# FIXME STOPGAP FOR BFD LIBRARY: BFD stuff
+CLIBS = ${TERMCAP} $(XM_CLIBS) ${TM_CLIBS} ${BFD_DIR}/libbfd.a
+CDEPS = ${XM_CDEPS} ${TM_CDEPS} ${BFD_DIR}/libbfd.a
+
+ADD_FILES = ${OBSTACK} ${REGEX} ${ALLOCA} ${GNU_MALLOC} ${GETOPT}
+ADD_DEPS = ${OBSTACK} ${REGEX1} ${ALLOCA1} ${GNU_MALLOC} ${GETOPT}
+
+VERSION = 3.94.2
+DIST=gdb-$(VERSION)
+
+LINT=/usr/5bin/lint
+LINTFLAGS=
+
+# Source files in the main directory.
+# Files which are included via a tconfig/* or xconfig/* file 
+# should *not* be specified here; they're in "ALLDEPFILES".
+SFILES_MAINDIR = \
+        blockframe.c breakpoint.c command.c core.c \
+        environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
+        main.c printcmd.c \
+        remote.c source.c stack.c symmisc.c symtab.c symfile.c \
+        utils.c valarith.c valops.c valprint.c values.c expread.y \
+        signame.c cplus-dem.c mem-break.c target.c inftarg.c \
+        dbxread.c coffread.c \
+        ieee-float.c 
+
+# Source files in subdirectories (which will be handled separately by
+#  'make gdb.tar.Z').
+# Files which are included via a tconfig/* or xconfig/* file 
+# should *not* be specified here; they're in "ALLDEPFILES".
+SFILES_SUBDIR = \
+        ${srcdir}/vx-share/dbgRpcLib.h \
+        ${srcdir}/vx-share/ptrace.h \
+        ${srcdir}/vx-share/reg.h \
+        ${srcdir}/vx-share/vxTypes.h \
+        ${srcdir}/vx-share/vxWorks.h \
+        ${srcdir}/vx-share/wait.h \
+        ${srcdir}/vx-share/xdr_ld.h \
+        ${srcdir}/vx-share/xdr_ptrace.h \
+        ${srcdir}/vx-share/xdr_rdb.h \
+        ${srcdir}/vx-share/xdr_regs.h \
+        ${srcdir}/nindy-share/Makefile \
+        ${srcdir}/nindy-share/VERSION \
+        ${srcdir}/nindy-share/b.out.h \
+        ${srcdir}/nindy-share/block_io.h \
+        ${srcdir}/nindy-share/coff.h \
+        ${srcdir}/nindy-share/demux.h \
+        ${srcdir}/nindy-share/env.h \
+        ${srcdir}/nindy-share/stop.h \
+        ${srcdir}/nindy-share/ttycntl.h
+
+# All source files that go into linking GDB, except config-specified files.
+SFILES = $(SFILES_MAINDIR) $(SFILES_SUBDIR)
+
+# All source files that lint should look at
+LINTFILES = $(SFILES) expread.tab.c init.c
+
+# Any additional files specified on these lines should also be added to
+# the OTHERS = definition below, so they go in the tar files.
+SFILES_STAND = $(SFILES) standalone.c
+SFILES_KGDB  = $(SFILES) stuff.c kdb-start.c
+
+# Header files that are not named in tconfig/* or xconfig/* go here.
+HFILES=        breakpoint.h command.h defs.h environ.h \
+       expression.h frame.h gdbcmd.h gdbcore.h \
+       getpagesize.h ieee-float.h inferior.h param-no-tm.h param.h \
+       signals.h signame.h symfile.h symtab.h \
+       target.h tdesc.h terminal.h tm-68k.h tm-i960.h tm-sunos.h \
+       value.h
+
+OPCODES = pn-opcode.h np1-opcode.h sparc-opcode.h vax-opcode.h m68k-opcode.h \
+         ns32k-opcode.h convex-opcode.h pyr-opcode.h mips-opcode.h \
+         am29k-opcode.h
+
+REMOTE_EXAMPLES = remote-sa.m68k.shar remote-multi.shar
+
+MALLOCSRC = gmalloc.c mcheck.c ansidecl.h stdlib.h gmalloc.h stddef.h
+GETOPTSRC = $(GETOPT_DIR)/getopt.c $(GETOPT_DIR)/getopt1.c
+
+POSSLIBS_MAINDIR = obstack.h obstack.c regex.c regex.h alloca.c \
+       $(MALLOCSRC)
+POSSLIBS = $(POSSLIBS_MAINDIR) $(GETOPTSRC)
+
+TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
+
+# tdesc-lib cannot be named simply tdesc, because if if it were GNU make
+# would try to make it from tdesc.c.
+# tdesc-lib removed from the list due to Motorola copyrights...gnu@cygnus.com
+OTHERS = Makefile.dist depend alldeps.mak Makefile.srcdir \
+        createtags munch config.gdb config.status \
+        ChangeLog ChangeLog-3.x \
+        README TODO TAGS WHATS.NEW \
+        gdb.texinfo gdb-int.texinfo gdbrc.tex threecol.tex \
+       .gdbinit COPYING expread.tab.c stab.def \
+        copying.c Projects Convex.notes copying.awk \
+        saber.suppress standalone.c stuff.c kdb-start.c \
+        hp-include # tests
+
+DEPFILES= ${TDEPFILES} ${XDEPFILES}
+
+SOURCES=$(SFILES) $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${OPCODES} ${ALLPARAM} ${POSSLIBS} 
+TAGFILES_MAINDIR = $(SFILES_MAINDIR) $(ALLDEPFILES_MAINDIR) \
+             ${HFILES} ${OPCODES} ${ALLPARAM} ${POSSLIBS_MAINDIR} 
+TARFILES = ${TAGFILES_MAINDIR} ${OTHERS} ${REMOTE_EXAMPLES}
+
+OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
+    values.o eval.o valops.o valarith.o valprint.o printcmd.o \
+    symtab.o symfile.o symmisc.o infcmd.o infrun.o remote.o \
+    command.o utils.o expread.o expprint.o environ.o version.o \
+    copying.o $(DEPFILES) signame.o cplus-dem.o mem-break.o target.o \
+    inftarg.o ieee-float.o \
+    dbxread.o coffread.o # mipsread.o
+
+RAPP_OBS = rgdb.o rudp.o rserial.o serial.o udp.o $(XDEPFILES)
+
+TSOBS = core.o inflow.o
+
+NTSOBS = standalone.o
+
+TSSTART = /lib/crt0.o
+
+NTSSTART = kdb-start.o
+
+RL_LIB = readline/libreadline.a
+RL_LIB_DEP = $(RL_LIB)
+
+# Prevent Sun make from putting in the machine type.  Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+       ${CC} -c ${CFLAGS} $<
+
+all: gdb
+
+install: gdb
+       cp gdb $(bindir)/gdb.new
+       mv $(bindir)/gdb.new $(bindir)/gdb
+       $(M_INSTALL)
+
+init.c: $(srcdir)/munch $(MUNCH_DEFINE) $(OBS) $(TSOBS)
+       $(srcdir)/munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) > init.c
+
+gdb: $(OBS) $(TSOBS) ${ADD_DEPS} ${RL_LIB_DEP} ${CDEPS} init.o
+       ${CC-LD} $(LDFLAGS) -o gdb init.o $(OBS) $(TSOBS) $(ADD_FILES) \
+       ${RL_LIB} $(CLIBS)
+
+saber_gdb: $(SFILES) $(GETOPTSRC) $(DEPFILES) copying.c obstack.c version.c
+       #setopt load_flags $(CFLAGS) -I$(BFD_DIR)
+       #load ./init.c $(SFILES)
+       #unload ${srcdir}/expread.y
+       #load ${srcdir}/expread.tab.c readline/libreadline.a
+       #load copying.c version.c
+       #load obstack.c $(GETOPTSRC)
+       #load `echo " "$(DEPFILES) | sed -e 's/\.o/.c/g' -e 's, , ../,g'`
+       #load ${BFD_DIR}/libbfd.a -ltermcap 
+       ##void mcheck(a) void (*a)(); { }
+
+
+
+# This is useful when debugging GDB, because some Unix's don't let you run GDB
+# on itself without copying the executable.  So "make gdb1" will make
+# gdb and put a copy in gdb1, and you can run it with "gdb gdb1".
+# Removing gdb1 before the copy is the right thing if gdb1 is open
+# in another process.
+gdb1: gdb
+       rm -f gdb1
+       cp gdb gdb1
+
+# This is a remote stub which runs under unix and starts up an
+# inferior process.  This is at least useful for debugging GDB's
+# remote support.
+rapp: $(RAPP_OBS)
+       rm -f rapp_init.c
+       ${srcdir}/munch ${RAPP_OBS} > rapp_init.c
+       ${CC-LD} $(LDFLAGS) -o $@ rapp_init.c $(RAPP_OBS)
+       
+Makefiles= Makefile.srcdir $(M_MAKEFILE) \
+       ${srcdir}/alldeps.mak ${srcdir}/Makefile.dist
+
+MAKE_MAKEFILE= echo "M_MAKEFILE=$(M_MAKEFILE)" | \
+       cat - ${Makefiles} ${srcdir}/depend >Makefile
+
+Makefile: $(Makefiles)
+       $(MAKE_MAKEFILE)
+
+alldeps.mak: ${srcdir}/tconfig ${srcdir}/xconfig
+       rm -f alldeps.mak alldeps.tmp allparam.tmp allconfig.tmp
+       for i in `ls -d ${srcdir}/tconfig/*[0-9A-Za-z] \
+          ${srcdir}/xconfig/*[0-9A-Za-z] | grep -v RCS` ; do \
+         echo $$i >>allconfig.tmp; \
+         awk <$$i ' \
+           $$1 == "TDEPFILES=" || $$1 == "XDEPFILES=" { \
+             for (i = 2; i <= NF; i++) \
+               print $$i >> "alldeps.tmp" ; \
+            } \
+           $$1 == "TM_FILE=" || $$1 == "XM_FILE=" { \
+             print $$2 >> "allparam.tmp" }' ; \
+       done
+       sort <alldeps.tmp | uniq | \
+         sed -e 's/arm-convert.o/arm-convert.s/' \
+             -e 's!^Onindy.o!nindy-share/Onindy.c!' \
+             -e 's!^nindy.o!nindy-share/nindy.c!' \
+             -e 's!ttybreak.o!nindy-share/ttybreak.c!' \
+             -e 's!ttyflush.o!nindy-share/ttyflush.c!' \
+             -e 's!xdr_ld.o!vx-share/xdr_ld.c!' \
+             -e 's!xdr_ptrace.o!vx-share/xdr_ptrace.c!' \
+             -e 's!xdr_rdb.o!vx-share/xdr_rdb.c!' \
+             -e 's!xdr_regs.o!vx-share/xdr_regs.c!' \
+             -e 's/\.o/.c/' \
+           >alldeps2.tmp
+       echo 'ALLDEPFILES = $$(ALLDEPFILES_MAINDIR) $$(ALLDEPFILES_SUBDIR)' \
+           >>alldeps.mak;
+       grep -v / alldeps2.tmp | \
+         awk 'BEGIN {printf "ALLDEPFILES_MAINDIR="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       grep / alldeps2.tmp | \
+         awk 'BEGIN {printf "ALLDEPFILES_SUBDIR="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       sort <allparam.tmp | uniq | awk 'BEGIN {printf "ALLPARAM="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       sort <allconfig.tmp | uniq | awk 'BEGIN {printf "ALLCONFIG="} \
+           NR == 0 {printf $$0;} \
+           NR != 0 {printf "\\\n" $$0} \
+           END {printf "\n\n"}' >>alldeps.mak;
+       rm -f alldeps.tmp alldeps2.tmp allparam.tmp allconfig.tmp
+
+# The sed script makes everything which depends on {x,t}m.h depend on
+# config.status as well, in case someone reconfigures gdb out from
+# under an already compiled gdb.
+depend: $(SOURCES) Makefile.dist
+       @echo Ignore errors about non-existent system-supplied include files
+       @echo for systems other than the one you are using.
+       @echo "If xm.h and tm.h don't exist, the error messages saying so"
+       @echo can safely be ignored.
+       @echo Also ignore parse errors in valops.c, and any errors in
+       @echo arm-convert.s.
+       -$(GCC) -MM $(CFLAGS) -I$(BFD_DIR) \
+           `ls $(SOURCES) | sort -u` >depend.tmp
+       <depend.tmp sed -e 's/ [xt]m.h/& config.status/g'  \
+         -e 's; vx-share/; $${srcdir}/vx-share/;g'  \
+         -e 's; nindy-share/; $${srcdir}/nindy-share/;g'  \
+         -e 's; $(INCLUDE_DIR)/; $(INCLUDE_DEP)/;g'  \
+         -e 's; [a-z0-9./]*bfd/; $(BFD_DEP)/;g'  \
+         -e 's; [a-z0-9./]*getopt/; $(GETOPT_DEP)/;g'  \
+         -e 's; \./; $${srcdir}/;g'  \
+         >depend
+       $(MAKE_MAKEFILE)
+       rm depend.tmp
+
+config.status:
+       @echo "You must configure gdb.  Look at the README file for details."
+       @false
+
+# These are not generated by "make depend" because they only are there
+# for some machines.
+tm-isi.h tm-sun3.h tm-news.h tm-hp300bsd.h tm-altos.h : tm-68k.h
+tm-hp300hpux.h tm-sun2.h tm-3b1.h : tm-68k.h
+xm-news1000.h : xm-news.h
+xm-i386-sv32.h : xm-i386.h
+tm-i386gas.h: tm-i386.h
+xm-sun4os4.h : xm-sparc.h
+tm-sun4os4.h : tm-sparc.h
+
+kdb : $(NTSSTART) $(OBS) $(NTSOBS) ${ADD_DEPS} ${RL_LIB_DEP}
+       rm -f init.c
+       $(srcdir)/munch ${MUNCH_DEFINE} $(OBS) $(NTSOBS) > init.c
+       $(CC) $(LDFLAGS) -c init.c $(CLIBS) 
+       ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o $(ADD_FILES) \
+       ${RL_LIB} -lc $(CLIBS)
+
+# Put the proper machine-specific files first.
+# createtags will edit the .o in DEPFILES into .c
+TAGS: ${TAGFILES}
+       $(srcdir)/createtags $(TM_FILE) ${XM_FILE} $(DEPFILES) ${TAGFILES}
+tags: TAGS
+
+# FIXME: Get alldeps.mak up to date, config.gdb none, THEN make gdb.tar.Z!
+gdb.tar.Z: ${TARFILES}
+       rm -f gdb.tar; rm -rf $(DIST)
+       cd readline ; make readline.tar
+       mkdir $(DIST)
+       cd $(DIST) ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
+       mkdir $(DIST)/readline
+       cd $(DIST)/readline ; tar xf ../../readline/readline.tar
+       mkdir $(DIST)/xconfig ${DIST}/tconfig
+       cd $(DIST)/tconfig ; \
+         for i in $(ALLCONFIG) ; do ln -s ../../$$i ../$$i ; done
+       mkdir $(DIST)/vx-share $(DIST)/nindy-share
+       cd $(DIST)/tconfig ; \
+         for i in $(SFILES_SUBDIR) $(ALLDEPFILES_SUBDIR); \
+           do ln -s ../../$$i ../$$i ; done
+       tar chf - $(DIST) | compress >gdb.tar.Z
+       rm -rf $(DIST)
+
+clean:
+       rm -f ${OBS} ${TSOBS} ${NTSOBS} ${ADD_FILES}
+       rm -f init.c init.o version.c
+       rm -f gdb core gdb.tar gdb.tar.Z make.log
+       rm -f gdb[0-9]
+       cd readline ; make clean
+
+distclean: clean expread.tab.c TAGS
+       rm -f tm.h xm.h config.status
+       rm -f y.output yacc.acts yacc.tmp
+       rm -f ${TESTS} Makefile
+
+realclean: clean
+       rm -f expread.tab.c TAGS
+       rm -f tm.h xm.h config.status
+       rm -f Makefile
+
+gdb.dvi : gdb.texinfo
+       tex gdb.texinfo
+       texindex gdb.??
+       tex gdb.texinfo
+
+# Make copying.c from COPYING
+copying.c : COPYING copying.awk
+       awk -f copying.awk < COPYING > copying.c
+
+version.c : Makefile.dist
+       echo 'char *version = "$(VERSION)";' >version.c
+
+${srcdir}/expread.tab.c : $(srcdir)/expread.y
+       @echo 'Expect 4 shift/reduce conflict.'
+       ${YACC} $(srcdir)/expread.y
+       mv y.tab.c ${srcdir}/expread.tab.c
+
+expread.o : ${srcdir}/expread.tab.c defs.h param.h symtab.h \
+            frame.h expression.h
+       $(CC) -c ${CFLAGS} `echo ${srcdir}/expread.tab.c | sed 's,^\./,,'`
+       mv expread.tab.o expread.o
+
+# dbxread, coffread, mipsread have dependencies on BFD header files.
+dbxread.o: ${srcdir}/dbxread.c
+       ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/dbxread.c
+
+coffread.o: ${srcdir}/coffread.c
+       ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/coffread.c
+
+mipsread.o: ${srcdir}/mipsread.c
+       ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/mipsread.c
+
+# Drag in the files that are in another directory.
+
+getopt1.o: $(GETOPT_DIR)/getopt1.c
+       ${CC} -c ${CFLAGS} $(GETOPT_DIR)/getopt1.c
+
+getopt.o: $(GETOPT_DIR)/getopt.c
+       ${CC} -c ${CFLAGS} $(GETOPT_DIR)/getopt.c
+
+xdr_ld.o: ${srcdir}/vx-share/xdr_ld.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_ld.c
+
+xdr_ptrace.o: ${srcdir}/vx-share/xdr_ptrace.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_ptrace.c
+
+xdr_rdb.o: ${srcdir}/vx-share/xdr_rdb.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_rdb.c
+
+xdr_regs.o: ${srcdir}/vx-share/xdr_regs.c
+       ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_regs.c
+
+nindy.o: ${srcdir}/nindy-share/nindy.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/nindy.c
+
+Onindy.o: ${srcdir}/nindy-share/Onindy.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/Onindy.c
+
+ttybreak.o: ${srcdir}/nindy-share/ttybreak.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/ttybreak.c
+
+ttyflush.o: ${srcdir}/nindy-share/ttyflush.c
+       ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/ttyflush.c
+
+tdesc-lib/libdc.o : force_update
+       cd tdesc-lib ; ${MAKE} "SYSV_DEFINE=${SYSV_DEFINE}"
+
+# In LOCAL_INCLUDES, -I${srcdir} is right if srcdir is an absolute path,
+# and -I../${srcdir} is right if it is relative (e.g. ".."), so search both.
+readline/libreadline.a : force_update
+       cd readline ; ${MAKE} "SYSV=${SYSV_DEFINE}"\
+               "VPATH=${srcdir}/readline:../${srcdir}/readline"\
+               "LOCAL_INCLUDES=-I../ -I${srcdir}/ -I../${srcdir}/"\
+               "DEBUG_FLAGS=${GLOBAL_CFLAGS}" "CC=${CC}" libreadline.a
+
+lint: $(LINTFILES)
+       $(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES)
+
+gdb.cxref: $(SFILES)
+       cxref -I. $(SFILES) >gdb.cxref
+
+force_update :
+
+# When used with GDB, the demangler should never look for leading underscores
+# because GDB strips them off during symbol read-in.  Thus -Dnounderscore.
+cplus-dem.o : cplus-dem.c
+       ${CC} -c -Dnounderscore `echo ${srcdir}/cplus-dem.c | sed 's,^\./,,'`
diff --git a/gdb/Makefile.srcdir b/gdb/Makefile.srcdir
new file mode 100755 (executable)
index 0000000..b5fb6b3
--- /dev/null
@@ -0,0 +1 @@
+srcdir=.
diff --git a/gdb/Projects b/gdb/Projects
new file mode 100644 (file)
index 0000000..b30d268
--- /dev/null
@@ -0,0 +1,97 @@
+
+        Suggested projects for aspiring or current GDB hackers
+        ======================================================
+
+    (You should probably chat with bug-gdb@cygnus.com to make sure that
+  no one else is doing the project you chose).
+
+Rewrite proceed, wait_for_inferior, and normal_stop to clean them up.
+Suggestions: 
+
+       1) Make each test in wait_for_inferior a seperate subroutine
+          call.
+       2) Combine wait_for_inferior and normal_stop to clean up
+          communication via global variables.
+       3) See if you can find some way to clean up the global
+          variables that are used; possibly group them by data flow
+          and information content?
+
+Work out some kind of way to allow running the inferior to be done as
+a sub-execution of, eg. breakpoint command lists.  Currently running
+the inferior interupts any command list execution.  This would require
+some rewriting of wait_for_inferior & friends, and hence should
+probably be done in concert with the above.
+
+Add function arguments to gdb user defined functions.
+
+Add convenience variables that refer to exec file, symbol file,
+selected frame source file, selected frame function, selected frame
+line number, etc.
+
+Add a "suspend" subcommand of the "continue" command to suspend gdb
+while continuing  execution of the subprocess.  Useful when you are
+debugging servers and you want to dodge out and initiate a connection
+to a server running under gdb.
+
+Work out and implement a reasonably general mechanism for multi-threaded
+processies.  There are parts of one implemented in convex-dep.c, if
+you want an example.
+
+Add stab information to allow reasonable debugging of inline functions
+(possibly they should show up on a stack backtrace?  With a note
+indicating that they weren't "real"?).
+
+Implement support for specifying arbitrary locations of stack frames
+(in practice, this usually requires specification of both the top and
+bottom of the stack frame (fp and sp), since you *must* retrieve the
+pc that was saved in the innermost frame).
+
+Modify the naked "until" command to step until past the current source
+line, rather than past the current pc value.  This is tricky simply
+because the low level routines have no way of specifying a multi-line
+step range, and there is no way of saying "don't print stuff when we
+stop" from above (otherwise could just call step many times).
+
+Modify the handling of symbols grouped through BINCL/EINCL stabs to
+allocate a partial symtab for each BINCL/EINCL grouping.  This will
+seriously decrease the size of inter-psymtab dependencies and hence
+lessen the amount that needs to be read in when a new source file is
+accessed. 
+
+Do an "x/i $pc" after each stepi or nexti.  
+
+Modify all of the disassemblers to use printf_filtered to get correct
+more filtering.
+
+Modify gdb to work correctly with Pascal.
+
+Rewrite macros that handle frame chaining and frameless functions.
+They should be able to tell the difference between start, main, and a
+frameless function called from main.
+
+Work out what information would need to be included in an executable
+by the compiler to allow gdb to debug functions which do not have a
+frame pointer.  Modify gdb and gcc to do this.
+
+When `attached' to a program (via either OS support or remote
+debugging), gdb should arrange to catch signals which the terminal
+might send, as it is unlikely that the program will be able to notice
+them.  SIGINT and SIGTSTP are obvious examples.
+
+Enhance the gdb manual with extra examples where needed.
+
+Arrange for list_command not to use decode_line_1 and thus not require
+symbols to be read in simply to read a source file.
+
+Allow patching of executables, a la "adb -w".
+
+Improve the target interface so that targets can be stacked; e.g. an
+exec file and a core file (memory references that the core file can't
+satisfy are directed to the exec file); those two plus a child process.
+The child doesn't let any refs through, but when the child terminates,
+you are back to debugging the core file -- you might even want to swap
+back and forth between the two, or between two core files.
+
+# Local Variables:
+# mode: text
+# End:
diff --git a/gdb/README b/gdb/README
new file mode 100644 (file)
index 0000000..999db4a
--- /dev/null
@@ -0,0 +1,259 @@
+This is GDB, the GNU source-level debugger, presently running under
+un*x.  This is a pre-alpha version of GDB version 4, and has NOT been
+extensively tested.  It surely has some bugs, both bugs that were
+present in version 3 and new bugs.  I have filed all the bug reports
+and fixes mailed to bug-gdb, and the fixes in particular will move
+into these sources as I find the time.
+
+             => THIS VERSION IS PARTICULARLY FRAGILE! <=
+
+       It depends on a preliminary version of a new "binary file
+       descriptor" library and a new global "include" directory, which
+       are packaged separately from GDB.  You must obtain, configure
+       and build this library manually, then configure and build gdb.
+       When building gdb's for multiple platforms, you must manually
+       rebuild the bfd library separately for each platform.  Yes, of
+       course, we are working on this!  FIXME!
+
+       Configure bfd for your host system by:
+
+               cd ../bfd
+               edit Makefile
+               make
+
+       Then you can cd ../gdb-whatever, and config and build gdb.
+
+This release moves the generic GNU include files, the BFD library,
+and the getopt routines into the parent directory of gdb.  The idea
+is that a variety of GNU tools can share a common copy of these things.
+
+A summary of features new since gdb-3.5 is in the file `WHATS.NEW'.
+
+The best way to build GDB, in my opinion, is in a subdirectory.  I use
+a naming convention "=XXX" where XXX is the machine type I'm building
+for.  Nothing depends on this, it's just how I remember which
+subdirectories are what.  So, once you have the BFD library built for
+that machine, you can do:
+
+       cd gdb-x.yy     (the directory where this README is)
+       mkdir =XXX      (e.g. mkdir =vax)
+       cd =XXX
+       ../config.gdb machine
+       make
+
+Machine is like "vax" or "sun4".  For more information type `../config.gdb'.
+
+Once you have done that, just `make' will do everything, producing an
+executable `gdb' in this directory.
+
+You can also build gdb binaries in a completely different directory from its 
+sources, by specifying "srcdir=YYY" to config.gdb, giving it an absolute
+or relative path to the source directory.  
+
+GDB can be used as a cross-debugger, running on a machine of one type
+while debugging a program running on a machine of another type.  You
+configure it this way by specifying `config.gdb host target' where host
+is where GDB runs, and target is where your program runs.
+
+If you want a new (current to this release) version of the manual, you
+will have to use the gdb.texinfo file provided with this distribution.
+For details see the texinfo manual (distributed with emacs and as a
+printed manual).
+
+About languages other than C...
+
+C++ support has been integrated into gdb.  GDB should work with FORTRAN
+programs (if you have problem, please send a bug report; note that you
+may have to refer to some FORTRAN variables with a trailing
+underscore), but I am not aware of anyone who is working on getting it
+to use the syntax of any language other than C or C++.  Pascal programs
+which use sets, subranges, file variables, or nested functions will not
+currently work.
+
+About kernel debugging...
+
+I have't done this myself so I can't really offer any advice.
+Remote debugging over serial lines is more like to be in a currently
+functioning state than the standalone gdb (kdb).  FIXME.
+
+About remote debugging...
+
+[This section seems to be out of date, I have never seen the "rapp"
+program, though I would like to.  FIXME.]
+`rapp' runs under unix and acts as a remote stub (like remote-multi.shar
+distributed with GDB version 3).  Currently it just works over UDP
+(network), not over a serial line.  To get it running
+* Compile GDB on the host machine as usual
+* Compile rapp on the target machine, giving for both host and target
+  the type of the target machine
+* Install "gdb" in /etc/services on both machines.
+
+This will get reworked before the initial release of 4.x.  FIXME.
+
+The two files remote-multi.shar and remote-sa.m68k.shar contain two
+examples of a remote stub to be used with remote.c.  The the -multi
+file is a general stub that can probably be running on various
+different flavors of unix to allow debugging over a serial line from
+one machine to another.  The remote-sa.m68k.shar is designed to run
+standalone on a 68k type cpu and communicate properley with the
+remote.c stub over a serial line.
+
+The files remote-eb.c and remote-nindy.c are two examples of remote
+interfaces for talking to existing ROM monitors (for the AMD 29000 and the
+Intel 960 repsectively).  There is also a remote interface for the
+VxWorks realtime kernel, which communicates over TCP/IP, in remote-vx.c
+and the vx-share subdirectory.
+
+About reporting bugs...
+
+The correct address for reporting bugs found with gdb is
+"bug-gdb@prep.ai.mit.edu".  Please email all bugs to that address.
+
+About xgdb...
+
+Hopefully a new xgdb will be in 4.x.
+
+xgdb.c was provided to us by the user community; it is not an integral
+part of the gdb distribution.  The problem of providing visual
+debugging support on top of gdb is peripheral to the GNU project and
+(at least right now) we can't afford to put time into it.  So while we
+will be happy to incorporate user fixes to xgdb.c, we do not guarantee
+that it will work and we will not fix bugs reported in it.  See
+XGDB-README for one person's opinion about what is wrong with the
+current xgdb.  Someone is working on writing a new XGDB, so improving
+(e.g. by fixing it so that it will work, if it doesn't currently) the
+current one is not worth it.
+
+For those intersted in auto display of source and the availability of
+an editor while debugging I suggest trying gdb-mode in gnu-emacs
+(Try typing M-x gdb RETURN).  Comments on this mode are welcome.
+
+About the machine-dependent files...
+
+tconfig/<machine>
+This contains Makefile stuff for when the target system is <machine>.
+It also specifies the name of the tm-XXX.h file for this machine.
+
+xconfig/<machine>
+This contains Makefile stuff for when the host system is <machine>.
+It also specifies the name of the xm-XXX.h file for this machine.
+
+tm-XXX.h (tm.h is a link to this file, created by config.gdb).
+This file contains macro definitions that express information
+about the target machine's registers, stack frame format and instructions.
+
+xm-XXX.h (xm.h is a link to this file, created by config.gdb).
+This contains macro definitions describing the host system environment,
+such as byte order, host C compiler and library, ptrace support,
+and core file structure.
+
+<machine>-opcode.h
+<machine>-pinsn.c
+These files contain the information necessary to print instructions
+for your cpu type.  <machine>-opcode.h includes some large initialized
+data structures, which is strange for a ".h" file, but it's OK since
+it is only included in one place.  <machine>-opcode.h is shared
+between the debugger and the assembler (if the GNU assembler has been
+ported to that machine), whereas <machine>-pinsn.c is specific to GDB.
+
+<machine>-tdep.c
+This file contains any miscellaneous code required for this machine
+as a target.  On some machines it doesn't exist at all.  Its existence
+is specified in the tconfig/XXX file.
+
+<machine>-xdep.c
+This file contains any miscellaneous code required for this machine
+as a host.  On some machines it doesn't exist at all.  Its existence
+is specified in the xconfig/XXX file.
+
+infptrace.c
+This is the low level interface to inferior processes for systems
+using the Unix ptrace call in a vanilla way.  Some systems have their
+own routines in <machine>-xdep.c.  Whether or not it is used
+is specified in the xconfig/XXX file.
+
+coredep.c
+Machine and system-dependent aspects of reading core files.  Some
+machines use coredep.c; some have the routines in <machine>-xdep.c.
+Whether or not it is used is specified in the xconfig/XXX file.
+Now that BFD is used to read core files, virtually all machines should
+use coredep.c and should just provide fetch_core_registers in
+<machine>-xdep.c.
+
+exec.c 
+Machine and system-dependent aspects of reading executable files.
+Some machines use exec.c; some have the routines in <machine>-tdep.c
+Since BFD, virtually all machines should use exec.c.
+
+About writing code for GDB...
+
+We appreciate having users contribute code that is of general use, but
+for it to be included in future GDB releases it must be cleanly
+written.  We do not want to include changes that will needlessly make
+future maintainance difficult.  It is not much harder to do things
+right, and in the long term it is worth it to the GNU project, and
+probably to you individually as well.
+
+Please code according to the GNU coding standards.  If you do not have
+a copy, you can request one by sending mail to gnu@prep.ai.mit.edu.
+
+If you make substantial changes, you'll have to file a copyright
+assignment with the Free Software Foundation before we can produce a
+release that includes your changes.  Send mail requesting the copyright
+assignment to gnu@prep.ai.mit.edu.  Do this early, like before the
+changes actually work, or even before you start them, because a manager
+or lawyer on your end will probably make this a slow process.
+
+Please try to avoid making machine-specific changes to
+machine-independent files.  If this is unavoidable, put a hook in the
+machine-independent file which calls a (possibly) machine-dependent
+macro (for example, the IGNORE_SYMBOL macro can be used for any
+symbols which need to be ignored on a specific machine.  Calling
+IGNORE_SYMBOL in dbxread.c is a lot cleaner than a maze of #if
+defined's).  The machine-independent code should do whatever "most"
+machines want if the macro is not defined in param.h.  Using #if
+defined can sometimes be OK (e.g.  SET_STACK_LIMIT_HUGE) but should be
+conditionalized on a specific feature of an operating system (set in
+tm.h or xm.h) rather than something like #if defined(vax) or #if
+defined(SYSV).  If you use an #ifdef on some symbol that is defined
+in a header file (e.g. #ifdef TIOCSETP), *please* make sure that you
+have #include'd the relevant header file in that module!
+
+It is better to replace entire routines which may be system-specific,
+rather than put in a whole bunch of hooks which are probably not going
+to be helpful for any purpose other than your changes.  For example,
+if you want to modify dbxread.c to deal with DBX debugging symbols
+which are in COFF files rather than BSD a.out files, do something
+along the lines of a macro GET_NEXT_SYMBOL, which could have
+different definitions for COFF and a.out, rather than trying to put
+the necessary changes throughout all the code in dbxread.c that
+currently assumes BSD format.
+
+Please avoid duplicating code.  For example, in GDB 3.x all the stuff
+in infptrace.c was duplicated in *-dep.c, and so changing something
+was very painful.  Thus in GDB 4.x these have all been consolidated
+into infptrace.c.  infptrace.c can deal with variations between
+systems the same way any system-independent file would (hooks, #if
+defined, etc.), and machines which are radically different don't need
+to use infptrace.c at all.  The same was true of core_file_command
+and exec_file_command.
+
+About debugging gdb with itself...
+
+You probably want to do a "make TAGS" after you configure your
+distribution; this will put the machine dependent routines for your
+local machine where they will be accessed first by a M-period .
+
+Also, make sure that you've compiled gdb with your local cc or taken
+appropriate precautions regarding ansification of include files.  See
+the Makefile for more information.
+
+When you run gdb in this directory, it will read a ".gdbinit" file that
+sets up some simple things to make debugging gdb easier.  The "info"
+command, when executed without a subcommand in a gdb being debugged by
+gdb, will pop you back up to the top level gdb.  See .gdbinit for details.
+\f
+(this is for editing this file with GNU emacs)
+Local Variables:
+mode: text
+End:
diff --git a/gdb/TODO b/gdb/TODO
new file mode 100644 (file)
index 0000000..93dce62
--- /dev/null
+++ b/gdb/TODO
@@ -0,0 +1,325 @@
+
+       gdb bug list
+       John Gilmore, gnu@cygnus.com
+
+This bug list is probably not up to date or accurate, but it reflects
+some known bugs in gdb, if you are into bug-hunting.
+
+
+Update the TODO list with all the lists of gdb bugs lying around on paper.
+
+"share" command should not need to be manually run.  It should be run
+as soon as possible, automatically, both on "run" and on core files.
+
+It should be possible to use symbols from shared libraries before we know
+exactly where the libraries will be loaded.  E.g. "b perror" before running
+the program.  This could maybe be done as an extension of the "breakpoint
+re-evaluation" after new symbols are loaded.
+
+Make single_step() insert and remove breakpoints in one operation.
+
+Speed up single stepping by avoiding extraneous ptrace calls.
+
+Speed up single stepping by not inserting and removing breakpoints
+each time the inferior starts and stops.
+
+Speed up watchpoints by not single-stepping them, but do something
+faster like single-line execution.
+
+Update gdb.texinfo to include doc on the directory structure and 
+the various tricks of building gdb.
+
+Do a tutorial in gdb.texinfo on how to do simple things in gdb.
+E.g. how to set a breakpoint that just prints something and continues.
+How to break on aborts.  Etc.
+
+Do a "new features" section for release 4.
+
+Provide "voodoo" debugging of core files.  This creates a zombie
+process as a child of the debugger, and loads it up with the data,
+stack, and regs of the core file.  This allows you to call functions
+in the executable, to manipulate the data in the core file.
+
+GDB reopens the source file on every line, as you "next" through it.
+
+Referencing the vtbl member of a struct doesn't work.  It prints OK
+if you print the struct, but it gets 0 if you try to deref it.
+
+Persistent command history: A feature where you could save off a list
+of the commands you did, so you can edit it into something that will bring
+the target to the same place every time you source it.  Sun wants it.
+This would also be useful for automated fast watchpointing; if you go
+past the place where it watchpoints, you just start it over again and
+do it more carefully.
+
+Deal with the Sun ptrace bug that loses the registers if the stack is
+paged out.
+
+Finish the C++ exception handling stub routines.  Lint points them out
+as unused statics functions.
+
+"i source" only shows you info about files that it can read.  When it
+can't read a file and complains, you can't see any info about it, like
+where it was compiled.  Perhaps "i source" should take an argument
+like that of "list".
+
+See if coredep.c's fetch_core_registers can be used on more machines.
+E.g. MIPS (mips-xdep.c).
+
+coredep.c is completely broken.  Needs work just to compile, it uses
+"u" and doesn't declare it, etc.
+
+unpack_double() does not handle IEEE float on the target unless the host
+is also IEEE.  Death on a vax.
+
+Test cross-debugging Unix-to-Unix.
+
+Check the RAPP remote protocol.  What is it?  It's in Makefile.dist
+and one ChangeLog entry.
+
+Set up interface between GDB and INFO so that you can hop into interactive
+INFO and back out again.  When running under Emacs, should use Emacs
+info, else fork the info program.  Installation of GDB should install
+its texinfo files into the info tree automagically, including the readline
+texinfo files..
+
+Improve backtrace output to avoid line wraps.  Prettify it.
+
+"help address" ought to find the "help set addressprint" entry.
+
+Remove the VTBL internal guts from printouts of C++ structs, unless
+vtblprint is set.
+
+Remove "at 0xnnnn" from the "b foo" response, if !addressprint and if
+it matches the source line indicated.
+
+The prompt at end of screen should accept space as well as CR.
+
+"List" should put you into a pseudo-"more" where you can hit space 
+to get more, forever to eof.
+
+Check STORE_RETURN_VALUE on all architectures.  Check near it in tm-sparc.h
+for other bogosities.
+
+Check for storage leaks in GDB, I'm sure there are a lot!
+
+vtblprint of a vtbl should demangle the names it's printing.
+
+Backtrace should point out what the currently selected frame is, in its
+display, perhaps showing ">3 foo (bar, ...)" rather than "#3 foo (bar, ...)".
+
+"i program" should work for core files, and display more info, like what
+actually caused it to die.
+
+Hitting ^Z to an inferior doesn't work right, it takes several continues
+to make it actually go.
+
+"i fun" doesn't show misc function vector symbols.
+
+"x/10i" should shorten the long name, if any, on subsequent lines.
+
+Check through the code for FIXME comments and fix them.  dbxread.c,
+blockframe.c, and plenty more.
+
+"next" over a function that longjumps, never stops until next time you happen
+to get to that spot by accident.  E.g. "n" over execute_command which has
+an error.
+
+Watchpoints seem not entirely reliable.
+
+"set zeroprint off", don't bother printing members of structs which are entirely
+zero.  Useful for those big structs with few useful members.
+
+GDB does four ioctl's for every command, probably switching terminal modes
+to/from inferior or for readline or something.
+
+terminal_ours versus terminal_inferior: cache state.  Switch should be a noop
+if the state is the same, too.
+
+ptype $i6 = void??!
+
+Clean up invalid_float handling so gdb doesn't coredump when it tries to
+access a NaN.  While this might work on SPARC, other machines are not
+configured right.
+
+"b value_at ; commands ; continue ; end" stops EVERY OTHER TIME!
+Then once you enter a command, it does the command, runs two more
+times, and then stops again!  Bizarre...  (This behaviour has been
+modified, but it is not yet 100% predictable when e.g. the commands
+call functions in the child, and while there, the child is interrupted
+with a signal, or hits a breakpoint.)
+
+Symbol completion with TAB does not unmangle names!
+
+help completion, help history should work.
+
+Symbol completion doesn't handle e.g. W::f.  (symtab.c,
+make_symbol_completion_list).
+
+AMD version: ^C should do ^Ak to stop ebmon.
+
+Check that we can handle stack trace through varargs AND alloca in same
+function, on 29K.
+
+wait_for_inferior loops forever if wait() gives it an error.
+
+"i frame" arg formatting sucks.  Should wrap lines.
+"bt" arg formatting needs the same treatment .
+
+"i frame" shows wrong "arglist at" location, doesn't show where the args
+should be found, only their actual values.
+
+Symbolic display of addrs, (& disassembly prefixes), don't show static
+fns, e.g. enable_command in gdb.
+
+'ptype yylval' ==> "union YYSTYPE { ..... }".  However, it is not a
+union YYSTYPE, but is simply a YYSTYPE, which is a typedef for an
+unnamed union.
+
+"show all" should work.
+
+There should be a way for "set" commands to validate the new setting
+before it takes effect.
+
+The "display" command should become the "always" command, e.g.
+       "always print XXX"
+       "always p/xxx XXX"
+       "always echo foo"
+       "always call XXX"
+       "always x/i $pc", etc.
+
+A mess of floating point opcodes are missing from sparc-opcode.h.
+Also, a little program should test the table for bits that are
+overspecified or underspecified.  E.g. if the must-be-ones bits
+and the must-be-zeroes bits leave some fields unexamined, and the format
+string leaves them unprinted, then point this out.  If multiple
+non-alias patterns match, point this out too.  Finally, there should
+be a sparc-optest.s file that tries each pattern out.  This file
+should end up coming back the same (modulo transformation comments) 
+if fed to "gas" then the .o is fed to gdb for disassembly.
+
+Merge the xxx-opcode.h files with gas again...
+
+Eliminate all the core_file_command's in all the xdep files.
+Eliminate separate declarations of registers[] everywhere.
+
+"ena d" is ambiguous, why?  "ena delete" seems to think it is a command!
+
+Line numbers are off in some spots.  In proceed() at 1st "oneproc = 1",
+it seems to run that statement, but it doesn't actually.
+
+Perhaps the tdep and xdep files, and the tm and xm files, into a config
+subdirectory.  If not, at least straighten out their names so that
+they all start with the machine name.
+
+inferior_status should include stop_print_frame.  It won't need to be
+reset in wait_for_inferior after bpstat_stop_status call, then.
+
+i line VAR produces "Line number not known for symbol ``var''.".  I
+thought we were stashing that info now!
+
+Make sure we can handle executables with no symbol info, e.g. /bin/csh.
+
+We should be able to write to executables that aren't running.
+
+We should be able to write to random files at hex offsets like adb.
+
+Tiemann:  It is very painful to look at fp registers that hold
+double precision values.  GDB is happy to show them to you as single
+precision, but you cannot look at them as doubles.  Perhaps casting
+should be changed to make this work; or maybe a new "set" option that
+sets the default fp precision to single, double, or quad.  This is not
+urgent, but would be nice to get into GDB 4.0.
+
+Make "target xxx" command interruptible.
+
+Handle add_file with separate text, data, and bss addresses.  Maybe
+handle separate addresses for each segment in the object file?
+
+Handle free_named_symtab to cope with multiply-loaded object files
+in a dynamic linking environment.  Should remember the last copy loaded,
+but not get too snowed if it finds references to the older copy.
+
+Implement have_memory, have_stack, have_registers, have_execution.
+Memory:  core, exec, child, vxworks even without child.
+stack:   core, child, vxworks with child
+registers:  core, child, vxworks with child
+execution:  child, vxworks with child.
+
+The original BFD core dump reading routine would itself coredump when fed
+a garbage file as a core file.  Does the current one?
+
+Breakpoints should not be inserted and deleted all the time.  Only the
+one(s) there should be removed when we have to step over one.  Support
+breakpoints that don't have to be removed to step over them.
+
+Stop reading stop_registers!
+
+Generalize and Standardize the RPC interface to a target program,
+improve it beyond the "ptrace" interface, and see if it can become a standard
+for remote debugging.  Is WRS interested in donating their target-end
+code?
+
+Remove all references to:
+       text_offset
+       data_offset
+       text_data_start
+       text_end
+       exec_data_offset
+       ...
+now that we have BFD.  All remaining are in machine dependent files.
+
+When quitting with a running program, if a core file was previously
+examined, you get "Couldn't read float regs from core file"...if 
+indeed it can't.  generic_mourn_inferior...
+
+...
+
+Check signal argument to remote proceed's and error if set.
+
+Handle floating point registers in core files under BFD.  Currently
+they are punted.
+
+Sort help and info output.
+
+Re-organize help categories into things that tend to fit on a screen
+and hang together.
+
+When trying to print source lines but you can't find the file,
+print the file name and line number, and leave it selected anyway
+so "i source" will show it.
+
+renote-nindy.c handles interrupts poorly; it error()s out of badly
+chosen places, e.g. leaving current_frame zero, which causes core dumps
+on the next command.
+
+Add in commands like ADB's for searching for patterns, etc.  We should
+be able to examine and patch raw unsymboled binaries as well in gdb as
+we can in adb.  (E.g. increase the timeout in /bin/login without source).
+
+Those xdep files that call register_addr without defining it are
+probably simply broken.  When reconfiguring this part of gdb, I could
+only make guesses about how to redo some of those files, and I
+probably guessed wrong, or left them "for later" when I have a
+machine that can attempt to build them.
+
+Use the complain() mechanism for handling all the error() calls in dbxread.c,
+and in similar situations in coffread.c and mipsread.c.
+
+When doing "step" or "next", if a few lines of source are skipped between
+the previous line and the current one, print those lines, not just the
+last line of a multiline statement.
+
+When searching for C++ superclasses in value_cast in valops.c, we must
+not search the "fields", only the "superclasses".  There might be a
+struct with a field name that matches the superclass name.  This can
+happen when the struct was defined before the superclass (before the
+name became a typedef).
+
+For "float point[15];":
+ptype &point[4]   ==> Attempt to take address of non-lvalue.
+p     &point[4]   ==> Dereferences point[4] rather than giving you point+4.
+
+Fix symbol reading in the presence of interrupts.  It currently leaves a
+cleanup to blow away the entire symbol table when a QUIT occurs.
+
diff --git a/gdb/WHATS.NEW b/gdb/WHATS.NEW
new file mode 100755 (executable)
index 0000000..97b0415
--- /dev/null
@@ -0,0 +1,223 @@
+               GDB 4.0 -- what has changed since 3.5?
+
+ *  New Facilities
+
+Gdb now paginates its output, with a ``more''-like interface.  You can
+set the screen width and screen height with new ``set'' commands; they
+default to your terminal settings.  Wide output is wrapped at good
+places to make the output more readable.
+
+Gdb now reads its input via the ``readline'' interface.  This provides
+inline editing of commands, using familiar Emacs or VI commands (like
+``tcsh'' or the korn shell); history substitutions a la the C shell;
+and storage and recall of your command history across debugging
+sessions.  The default is Emacs mode; to switch temporarily to vi mode,
+use control-meta-J or ESC control-j.  You can switch permanently to vi
+mode by putting the line ``set editing-mode vi'' in the file .inputrc
+in your home directory.   For full details, see the description in
+readline/inc-readline.texinfo and readline/inc-history.texinfo.
+
+Gdb now supports cross-debugging from a host machine of one type to a
+target machine of another type.  Communication with the target system
+is over serial lines.  The ``target'' command handles connecting to the
+remote system; the ``load'' command will download a program into the
+remote system.  It also supports debugging of realtime processes
+running under VxWorks, using SunRPC Remote Procedure Calls over TCP/IP
+to talk to a debugger stub on the target system.
+
+New CPUs supported include the AMD 29000 and Intel 960.
+
+GDB now reads object files and symbol tables via a ``binary file'' 
+library, which allows a single copy of GDB to debug programs of multiple
+object file types such as a.out and coff.
+
+There is now a GDB reference card in "gdbrc.tex".
+
+
+ *  Control-Variable user interface simplified
+
+All variables that control the operation of the debugger can be set
+by the ``set'' command, and displayed by the ``show'' command.
+
+For example, ``set prompt new-gdb=>'' will change your prompt to new-gdb=>.
+``Show prompt'' produces the response:
+Gdb's prompt is new-gdb=>.
+
+What follows are the NEW set commands.  The command ``help set'' will
+print a complete list of old and new set commands.  ``help set FOO''
+will give a longer description of the variable FOO.
+
+caution on/off:  Enables warning questions for operations that are
+                hard to recover from, e.g. rerunning the program while
+                it is already running.  Default is ON.
+
+editing on/off:  Enables EMACS style command line editing 
+                 of input.  Previous lines can be recalled with 
+                control-P, the current line can be edited with control-B,
+                you can search for commands with control-R, etc.
+                Default is ON.
+
+history filename NAME:  NAME is where the gdb command history 
+                       will be stored.  The default is .gdb_history,
+                       or the value of the environment variable
+                       GDBHISTFILE.
+
+history size N:  The size, in commands, of the command history.  The 
+                default is 256, or the value of the environment variable
+                HISTSIZE.
+
+history write on/off: If this value is set to ON, the history file will
+                     be saved after exiting gdb.  If set to OFF, the 
+                     file will not be saved.  The default is OFF.
+
+history expansion on/off: If this value is set to ON, then csh-like 
+                         history expansion will be performed  on 
+                         command line input.  The default is OFF.
+
+radix N:  Sets the default radix for input and output.  It can be set
+         to 8, 10, or 16.  Note that the argument to "radix" is interpreted
+         in the current radix, so "set radix 10" is always a no-op.
+
+screen-height N: This integer value is the number of lines on a page. Default
+                 is 24, the current `stty rows'' setting, or the ``li#''
+                setting from the termcap entry matching the environment
+                variable TERM.
+
+screen-width N:  This integer value is the number of characters on a line.
+                Default is 80, the current `stty cols'' setting, or the ``co#''
+                setting from the termcap entry matching the environment
+                variable TERM.
+
+Note: ``set screensize'' is obsolete. Use ``set screen-height'' and
+``set screen-width'' instead.
+
+addressprint on/off:  Print memory addresses in various command displays,
+                     such as stack traces and structure values.  Gdb looks
+                     more ``symbolic'' if you turn this off; it looks more
+                     ``machine level'' with it on.  Default is ON.
+
+arrayprint on/off:  Prettyprint arrays.  New convenient format!  Default 
+                    is OFF.
+
+demangle on/off:   Print C++ symbols in "source" form if on, "raw" form if off.
+
+asm-demangle on/off:  Same, for assembler level printouts like instructions.
+
+vtblprint on/off:  Prettyprint C++ virtual function tables.  Default is OFF.
+
+
+ *  Support for Epoch Environment.
+
+The epoch environment is a version of Emacs v18 with windowing.  One
+new command, ``inspect'', is identical to ``print'', except that if you
+are running in the epoch environment, the value is printed in its own
+window.
+
+
+ *  Support for Shared Libraries
+
+GDB can now debug programs and core files that use SunOS shared libraries.
+Symbols from a shared library cannot be referenced
+before the shared library has been linked with the program (this
+happens after you type ``run'' and before the function main() is entered).
+At any time after this linking (including when examining core files
+from dynamically linked programs), gdb reads the symbols from each
+shared library when you type the ``sharedlibrary'' command.
+It can be abbreviated ``share''.
+
+sharedlibrary REGEXP:  Load shared object library symbols for files 
+                       matching a unix regular expression.  No argument
+                      indicates to load symbols for all shared libraries.
+
+info sharedlibrary:  Status of loaded shared libraries.
+
+
+ *  Watchpoints
+
+A watchpoint stops execution of a program whenever the value of an
+expression changes.  Checking for this slows down execution
+tremendously whenever you are in the scope of the expression, but is
+quite useful for catching tough ``bit-spreader'' or pointer misuse
+problems.  Some machines such as the 386 have hardware for doing this
+more quickly, and future versions of gdb will use this hardware.
+
+watch EXP:  Set a watchpoint (breakpoint) for an expression.
+
+info watchpoints:  Information about your watchpoints.
+
+delete N:   Deletes watchpoint number N (same as breakpoints).
+disable N:  Temporarily turns off watchpoint number N (same as breakpoints).
+enable N:   Re-enables watchpoint number N (same as breakpoints).
+
+
+ *  C++ multiple inheritance
+
+When used with a GCC version 2 compiler, GDB supports multiple inheritance
+for C++ programs.
+
+ *  C++ exception handling
+
+Gdb now supports limited C++ exception handling.  Besides the existing
+ability to breakpoint on an exception handler, gdb can breakpoint on
+the raising of an exception (before the stack is peeled back to the
+handler's context).
+
+catch FOO:  If there is a FOO exception handler in the dynamic scope,
+           set a breakpoint to catch exceptions which may be raised there.
+           Multiple exceptions (``catch foo bar baz'') may be caught.
+
+info catch:  Lists all exceptions which may be caught in the
+             current stack frame.
+
+
+ *  Minor command changes
+
+The command ``call func (arg, arg, ...)'' now acts like the print
+command, except it does not print or save a value if the function's result
+is void.  This is similar to dbx usage.
+
+The ``up'' and ``down'' commands now always print the frame they end up
+at; ``up-silently'' and `down-silently'' can be used in scripts to change
+frames without printing.
+
+ *  New directory command
+
+'dir' now adds directories to the FRONT of the source search path.
+The path starts off empty.  Source files that contain debug information
+about the directory in which they were compiled can be found even
+with an empty path; GCC includes this information.  If GDB can't find
+your source file in the current directory, type "dir .".
+
+ *  Features removed in this release
+
+``info types'' has been removed, since it printed builtin types in a
+confusing fashion, and did not do useful things with typedefs.  ``ptype''
+or ``whatis'' are more useful commands for dealing with types..
+
+
+ * Configuring GDB for compilation
+
+For normal use, type ``config.gdb host''.  Hosts now handled are:
+
+3b1 altos altosgas arm bigmips convex hp300bsd hp300hpux i386v i386v-g 
+i386v32 i386v32-g isi littlemips m88k merlin news news1000 none np1 pn
+pyramid sun2os3 sun2os4 sun386 sun3os3 sun3os4 sun4os3 sun4os4 symmetry
+umax vax
+
+Type config.gdb +host to get a full description of each host.
+
+You can now build gdb conveniently for several architectures from the
+same sources.  If config.gdb is run from a subdirectory, it configures
+the Makefile to use source files from '..'.  Each subdirectory can be
+indpendently configured.  An explicit source file directory can also
+be specified with the +srcdir=xxx option.  Due to obscure search rules
+in the C preprocessor, if you have previously built gdb in the main 
+directory, run 'make cleanconfig' in the top level directory before
+building it in a subdirectory.
+
+GDB now handles cross debugging.  If you are remotely debugging between 
+two different machines, type ``config.gdb host target''.
+Host is the machine where gdb will run; target is the machine
+where the program that you are debugging will run.
+
+Type config.gdb +target to get a full description of each target.
diff --git a/gdb/alldeps.mak b/gdb/alldeps.mak
new file mode 100644 (file)
index 0000000..73e6cb8
--- /dev/null
@@ -0,0 +1,196 @@
+ALLDEPFILES = $(ALLDEPFILES_MAINDIR) $(ALLDEPFILES_SUBDIR)
+ALLDEPFILES_MAINDIR=\
+altos-xdep.c\
+am29k-pinsn.c\
+am29k-tdep.c\
+arm-convert.s\
+arm-pinsn.c\
+arm-tdep.c\
+arm-xdep.c\
+convex-pinsn.c\
+convex-tdep.c\
+convex-xdep.c\
+coredep.c\
+exec.c\
+gould-pinsn.c\
+gould-xdep.c\
+hp300hpux-xdep.c\
+i386-pinsn.c\
+i386-tdep.c\
+i386-xdep.c\
+i960-pinsn.c\
+i960-tdep.c\
+infptrace.c\
+m68k-pinsn.c\
+m68k-tdep.c\
+mips-pinsn.c\
+mips-tdep.c\
+mips-xdep.c\
+mipsread.c\
+news-xdep.c\
+nindy-tdep.c\
+ns32k-pinsn.c\
+pyr-pinsn.c\
+pyr-tdep.c\
+pyr-xdep.c\
+remote-eb.c\
+remote-nindy.c\
+remote-vx.c\
+solib.c\
+sparc-pinsn.c\
+sparc-tdep.c\
+sparc-xdep.c\
+sun3-xdep.c\
+sun386-xdep.c\
+symmetry-tdep.c\
+symmetry-xdep.c\
+tdesc.c\
+umax-xdep.c\
+vax-pinsn.c
+
+ALLDEPFILES_SUBDIR=\
+nindy-share/Onindy.c\
+nindy-share/nindy.c\
+nindy-share/ttybreak.c\
+nindy-share/ttyflush.c\
+vx-share/xdr_ld.c\
+vx-share/xdr_ptrace.c\
+vx-share/xdr_rdb.c\
+vx-share/xdr_regs.c
+
+ALLPARAM=\
+tm-29k.h\
+tm-3b1.h\
+tm-88k.h\
+tm-altos.h\
+tm-altosgas.h\
+tm-arm.h\
+tm-bigmips.h\
+tm-convex.h\
+tm-hp300bsd.h\
+tm-hp300hpux.h\
+tm-i386v-g.h\
+tm-i386v.h\
+tm-isi.h\
+tm-merlin.h\
+tm-mips.h\
+tm-news.h\
+tm-nindy960.h\
+tm-np1.h\
+tm-pn.h\
+tm-pyr.h\
+tm-sparc.h\
+tm-sun2.h\
+tm-sun2os4.h\
+tm-sun3.h\
+tm-sun386.h\
+tm-sun3os4.h\
+tm-sun4os4.h\
+tm-symmetry.h\
+tm-umax.h\
+tm-vax.h\
+tm-vxworks68.h\
+tm-vxworks960.h\
+xm-3b1.h\
+xm-88k.h\
+xm-altos.h\
+xm-arm.h\
+xm-bigmips.h\
+xm-convex.h\
+xm-hp300bsd.h\
+xm-hp300hpux.h\
+xm-i386v.h\
+xm-i386v32.h\
+xm-isi.h\
+xm-merlin.h\
+xm-mips.h\
+xm-news.h\
+xm-news1000.h\
+xm-np1.h\
+xm-pn.h\
+xm-pyr.h\
+xm-sparc.h\
+xm-sun2.h\
+xm-sun3.h\
+xm-sun386.h\
+xm-sun3os4.h\
+xm-sun4os4.h\
+xm-symmetry.h\
+xm-umax.h\
+xm-vax.h
+
+ALLCONFIG=\
+./tconfig/3b1\
+./tconfig/altos\
+./tconfig/altosgas\
+./tconfig/am29k\
+./tconfig/arm\
+./tconfig/bigmips\
+./tconfig/convex\
+./tconfig/hp300bsd\
+./tconfig/hp300hpux\
+./tconfig/i386v\
+./tconfig/i386v-g\
+./tconfig/i386v32\
+./tconfig/i386v32-g\
+./tconfig/i960\
+./tconfig/isi\
+./tconfig/littlemips\
+./tconfig/m88k\
+./tconfig/merlin\
+./tconfig/news\
+./tconfig/news1000\
+./tconfig/nindy960\
+./tconfig/none\
+./tconfig/np1\
+./tconfig/pn\
+./tconfig/pyramid\
+./tconfig/sun2os3\
+./tconfig/sun2os4\
+./tconfig/sun3\
+./tconfig/sun386\
+./tconfig/sun3os3\
+./tconfig/sun3os4\
+./tconfig/sun4\
+./tconfig/sun4os3\
+./tconfig/sun4os4\
+./tconfig/symmetry\
+./tconfig/umax\
+./tconfig/vax\
+./tconfig/vxworks68\
+./tconfig/vxworks960\
+./xconfig/3b1\
+./xconfig/altos\
+./xconfig/altosgas\
+./xconfig/arm\
+./xconfig/bigmips\
+./xconfig/convex\
+./xconfig/hp300bsd\
+./xconfig/hp300hpux\
+./xconfig/i386v\
+./xconfig/i386v-g\
+./xconfig/i386v32\
+./xconfig/i386v32-g\
+./xconfig/isi\
+./xconfig/littlemips\
+./xconfig/m88k\
+./xconfig/merlin\
+./xconfig/news\
+./xconfig/news1000\
+./xconfig/none\
+./xconfig/np1\
+./xconfig/pn\
+./xconfig/pyramid\
+./xconfig/sun2os3\
+./xconfig/sun2os4\
+./xconfig/sun3\
+./xconfig/sun386\
+./xconfig/sun3os3\
+./xconfig/sun3os4\
+./xconfig/sun4\
+./xconfig/sun4os3\
+./xconfig/sun4os4\
+./xconfig/symmetry\
+./xconfig/umax\
+./xconfig/vax
+
diff --git a/gdb/alloca.c b/gdb/alloca.c
new file mode 100644 (file)
index 0000000..d5de3de
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+       alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+       last edit:      86/05/30        rms
+          include config.h, since on VMS it renames some symbols.
+          Use xmalloc instead of malloc.
+
+       This implementation of the PWB library alloca() function,
+       which is used to allocate space off the run-time stack so
+       that it is automatically reclaimed upon procedure exit, 
+       was inspired by discussions with J. Q. Johnson of Cornell.
+
+       It should work under any C implementation that uses an
+       actual procedure stack (as opposed to a linked list of
+       frames).  There are some preprocessor constants that can
+       be defined when compiling for your specific system, for
+       improved efficiency; however, the defaults should be okay.
+
+       The general concept of this implementation is to keep
+       track of all alloca()-allocated blocks, and reclaim any
+       that are found to be deeper in the stack than the current
+       invocation.  This heuristic does not reclaim storage as
+       soon as it becomes invalid, but it will do so eventually.
+
+       As a special case, alloca(0) reclaims storage without
+       allocating any.  It is a good idea to use alloca(0) in
+       your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char    SCCSid[] = "@(#)alloca.c        1.1";   /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif static
+#endif emacs
+
+#ifdef __STDC__
+typedef void   *pointer;               /* generic pointer type */
+#else
+typedef char   *pointer;               /* generic pointer type */
+#endif
+
+#define        NULL    0                       /* null pointer constant */
+
+extern void    free();
+extern pointer xmalloc();
+
+/*
+       Define STACK_DIRECTION 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
+*/
+
+#ifndef STACK_DIRECTION
+#define        STACK_DIRECTION 0               /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define        STACK_DIR       STACK_DIRECTION /* known at compile-time */
+
+#else  /* STACK_DIRECTION == 0; need run-time code */
+
+static int     stack_dir;              /* 1 or -1 once known */
+#define        STACK_DIR       stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+  static char  *addr = NULL;   /* address of first
+                                  `dummy', once known */
+  auto char    dummy;          /* to get stack address */
+
+  if (addr == NULL)
+    {                          /* initial entry */
+      addr = &dummy;
+
+      find_stack_direction (); /* recurse once */
+    }
+  else                         /* second entry */
+    if (&dummy > addr)
+      stack_dir = 1;           /* stack grew upward */
+    else
+      stack_dir = -1;          /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+       An "alloca header" is used to:
+       (a) chain together all alloca()ed blocks;
+       (b) keep track of stack depth.
+
+       It is very important that sizeof(header) agree with malloc()
+       alignment chunk size.  The following default should work okay.
+*/
+
+#ifndef        ALIGN_SIZE
+#define        ALIGN_SIZE      sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];      /* to force sizeof(header) */
+  struct
+    {
+      union hdr *next;         /* for chaining headers */
+      char *deep;              /* for stack depth measure */
+    } h;
+} header;
+
+/*
+       alloca( size ) returns a pointer to at least `size' bytes of
+       storage which will be automatically reclaimed upon exit from
+       the procedure that called alloca().  Originally, this space
+       was supposed to be taken from the current stack frame of the
+       caller, but that method cannot be made to work for some
+       implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size)                  /* returns pointer to storage */
+     unsigned  size;           /* # bytes to allocate */
+{
+  auto char    probe;          /* probes stack depth: */
+  register char        *depth = &probe;
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)          /* unknown growth direction */
+    find_stack_direction ();
+#endif
+
+                               /* Reclaim garbage, defined as all alloca()ed storage that
+                                  was allocated from deeper in the stack than currently. */
+
+  {
+    register header    *hp;    /* traverses linked list */
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if (STACK_DIR > 0 && hp->h.deep > depth
+         || STACK_DIR < 0 && hp->h.deep < depth)
+       {
+         register header       *np = hp->h.next;
+
+         free ((pointer) hp);  /* collect garbage */
+
+         hp = np;              /* -> next header */
+       }
+      else
+       break;                  /* rest are not deeper */
+
+    last_alloca_header = hp;   /* -> last valid storage */
+  }
+
+  if (size == 0)
+    return NULL;               /* no allocation required */
+
+  /* Allocate combined header + user data storage. */
+
+  {
+    register pointer   new = xmalloc (sizeof (header) + size);
+    /* address of header */
+
+    ((header *)new)->h.next = last_alloca_header;
+    ((header *)new)->h.deep = depth;
+
+    last_alloca_header = (header *)new;
+
+    /* User storage begins just after header. */
+
+    return (pointer)((char *)new + sizeof(header));
+  }
+}
+
diff --git a/gdb/altos-xdep.c b/gdb/altos-xdep.c
new file mode 100644 (file)
index 0000000..1949c8d
--- /dev/null
@@ -0,0 +1,166 @@
+/* Low level interface to ptrace, for GDB when running under m68k SVR2 Unix
+   on Altos 3068.  Report bugs to Jyrki Kuoppala <jkp@cs.hut.fi>
+   Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#ifdef USG
+#include <sys/page.h>
+#ifdef ALTOS
+#include <sys/net.h>
+#include <errno.h>
+#endif
+#endif
+
+#include "gdbcore.h"
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+       struct user u;
+
+       unsigned int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name ("Not a core file: reading upage");
+       if (val != sizeof u)
+         error ("Not a core file: could only read %d bytes", val);
+       data_start = exec_data_start;
+
+#if !defined (NBPG)
+#define NBPG NBPP
+#endif
+#if !defined (UPAGES)
+#define UPAGES USIZE
+#endif
+
+       data_end = data_start + NBPG * u.u_dsize;
+       stack_start = stack_end - NBPG * u.u_ssize;
+       data_offset = NBPG * UPAGES + exec_data_start % NBPG /* Not sure about this //jkp */;
+       stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+       /* Some machines put an absolute address in here and some put
+          the offset in the upage of the regs.  */
+       reg_offset = (int) u.u_state;
+       if (reg_offset > NBPG * UPAGES)
+         reg_offset -= KERNEL_U_ADDR;
+
+       bcopy (&u.u_exdata, &core_aouthdr, sizeof (AOUTHDR));
+       printf ("Core file is from \"%s\".\n", u.u_comm);
+
+       /* I don't know where to find this info.
+          So, for now, mark it as not available.  */
+       N_SET_MAGIC (core_aouthdr, 0);
+
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < NUM_REGS; regno++)
+           {
+             char buf[MAX_REGISTER_RAW_SIZE];
+
+             val = lseek (corechan, register_addr (regno, reg_offset), 0);
+             if (val < 0
+                 || (val = myread (corechan, buf, sizeof buf)) < 0)
+               {
+                 char * buffer = (char *) alloca (strlen (reg_names[regno])
+                                                  + 30);
+                 strcpy (buffer, "Reading register ");
+                 strcat (buffer, reg_names[regno]);
+                                                  
+                 perror_with_name (buffer);
+               }
+
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
diff --git a/gdb/am29k-opcode.h b/gdb/am29k-opcode.h
new file mode 100644 (file)
index 0000000..96aff40
--- /dev/null
@@ -0,0 +1,271 @@
+/* Table of opcodes for the AMD 29000
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.  Written by Jim Kingdon.
+
+This file is part of GDB.
+
+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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+struct am29k_opcode {
+  /* Name of the instruction.  */
+  char *name;
+
+  /* Opcode (i.e. most significant byte of the word).  */
+  unsigned char opcode;
+
+  /* A string of characters which describe the operands.
+     Valid characters are:
+     ,        Itself.  The character appears in the assembly code.
+     a        RA.  The register number is in bits 8-15 of the instruction.
+     b        RB.  The register number is in bits 0-7 of the instruction.
+     c        RC.  The register number is in bits 16-23 of the instruction.
+     i        An immediate operand is in bits 0-7 of the instruction.
+     x        Bits 0-7 and 16-23 of the instruction are bits 0-7 and 8-15
+              (respectively) of the immediate operand.
+     h        Same as x but the instruction contains bits 16-31 of the
+              immediate operand.
+     X        Same as x but bits 16-31 of the signed immediate operand
+              are set to 1 (thus the operand is always negative).
+     P,A      Bits 0-7 and 16-23 of the instruction are bits 2-9 and 10-17
+              (respectively) of the immediate operand.
+             P=PC-relative, sign-extended to 32 bits.
+             A=Absolute, zero-extended to 32 bits.
+     e        CE bit (bit 23) for a load/store instruction.
+     n        Control field (bits 16-22) for a load/store instruction.
+     v        Immediate operand in bits 16-23 of the instruction.
+              (used for trap numbers).
+     s        SA.  Special-purpose register number in bits 8-15
+              of the instruction.
+     u        UI--bit 7 of the instruction.
+     r        RND--bits 4-6 of the instruction.
+     d        FD--bits 2-3 of the instruction.
+     f        FS--bits 0-1 of the instruction.  */
+  char *args;
+};
+
+static struct am29k_opcode am29k_opcodes[] =
+{
+
+{ "add", 0x14, "c,a,b" },
+{ "add", 0x15, "c,a,i" },
+{ "addc", 0x1c, "c,a,b" },
+{ "addc", 0x1d, "c,a,i" },
+{ "addcs", 0x18, "c,a,b" },
+{ "addcs", 0x19, "c,a,i" },
+{ "addcu", 0x1a, "c,a,b" },
+{ "addcu", 0x1b, "c,a,i" },
+{ "adds", 0x10, "c,a,b" },
+{ "adds", 0x11, "c,a,i" },
+{ "addu", 0x12, "c,a,b" },
+{ "addu", 0x13, "c,a,i" },
+{ "and", 0x90, "c,a,b" },
+{ "and", 0x91, "c,a,i" },
+{ "andn", 0x9c, "c,a,b" },
+{ "andn", 0x9d, "c,a,i" },
+{ "aseq", 0x70, "v,a,b" },
+{ "aseq", 0x71, "v,a,i" },
+{ "asge", 0x5c, "v,a,b" },
+{ "asge", 0x5d, "v,a,i" },
+{ "asgeu", 0x5e, "v,a,b" },
+{ "asgeu", 0x5f, "v,a,i" },
+{ "asgt", 0x58, "v,a,b" },
+{ "asgt", 0x59, "v,a,i" },
+{ "asgtu", 0x5a, "v,a,b" },
+{ "asgtu", 0x5b, "v,a,i" },
+{ "asle", 0x54, "v,a,b" },
+{ "asle", 0x55, "v,a,i" },
+{ "asleu", 0x56, "v,a,b" },
+{ "asleu", 0x57, "v,a,i" },
+{ "aslt", 0x50, "v,a,b" },
+{ "aslt", 0x51, "v,a,i" },
+{ "asltu", 0x52, "v,a,b" },
+{ "asltu", 0x53, "v,a,i" },
+{ "asneq", 0x72, "v,a,b" },
+{ "asneq", 0x73, "v,a,i" },
+{ "call", 0xa8, "a,P" },
+{ "call", 0xa9, "a,A" },
+{ "calli", 0xc8, "a,b" },
+{ "class", 0xe6, "c,a,f" },
+{ "clz", 0x08, "c,b" },
+{ "clz", 0x09, "c,i" },
+{ "const", 0x03, "a,x" },
+{ "consth", 0x02, "a,h" },
+{ "consthz", 0x05, "a,h" },
+{ "constn", 0x01, "a,X" },
+{ "convert", 0xe4, "c,a,u,r,d,f" },
+{ "cpbyte", 0x2e, "c,a,b" },
+{ "cpbyte", 0x2f, "c,a,i" },
+{ "cpeq", 0x60, "c,a,b" },
+{ "cpeq", 0x61, "c,a,i" },
+{ "cpge", 0x4c, "c,a,b" },
+{ "cpge", 0x4d, "c,a,i" },
+{ "cpgeu", 0x4e, "c,a,b" },
+{ "cpgeu", 0x4f, "c,a,i" },
+{ "cpgt", 0x48, "c,a,b" },
+{ "cpgt", 0x49, "c,a,i" },
+{ "cpgtu", 0x4a, "c,a,b" },
+{ "cpgtu", 0x4b, "c,a,i" },
+{ "cple", 0x44, "c,a,b" },
+{ "cple", 0x45, "c,a,i" },
+{ "cpleu", 0x46, "c,a,b" },
+{ "cpleu", 0x47, "c,a,i" },
+{ "cplt", 0x40, "c,a,b" },
+{ "cplt", 0x41, "c,a,i" },
+{ "cpltu", 0x42, "c,a,b" },
+{ "cpltu", 0x43, "c,a,i" },
+{ "cpneq", 0x62, "c,a,b" },
+{ "cpneq", 0x63, "c,a,i" },
+{ "dadd", 0xf1, "c,a,b" },
+{ "ddiv", 0xf7, "c,a,b" },
+{ "deq", 0xeb, "c,a,b" },
+{ "dge", 0xef, "c,a,b" },
+{ "dgt", 0xed, "c,a,b" },
+{ "div", 0x6a, "c,a,b" },
+{ "div", 0x6b, "c,a,i" },
+{ "div0", 0x68, "c,b" },
+{ "div0", 0x69, "c,i" },
+{ "divide", 0xe1, "c,a,b" },
+{ "dividu", 0xe3, "c,a,b" },
+{ "divl", 0x6c, "c,a,b" },
+{ "divl", 0x6d, "c,a,i" },
+{ "divrem", 0x6e, "c,a,b" },
+{ "divrem", 0x6f, "c,a,i" },
+{ "dmac", 0xd9, "F,C,a,b" },
+{ "dmsm", 0xdb, "c,a,b" },
+{ "dmul", 0xf5, "c,a,b" },
+{ "dsub", 0xf3, "c,a,b" },
+{ "emulate", 0xd7, "v,a,b" },
+{ "exbyte", 0x0a, "c,a,b" },
+{ "exbyte", 0x0b, "c,a,i" },
+{ "exhw", 0x7c, "c,a,b" },
+{ "exhw", 0x7d, "c,a,i" },
+{ "exhws", 0x7e, "c,a" },
+{ "extract", 0x7a, "c,a,b" },
+{ "extract", 0x7b, "c,a,i" },
+{ "fadd", 0xf0, "c,a,b" },
+{ "fdiv", 0xf6, "c,a,b" },
+{ "fdmul", 0xf9, "c,a,b" },
+{ "feq", 0xea, "c,a,b" },
+{ "fge", 0xee, "c,a,b" },
+{ "fgt", 0xec, "c,a,b" },
+{ "fmac", 0xd8, "F,C,a,b" },
+{ "fmsm", 0xda, "c,a,b" },
+{ "fmul", 0xf4, "c,a,b" },
+{ "fsub", 0xf2, "c,a,b" },
+{ "halt", 0x89, "" },
+{ "inbyte", 0x0c, "c,a,b" },
+{ "inbyte", 0x0d, "c,a,i" },
+{ "inhw", 0x78, "c,a,b" },
+{ "inhw", 0x79, "c,a,i" },
+{ "inv", 0x9f, "" },
+{ "iret", 0x88, "" },
+{ "iretinv", 0x8c, "" },
+{ "jmp", 0xa0, "P" },
+{ "jmp", 0xa1, "A" },
+{ "jmpf", 0xa4, "a,P" },
+{ "jmpf", 0xa5, "a,A" },
+{ "jmpfdec", 0xb4, "a,P" },
+{ "jmpfdec", 0xb5, "a,A" },
+{ "jmpfi", 0xc4, "a,b" },
+{ "jmpi", 0xc0, "b" },
+{ "jmpt", 0xac, "a,P" },
+{ "jmpt", 0xad, "a,A" },
+{ "jmpti", 0xcc, "a,b" },
+{ "load", 0x16, "e,n,a,b" },
+{ "load", 0x17, "e,n,a,i" },
+{ "loadl", 0x06, "e,n,a,b" },
+{ "loadl", 0x07, "e,n,a,i" },
+{ "loadm", 0x36, "e,n,a,b" },
+{ "loadm", 0x37, "e,n,a,i" },
+{ "loadset", 0x26, "e,n,a,b" },
+{ "loadset", 0x27, "e,n,a,i" },
+{ "mfacc", 0xe9, "c,d,f" },
+{ "mfsr", 0xc6, "c,s" },
+{ "mftlb", 0xb6, "c,a" },
+{ "mtacc", 0xe8, "c,d,f" },
+{ "mtsr", 0xce, "s,b" },
+{ "mtsrim", 0x04, "s,x" },
+{ "mttlb", 0xbe, "a,b" },
+{ "mul", 0x64, "c,a,b" },
+{ "mul", 0x65, "c,a,i" },
+{ "mull", 0x66, "c,a,b" },
+{ "mull", 0x67, "c,a,i" },
+{ "multiplu", 0xe2, "c,a,b" },
+{ "multiply", 0xe0, "c,a,b" },
+{ "multm", 0xde, "c,a,b" },
+{ "multmu", 0xdf, "c,a,b" },
+{ "mulu", 0x74, "c,a,b" },
+{ "mulu", 0x75, "c,a,i" },
+{ "nand", 0x9a, "c,a,b" },
+{ "nand", 0x9b, "c,a,i" },
+{ "nor", 0x98, "c,a,b" },
+{ "nor", 0x99, "c,a,i" },
+{ "or", 0x92, "c,a,b" },
+{ "or", 0x93, "c,a,i" },
+{ "orn", 0xaa, "c,a,b" },
+{ "orn", 0xab, "c,a,i" },
+
+/* The description of "setip" in Chapter 8 ("instruction set") of the user's
+   manual claims that these are absolute register numbers.  But section
+   7.2.1 explains that they are not.  The latter is correct, so print
+   these normally ("lr0", "lr5", etc.).  */
+{ "setip", 0x9e, "c,a,b" },
+
+{ "sll", 0x80, "c,a,b" },
+{ "sll", 0x81, "c,a,i" },
+{ "sqrt", 0xe5, "c,a,f" },
+{ "sra", 0x86, "c,a,b" },
+{ "sra", 0x87, "c,a,i" },
+{ "srl", 0x82, "c,a,b" },
+{ "srl", 0x83, "c,a,i" },
+{ "store", 0x1e, "e,n,a,b" },
+{ "store", 0x1f, "e,n,a,i" },
+{ "storel", 0x0e, "e,n,a,b" },
+{ "storel", 0x0f, "e,n,a,i" },
+{ "storem", 0x3e, "e,n,a,b" },
+{ "storem", 0x3f, "e,n,a,i" },
+{ "sub", 0x24, "c,a,b" },
+{ "sub", 0x25, "c,a,i" },
+{ "subc", 0x2c, "c,a,b" },
+{ "subc", 0x2d, "c,a,i" },
+{ "subcs", 0x28, "c,a,b" },
+{ "subcs", 0x29, "c,a,i" },
+{ "subcu", 0x2a, "c,a,b" },
+{ "subcu", 0x2b, "c,a,i" },
+{ "subr", 0x34, "c,a,b" },
+{ "subr", 0x35, "c,a,i" },
+{ "subrc", 0x3c, "c,a,b" },
+{ "subrc", 0x3d, "c,a,i" },
+{ "subrcs", 0x38, "c,a,b" },
+{ "subrcs", 0x39, "c,a,i" },
+{ "subrcu", 0x3a, "c,a,b" },
+{ "subrcu", 0x3b, "c,a,i" },
+{ "subrs", 0x30, "c,a,b" },
+{ "subrs", 0x31, "c,a,i" },
+{ "subru", 0x32, "c,a,b" },
+{ "subru", 0x33, "c,a,i" },
+{ "subs", 0x20, "c,a,b" },
+{ "subs", 0x21, "c,a,i" },
+{ "subu", 0x22, "c,a,b" },
+{ "subu", 0x23, "c,a,i" },
+{ "xnor", 0x96, "c,a,b" },
+{ "xnor", 0x97, "c,a,i" },
+{ "xor", 0x94, "c,a,b" },
+{ "xor", 0x95, "c,a,i" }
+
+};
+
+#define NUM_OPCODES ((sizeof am29k_opcodes) / (sizeof am29k_opcodes[0]))
+
diff --git a/gdb/am29k-pinsn.c b/gdb/am29k-pinsn.c
new file mode 100644 (file)
index 0000000..c933629
--- /dev/null
@@ -0,0 +1,296 @@
+/* Instruction printing code for the AMD 29000
+   Copyright (C) 1990 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.  Written by Jim Kingdon.
+
+This file is part of GDB.
+
+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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "target.h"
+#include "am29k-opcode.h"
+
+/* Print a symbolic representation of a general-purpose
+   register number NUM on STREAM.
+   NUM is a number as found in the instruction, not as found in
+   debugging symbols; it must be in the range 0-255.  */
+static void
+print_general (num, stream)
+     int num;
+     FILE *stream;
+{
+  if (num < 128)
+    fprintf_filtered (stream, "gr%d", num);
+  else
+    fprintf_filtered (stream, "lr%d", num - 128);
+}
+
+/* Like print_general but a special-purpose register.
+   
+   The mnemonics used by the AMD assembler are not quite the same
+   as the ones in the User's Manual.  We use the ones that the
+   assembler uses.  */
+static void
+print_special (num, stream)
+     int num;
+     FILE *stream;
+{
+  /* Register names of registers 0-SPEC0_NUM-1.  */
+  static char *spec0_names[] = {
+    "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr",
+    "pc0", "pc1", "pc2", "mmu", "lru"
+    };
+#define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0]))
+
+  /* Register names of registers 128-128+SPEC128_NUM-1.  */
+  static char *spec128_names[] = {
+    "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr"
+    };
+#define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0]))
+
+  /* Register names of registers 160-160+SPEC160_NUM-1.  */
+  static char *spec160_names[] = {
+    "fpe", "inte", "fps", "sr163", "exop"
+    };
+#define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0]))
+
+  if (num < SPEC0_NUM)
+    fprintf_filtered (stream, spec0_names[num]);
+  else if (num >= 128 && num < 128 + SPEC128_NUM)
+    fprintf_filtered (stream, spec128_names[num-128]);
+  else if (num >= 160 && num < 160 + SPEC160_NUM)
+    fprintf_filtered (stream, spec160_names[num-160]);
+  else
+    fprintf_filtered (stream, "sr%d", num);
+}
+
+/* Is an instruction with OPCODE a delayed branch?  */
+static int
+is_delayed_branch (opcode)
+     int opcode;
+{
+  return (opcode == 0xa8 || opcode == 0xa9 || opcode == 0xa0 || opcode == 0xa1
+         || opcode == 0xa4 || opcode == 0xa5
+         || opcode == 0xb4 || opcode == 0xb5
+         || opcode == 0xc4 || opcode == 0xc0
+         || opcode == 0xac || opcode == 0xad
+         || opcode == 0xcc);
+}
+
+/* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}.
+   Note that the amd can be set up as either
+   big or little-endian (the tm file says which) and we can't assume
+   the host machine is the same.  */
+static void
+find_bytes (insn, insn0, insn8, insn16, insn24)
+     char *insn;
+     unsigned char *insn0;
+     unsigned char *insn8;
+     unsigned char *insn16;
+     unsigned char *insn24;
+{
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+  *insn24 = insn[0];
+  *insn16 = insn[1];
+  *insn8  = insn[2];
+  *insn0  = insn[3];
+#else /* Little-endian.  */
+  *insn24 = insn[3];
+  *insn16 = insn[2];
+  *insn8 = insn[1];
+  *insn0 = insn[0];
+#endif /* Little-endian.  */
+}
+
+/* Print one instruction from MEMADDR on STREAM.
+   Return the size of the instruction (always 4 on am29k).  */
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  /* The raw instruction.  */
+  char insn[4];
+
+  /* The four bytes of the instruction.  */
+  unsigned char insn24, insn16, insn8, insn0;
+
+  struct am29k_opcode *opcode;
+
+  read_memory (memaddr, &insn[0], 4);
+
+  find_bytes (insn, &insn0, &insn8, &insn16, &insn24);
+
+  /* The opcode is always in insn24.  */
+  for (opcode = &am29k_opcodes[0];
+       opcode < &am29k_opcodes[NUM_OPCODES];
+       ++opcode)
+    {
+      if (insn24 == opcode->opcode)
+       {
+         char *s;
+         
+         fprintf_filtered (stream, "%s ", opcode->name);
+         for (s = opcode->args; *s != '\0'; ++s)
+           {
+             switch (*s)
+               {
+               case 'a':
+                 print_general (insn8, stream);
+                 break;
+                 
+               case 'b':
+                 print_general (insn0, stream);
+                 break;
+
+               case 'c':
+                 print_general (insn16, stream);
+                 break;
+
+               case 'i':
+                 fprintf_filtered (stream, "%d", insn0);
+                 break;
+
+               case 'x':
+                 fprintf_filtered (stream, "%d", (insn16 << 8) + insn0);
+                 break;
+
+               case 'h':
+                 fprintf_filtered (stream, "0x%x",
+                                   (insn16 << 24) + (insn0 << 16));
+                 break;
+
+               case 'X':
+                 fprintf_filtered (stream, "%d",
+                                   ((insn16 << 8) + insn0) | 0xffff0000);
+                 break;
+
+               case 'P':
+                 /* This output looks just like absolute addressing, but
+                    maybe that's OK (it's what the GDB 68k and EBMON
+                    29k disassemblers do).  */
+                 /* All the shifting is to sign-extend it.  p*/
+                 print_address
+                   (memaddr +
+                    (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14),
+                    stream);
+                 break;
+
+               case 'A':
+                 print_address ((insn16 << 10) + (insn0 << 2), stream);
+                 break;
+
+               case 'e':
+                 fprintf_filtered (stream, "%d", insn16 >> 7);
+                 break;
+
+               case 'n':
+                 fprintf_filtered (stream, "0x%x", insn16 & 0x7f);
+                 break;
+
+               case 'v':
+                 fprintf_filtered (stream, "%#x", insn16);
+                 break;
+
+               case 's':
+                 print_special (insn8, stream);
+                 break;
+
+               case 'u':
+                 fprintf_filtered (stream, "%d", insn0 >> 7);
+                 break;
+
+               case 'r':
+                 fprintf_filtered (stream, "%d", (insn0 >> 4) & 7);
+                 break;
+
+               case 'd':
+                 fprintf_filtered (stream, "%d", (insn0 >> 2) & 3);
+                 break;
+
+               case 'f':
+                 fprintf_filtered (stream, "%d", insn0 & 3);
+                 break;
+
+               case 'F':
+                 fprintf_filtered (stream, "%d", (insn0 >> 18) & 15);
+                 break;
+
+               case 'C':
+                 fprintf_filtered (stream, "%d", (insn0 >> 16) & 3);
+                 break;
+
+               default:
+                 fprintf_filtered (stream, "%c", *s);
+               }
+           }
+
+         /* Now we look for a const,consth pair of instructions,
+            in which case we try to print the symbolic address.  */
+         if (insn24 == 2)  /* consth */
+           {
+             int errcode;
+             char prev_insn[4];
+             unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24;
+             
+             errcode = target_read_memory (memaddr - 4,
+                                           &prev_insn[0],
+                                           4);
+             if (errcode == 0)
+               {
+                 /* If it is a delayed branch, we need to look at the
+                    instruction before the delayed brach to handle
+                    things like
+                    
+                    const _foo
+                    call _printf
+                    consth _foo
+                    */
+                 find_bytes (prev_insn, &prev_insn0, &prev_insn8,
+                             &prev_insn16, &prev_insn24);
+                 if (is_delayed_branch (prev_insn24))
+                   {
+                     errcode = target_read_memory
+                       (memaddr - 8, &prev_insn[0], 4);
+                     find_bytes (prev_insn, &prev_insn0, &prev_insn8,
+                                 &prev_insn16, &prev_insn24);
+                   }
+               }
+                 
+             /* If there was a problem reading memory, then assume
+                the previous instruction was not const.  */
+             if (errcode == 0)
+               {
+                 /* Is it const to the same register?  */
+                 if (prev_insn24 == 3
+                     && prev_insn8 == insn8)
+                   {
+                     fprintf_filtered (stream, "\t; ");
+                     print_address (((insn16 << 24) + (insn0 << 16)
+                                     + (prev_insn16 << 8) + (prev_insn0)),
+                                    stream);
+                   }
+               }
+           }
+
+         return 4;
+       }
+    }
+  fprintf_filtered (stream, ".word %#8x",
+                   (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0);
+  return 4;
+}
diff --git a/gdb/am29k-tdep.c b/gdb/am29k-tdep.c
new file mode 100644 (file)
index 0000000..e58847b
--- /dev/null
@@ -0,0 +1,695 @@
+/* Target-machine dependent code for the AMD 29000
+   Copyright (C) 1990 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.  Written by Jim Kingdon.
+
+This file is part of GDB.
+
+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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include <stdio.h>
+#include "frame.h"
+#include "value.h"
+#include "param.h"
+#include "symtab.h"
+#include "inferior.h"
+
+/* Structure to hold cached info about function prologues.  */
+struct prologue_info
+{
+  CORE_ADDR pc;                        /* First addr after fn prologue */
+  unsigned rsize, msize;       /* register stack frame size, mem stack ditto */
+  unsigned mfp_used : 1;       /* memory frame pointer used */
+  unsigned rsize_valid : 1;    /* Validity bits for the above */
+  unsigned msize_valid : 1;
+  unsigned mfp_valid : 1;
+};
+
+/* Examine the prologue of a function which starts at PC.  Return
+   the first addess past the prologue.  If MSIZE is non-NULL, then
+   set *MSIZE to the memory stack frame size.  If RSIZE is non-NULL,
+   then set *RSIZE to the register stack frame size (not including
+   incoming arguments and the return address & frame pointer stored
+   with them).  If no prologue is found, *RSIZE is set to zero.
+   If no prologue is found, or a prologue which doesn't involve
+   allocating a memory stack frame, then set *MSIZE to zero.
+
+   Note that both msize and rsize are in bytes.  This is not consistent
+   with the _User's Manual_ with respect to rsize, but it is much more
+   convenient.
+
+   If MFP_USED is non-NULL, *MFP_USED is set to nonzero if a memory
+   frame pointer is being used.  */
+CORE_ADDR
+examine_prologue (pc, rsize, msize, mfp_used)
+     CORE_ADDR pc;
+     unsigned *msize;
+     unsigned *rsize;
+     int *mfp_used;
+{
+  long insn;
+  CORE_ADDR p = pc;
+  int misc_index = find_pc_misc_function (pc);
+  struct prologue_info *mi = 0;
+
+  if (misc_index >= 0)
+    mi = (struct prologue_info *)misc_function_vector[misc_index].misc_info;
+
+  if (mi != 0)
+    {
+      int valid = 1;
+      if (rsize != NULL)
+       {
+         *rsize = mi->rsize;
+         valid &= mi->rsize_valid;
+       }
+      if (msize != NULL)
+       {
+         *msize = mi->msize;
+         valid &= mi->msize_valid;
+       }
+      if (mfp_used != NULL)
+       {
+         *mfp_used = mi->mfp_used;
+         valid &= mi->mfp_valid;
+       }
+      if (valid)
+       return mi->pc;
+    }
+
+  if (rsize != NULL)
+    *rsize = 0;
+  if (msize != NULL)
+    *msize = 0;
+  if (mfp_used != NULL)
+    *mfp_used = 0;
+  
+  /* Prologue must start with subtracting a constant from gr1.
+     Normally this is sub gr1,gr1,<rsize * 4>.  */
+  insn = read_memory_integer (p, 4);
+  if ((insn & 0xffffff00) != 0x25010100)
+    {
+      /* If the frame is large, instead of a single instruction it
+        might be a pair of instructions:
+        const <reg>, <rsize * 4>
+        sub gr1,gr1,<reg>
+        */
+      int reg;
+      /* Possible value for rsize.  */
+      unsigned int rsize0;
+      
+      if ((insn & 0xff000000) != 0x03000000)
+       {
+         p = pc;
+         goto done;
+       }
+      reg = (insn >> 8) & 0xff;
+      rsize0 = (((insn >> 8) & 0xff00) | (insn & 0xff));
+      p += 4;
+      insn = read_memory_integer (p, 4);
+      if ((insn & 0xffffff00) != 0x24010100
+         || (insn & 0xff) != reg)
+       {
+         p = pc;
+         goto done;
+       }
+      if (rsize != NULL)
+       *rsize = rsize0;
+    }
+  else
+    {
+      if (rsize != NULL)
+       *rsize = (insn & 0xff);
+    }
+  p += 4;
+
+  /* Next instruction must be asgeu V_SPILL,gr1,rab.  */
+  insn = read_memory_integer (p, 4);
+  if (insn != 0x5e40017e)
+    {
+      p = pc;
+      goto done;
+    }
+  p += 4;
+
+  /* Next instruction usually sets the frame pointer (lr1) by adding
+     <size * 4> from gr1.  However, this can (and high C does) be
+     deferred until anytime before the first function call.  So it is
+     OK if we don't see anything which sets lr1.  */
+  /* Normally this is just add lr1,gr1,<size * 4>.  */
+  insn = read_memory_integer (p, 4);
+  if ((insn & 0xffffff00) == 0x15810100)
+    p += 4;
+  else
+    {
+      /* However, for large frames it can be
+        const <reg>, <size *4>
+        add lr1,gr1,<reg>
+        */
+      int reg;
+      CORE_ADDR q;
+
+      if ((insn & 0xff000000) == 0x03000000)
+       {
+         reg = (insn >> 8) & 0xff;
+         q = p + 4;
+         insn = read_memory_integer (q, 4);
+         if ((insn & 0xffffff00) == 0x14810100
+             && (insn & 0xff) == reg)
+           p = q;
+       }
+    }
+
+  /* Next comes "add lr{<rsize-1>},msp,0", but only if a memory
+     frame pointer is in use.  We just check for add lr<anything>,msp,0;
+     we don't check this rsize against the first instruction, and
+     we don't check that the trace-back tag indicates a memory frame pointer
+     is in use.  
+
+     The recommended instruction is actually "sll lr<whatever>,msp,0". 
+     We check for that, too.  Originally Jim Kingdon's code seemed
+     to be looking for a "sub" instruction here, but the mask was set
+     up to lose all the time. */
+  insn = read_memory_integer (p, 4);
+  if (((insn & 0xff80ffff) == 0x15807d00)      /* add */
+   || ((insn & 0xff80ffff) == 0x81807d00) )    /* sll */
+    {
+      p += 4;
+      if (mfp_used != NULL)
+       *mfp_used = 1;
+    }
+
+  /* Next comes a subtraction from msp to allocate a memory frame,
+     but only if a memory frame is
+     being used.  We don't check msize against the trace-back tag.
+
+     Normally this is just
+     sub msp,msp,<msize>
+     */
+  insn = read_memory_integer (p, 4);
+  if ((insn & 0xffffff00) == 0x257d7d00)
+    {
+      p += 4;
+      if (msize != NULL)
+       *msize = insn & 0xff;
+    }
+  else
+    {
+      /* For large frames, instead of a single instruction it might
+        be
+
+        const <reg>, <msize>
+        consth <reg>, <msize>     ; optional
+        sub msp,msp,<reg>
+        */
+      int reg;
+      unsigned msize0;
+      CORE_ADDR q = p;
+
+      if ((insn & 0xff000000) == 0x03000000)
+       {
+         reg = (insn >> 8) & 0xff;
+         msize0 = ((insn >> 8) & 0xff00) | (insn & 0xff);
+         q += 4;
+         insn = read_memory_integer (q, 4);
+         /* Check for consth.  */
+         if ((insn & 0xff000000) == 0x02000000
+             && (insn & 0x0000ff00) == reg)
+           {
+             msize0 |= (insn << 8) & 0xff000000;
+             msize0 |= (insn << 16) & 0x00ff0000;
+             q += 4;
+             insn = read_memory_integer (q, 4);
+           }
+         /* Check for sub msp,msp,<reg>.  */
+         if ((insn & 0xffffff00) == 0x247d7d00
+             && (insn & 0xff) == reg)
+           {
+             p = q + 4;
+             if (msize != NULL)
+               *msize = msize0;
+           }
+       }
+    }
+
+ done:
+  if (misc_index >= 0)
+    {
+      if (mi == 0)
+       {
+         /* Add a new cache entry.  */
+         mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info));
+         misc_function_vector[misc_index].misc_info = (char *)mi;
+         mi->rsize_valid = 0;
+         mi->msize_valid = 0;
+         mi->mfp_valid = 0;
+       }
+      /* else, cache entry exists, but info is incomplete.  */
+      mi->pc = p;
+      if (rsize != NULL)
+       {
+         mi->rsize = *rsize;
+         mi->rsize_valid = 1;
+       }
+      if (msize != NULL)
+       {
+         mi->msize = *msize;
+         mi->msize_valid = 1;
+       }
+      if (mfp_used != NULL)
+       {
+         mi->mfp_used = *mfp_used;
+         mi->mfp_valid = 1;
+       }
+    }
+  return p;
+}
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+CORE_ADDR
+skip_prologue (pc)
+     CORE_ADDR pc;
+{
+  return examine_prologue (pc, (unsigned *)NULL, (unsigned *)NULL,
+                          (int *)NULL);
+}
+
+/* Initialize the frame.  In addition to setting "extra" frame info,
+   we also set ->frame because we use it in a nonstandard way, and ->pc
+   because we need to know it to get the other stuff.  See the diagram
+   of stacks and the frame cache in tm-29k.h for more detail.  */
+static void
+init_frame_info (innermost_frame, fci)
+     int innermost_frame;
+     struct frame_info *fci;
+{
+  CORE_ADDR p;
+  long insn;
+  unsigned rsize;
+  unsigned msize;
+  int mfp_used;
+  struct symbol *func;
+
+  p = fci->pc;
+
+  if (innermost_frame)
+    fci->frame = read_register (GR1_REGNUM);
+  else
+    fci->frame = fci->next_frame + fci->next->rsize;
+  
+#if CALL_DUMMY_LOCATION == ON_STACK
+  This wont work;
+#else
+  if (PC_IN_CALL_DUMMY (p, 0, 0))
+#endif
+    {
+      fci->rsize = DUMMY_FRAME_RSIZE;
+      /* This doesn't matter since we never try to get locals or args
+        from a dummy frame.  */
+      fci->msize = 0;
+      /* Dummy frames always use a memory frame pointer.  */
+      fci->saved_msp = 
+       read_register_stack_integer (fci->frame + DUMMY_FRAME_RSIZE - 4, 4);
+      return;
+    }
+    
+  func = find_pc_function (p);
+  if (func != NULL)
+    p = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
+  else
+    {
+      /* Search backward to find the trace-back tag.  However,
+        do not trace back beyond the start of the text segment
+        (just as a sanity check to avoid going into never-never land).  */
+      while (p >= text_start
+            && ((insn = read_memory_integer (p, 4)) & 0xff000000) != 0)
+       p -= 4;
+      
+      if (p < text_start)
+       {
+         /* Couldn't find the trace-back tag.
+            Something strange is going on.  */
+         fci->saved_msp = 0;
+         fci->rsize = 0;
+         fci->msize = 0;
+         return;
+       }
+      else
+       /* Advance to the first word of the function, i.e. the word
+          after the trace-back tag.  */
+       p += 4;
+    }
+  /* We've found the start of the function.  Since High C interchanges
+     the meanings of bits 23 and 22 (as of Jul 90), and we
+     need to look at the prologue anyway to figure out
+     what rsize is, ignore the contents of the trace-back tag.  */
+  examine_prologue (p, &rsize, &msize, &mfp_used);
+  fci->rsize = rsize;
+  fci->msize = msize;
+  if (innermost_frame)
+    {
+      fci->saved_msp = read_register (MSP_REGNUM) + msize;
+    }
+  else
+    {
+      if (mfp_used)
+       fci->saved_msp =
+         read_register_stack_integer (fci->frame + rsize - 1, 4);
+      else
+       fci->saved_msp = fci->next->saved_msp + msize;
+    }
+}
+
+void
+init_extra_frame_info (fci)
+     struct frame_info *fci;
+{
+  if (fci->next == 0)
+    /* Assume innermost frame.  May produce strange results for "info frame"
+       but there isn't any way to tell the difference.  */
+    init_frame_info (1, fci);
+  else
+    /* We're in get_prev_frame_info.
+       Take care of everything in init_frame_pc.  */
+    ;
+}
+
+void
+init_frame_pc (fromleaf, fci)
+     int fromleaf;
+     struct frame_info *fci;
+{
+  fci->pc = (fromleaf ? SAVED_PC_AFTER_CALL (fci->next) :
+            fci->next ? FRAME_SAVED_PC (fci->next) : read_pc ());
+  init_frame_info (0, fci);
+}
+\f
+/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
+   offsets being relative to the memory stack pointer (high C) or
+   saved_msp (gcc).  */
+
+CORE_ADDR
+frame_locals_address (fi)
+     struct frame_info *fi;
+{
+  struct block *b = block_for_pc (fi->pc);
+  /* If compiled without -g, assume GCC.  */
+  if (b == NULL || BLOCK_GCC_COMPILED (b))
+    return fi->saved_msp;
+  else
+    return fi->saved_msp - fi->msize;
+}
+\f
+/* Routines for reading the register stack.  The caller gets to treat
+   the register stack as a uniform stack in memory, from address $gr1
+   straight through $rfb and beyond.  */
+
+/* Analogous to read_memory except the length is understood to be 4.
+   Also, myaddr can be NULL (meaning don't bother to read), and
+   if actual_mem_addr is non-NULL, store there the address that it
+   was fetched from (or if from a register the offset within
+   registers).  Set *LVAL to lval_memory or lval_register, depending
+   on where it came from.  */
+void
+read_register_stack (memaddr, myaddr, actual_mem_addr, lval)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     CORE_ADDR *actual_mem_addr;
+     enum lval_type *lval;
+{
+  long rfb = read_register (RFB_REGNUM);
+  long rsp = read_register (RSP_REGNUM);
+  if (memaddr < rfb)
+    {
+      /* It's in a register.  */
+      int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
+      if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127)
+       error ("Attempt to read register stack out of range.");
+      if (myaddr != NULL)
+       read_register_gen (regnum, myaddr);
+      if (lval != NULL)
+       *lval = lval_register;
+      if (actual_mem_addr != NULL)
+       *actual_mem_addr = REGISTER_BYTE (regnum);
+    }
+  else
+    {
+      /* It's in the memory portion of the register stack.  */
+      if (myaddr != NULL)
+       read_memory (memaddr, myaddr, 4);
+      if (lval != NULL)
+       *lval = lval_memory;
+      if (actual_mem_addr != NULL)
+       *actual_mem_addr == memaddr;
+    }
+}
+
+/* Analogous to read_memory_integer
+   except the length is understood to be 4.  */
+long
+read_register_stack_integer (memaddr, len)
+     CORE_ADDR memaddr;
+     int len;
+{
+  long buf;
+  read_register_stack (memaddr, &buf, NULL, NULL);
+  SWAP_TARGET_AND_HOST (&buf, 4);
+  return buf;
+}
+
+/* Copy 4 bytes from GDB memory at MYADDR into inferior memory
+   at MEMADDR and put the actual address written into in
+   *ACTUAL_MEM_ADDR.  */
+static void
+write_register_stack (memaddr, myaddr, actual_mem_addr)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     CORE_ADDR *actual_mem_addr;
+{
+  long rfb = read_register (RFB_REGNUM);
+  long rsp = read_register (RSP_REGNUM);
+  if (memaddr < rfb)
+    {
+      /* It's in a register.  */
+      int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
+      if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127)
+       error ("Attempt to read register stack out of range.");
+      if (myaddr != NULL)
+       write_register (regnum, *(long *)myaddr);
+      if (actual_mem_addr != NULL)
+       *actual_mem_addr = NULL;
+    }
+  else
+    {
+      /* It's in the memory portion of the register stack.  */
+      if (myaddr != NULL)
+       write_memory (memaddr, myaddr, 4);
+      if (actual_mem_addr != NULL)
+       *actual_mem_addr == memaddr;
+    }
+}
+\f
+/* Find register number REGNUM relative to FRAME and put its
+   (raw) contents in *RAW_BUFFER.  Set *OPTIMIZED if the variable
+   was optimized out (and thus can't be fetched).  If the variable
+   was fetched from memory, set *ADDRP to where it was fetched from,
+   otherwise it was fetched from a register.
+
+   The argument RAW_BUFFER must point to aligned memory.  */
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
+     char *raw_buffer;
+     int *optimized;
+     CORE_ADDR *addrp;
+     FRAME frame;
+     int regnum;
+     enum lval_type *lvalp;
+{
+  struct frame_info *fi = get_frame_info (frame);
+  CORE_ADDR addr;
+  enum lval_type lval;
+
+  /* Once something has a register number, it doesn't get optimized out.  */
+  if (optimized != NULL)
+    *optimized = 0;
+  if (regnum == RSP_REGNUM)
+    {
+      if (raw_buffer != NULL)
+       *(CORE_ADDR *)raw_buffer = fi->frame;
+      if (lvalp != NULL)
+       *lvalp = not_lval;
+      return;
+    }
+  else if (regnum == PC_REGNUM)
+    {
+      if (raw_buffer != NULL)
+       *(CORE_ADDR *)raw_buffer = fi->pc;
+
+      /* Not sure we have to do this.  */
+      if (lvalp != NULL)
+       *lvalp = not_lval;
+
+      return;
+    }
+  else if (regnum == MSP_REGNUM)
+    {
+      if (raw_buffer != NULL)
+       {
+         if (fi->next != NULL)
+           *(CORE_ADDR *)raw_buffer = fi->next->saved_msp;
+         else
+           *(CORE_ADDR *)raw_buffer = read_register (MSP_REGNUM);
+       }
+      /* The value may have been computed, not fetched.  */
+      if (lvalp != NULL)
+       *lvalp = not_lval;
+      return;
+    }
+  else if (regnum < LR0_REGNUM || regnum >= LR0_REGNUM + 128)
+    {
+      /* These registers are not saved over procedure calls,
+        so just print out the current values.  */
+      if (raw_buffer != NULL)
+       *(CORE_ADDR *)raw_buffer = read_register (regnum);
+      if (lvalp != NULL)
+       *lvalp = lval_register;
+      if (addrp != NULL)
+       *addrp = REGISTER_BYTE (regnum);
+      return;
+    }
+      
+  addr = fi->frame + (regnum - LR0_REGNUM) * 4;
+  if (raw_buffer != NULL)
+    read_register_stack (addr, raw_buffer, &addr, &lval);
+  if (lvalp != NULL)
+    *lvalp = lval;
+  if (addrp != NULL)
+    *addrp = addr;
+}
+\f
+/* Discard from the stack the innermost frame,
+   restoring all saved registers.  */
+
+void
+pop_frame ()
+{
+  FRAME frame = get_current_frame ();                                        
+  struct frame_info *fi = get_frame_info (frame);                            
+  CORE_ADDR rfb = read_register (RFB_REGNUM);                                
+  CORE_ADDR gr1 = fi->frame + fi->rsize;
+  CORE_ADDR lr1;                                                             
+  CORE_ADDR ret_addr;
+  int i;
+
+  /* If popping a dummy frame, need to restore registers.  */
+  if (PC_IN_CALL_DUMMY (read_register (PC_REGNUM),
+                       read_register (SP_REGNUM),
+                       FRAME_FP (fi)))
+    {
+      for (i = 0; i < DUMMY_SAVE_SR128; ++i)
+       write_register
+         (SR_REGNUM (i + 128),
+          read_register (LR0_REGNUM + DUMMY_ARG / 4 + i));
+      for (i = 0; i < DUMMY_SAVE_GR96; ++i)
+       write_register
+         (GR96_REGNUM + i,
+          read_register (LR0_REGNUM + DUMMY_ARG / 4 + DUMMY_SAVE_SR128 + i));
+    }
+
+  /* Restore the memory stack pointer.  */
+  write_register (MSP_REGNUM, fi->saved_msp);                                
+  /* Restore the register stack pointer.  */                                 
+  write_register (GR1_REGNUM, gr1);
+  /* Check whether we need to fill registers.  */                            
+  lr1 = read_register (LR0_REGNUM + 1);                                      
+  if (lr1 > rfb)                                                             
+    {                                                                        
+      /* Fill.  */                                                           
+      int num_bytes = lr1 - rfb;
+      int i;                                                                 
+      long word;                                                             
+      write_register (RAB_REGNUM, read_register (RAB_REGNUM) + num_bytes);  
+      write_register (RFB_REGNUM, lr1);                                      
+      for (i = 0; i < num_bytes; i += 4)                                     
+        {
+         /* Note: word is in host byte order.  */
+          word = read_memory_integer (rfb + i, 4);
+          write_register (LR0_REGNUM + ((rfb - gr1) % 0x80) + i / 4, word);                                          
+        }                                                                    
+    }
+  ret_addr = read_register (LR0_REGNUM);
+  write_register (PC_REGNUM, ret_addr);
+  write_register (NPC_REGNUM, ret_addr + 4);
+  flush_cached_frames ();                                                    
+  set_current_frame (create_new_frame (0, read_pc()));               
+}
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+void 
+push_dummy_frame ()
+{
+  long w;
+  CORE_ADDR rab, gr1;
+  CORE_ADDR msp = read_register (MSP_REGNUM);
+  int i;
+  
+  /* Save the PC.  */
+  write_register (LR0_REGNUM, read_register (PC_REGNUM));
+
+  /* Allocate the new frame.  */
+  gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE;
+  write_register (GR1_REGNUM, gr1);
+
+  rab = read_register (RAB_REGNUM);
+  if (gr1 < rab)
+    {
+      /* We need to spill registers.  */
+      int num_bytes = rab - gr1;
+      CORE_ADDR rfb = read_register (RFB_REGNUM);
+      int i;
+      long word;
+
+      write_register (RFB_REGNUM, rfb - num_bytes);
+      write_register (RAB_REGNUM, gr1);
+      for (i = 0; i < num_bytes; i += 4)
+       {
+         /* Note:  word is in target byte order.  */
+         read_register_gen (LR0_REGNUM + i / 4, &word, 4);
+         write_memory (rfb - num_bytes + i, &word, 4);
+       }
+    }
+
+  /* There are no arguments in to the dummy frame, so we don't need
+     more than rsize plus the return address and lr1.  */
+  write_register (LR0_REGNUM + 1, gr1 + DUMMY_FRAME_RSIZE + 2 * 4);
+
+  /* Set the memory frame pointer.  */
+  write_register (LR0_REGNUM + DUMMY_FRAME_RSIZE / 4 - 1, msp);
+
+  /* Allocate arg_slop.  */
+  write_register (MSP_REGNUM, msp - 16 * 4);
+
+  /* Save registers.  */
+  for (i = 0; i < DUMMY_SAVE_SR128; ++i)
+    write_register (LR0_REGNUM + DUMMY_ARG / 4 + i,
+                   read_register (SR_REGNUM (i + 128)));
+  for (i = 0; i < DUMMY_SAVE_GR96; ++i)
+    write_register (LR0_REGNUM + DUMMY_ARG / 4 + DUMMY_SAVE_SR128 + i,
+                   read_register (GR96_REGNUM + i));
+}
diff --git a/gdb/ansidecl.h b/gdb/ansidecl.h
new file mode 100755 (executable)
index 0000000..9e8f390
--- /dev/null
@@ -0,0 +1,93 @@
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library 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 1, or (at your option)
+any later version.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+       Macros
+               PTR             - Generic pointer type
+               LONG_DOUBLE     - `long double' type
+               CONST           - `const' keyword
+               VOLATILE        - `volatile' keyword
+               SIGNED          - `signed' keyword
+               PTRCONST        - Generic const pointer (void *const)
+
+       EXFUN(name, prototype)          - declare external function NAME
+                                         with prototype PROTOTYPE
+       DEFUN(name, arglist, args)      - define function NAME with
+                                         args ARGLIST of types in ARGS
+       DEFUN_VOID(name)                - define function NAME with no args
+       AND                             - argument separator for ARGS
+       NOARGS                          - null arglist
+       DOTS                            - `...' in args
+
+    For example:
+       extern int EXFUN(printf, (CONST char *format DOTS));
+       int DEFUN(fprintf, (stream, format),
+                 FILE *stream AND CONST char *format DOTS) { ... }
+       void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef        _ANSIDECL_H
+
+#define        _ANSIDECL_H     1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#ifdef __STDC__
+
+#define        PTR             void *
+#define        PTRCONST        void *CONST
+#define        LONG_DOUBLE     long double
+
+#define        AND             ,
+#define        NOARGS          void
+#define        CONST           const
+#define        VOLATILE        volatile
+#define        SIGNED          signed
+#define        DOTS            , ...
+
+#define        EXFUN(name, proto)              name proto
+#define        DEFUN(name, arglist, args)      name(args)
+#define        DEFUN_VOID(name)                name(NOARGS)
+
+#else  /* Not ANSI C.  */
+
+#define        PTR             char *
+#define        PTRCONST        PTR
+#define        LONG_DOUBLE     double
+
+#define        AND             ;
+#define        NOARGS
+#define        CONST
+#define        VOLATILE
+#define        SIGNED
+#define        DOTS
+
+#define        EXFUN(name, proto)              name()
+#define        DEFUN(name, arglist, args)      name arglist args;
+#define        DEFUN_VOID(name)                name()
+
+#endif /* ANSI C.  */
+
+
+#endif /* ansidecl.h   */
diff --git a/gdb/arm-convert.s b/gdb/arm-convert.s
new file mode 100644 (file)
index 0000000..416132b
--- /dev/null
@@ -0,0 +1,16 @@
+       .text
+       .global _convert_from_extended
+
+_convert_from_extended:
+
+       ldfe    f0,[a1]
+       stfd    f0,[a2]
+       movs    pc,lr
+
+       .global _convert_to_extended
+
+_convert_to_extended:
+
+       ldfd    f0,[a1]
+       stfe    f0,[a2]
+       movs    pc,lr
diff --git a/gdb/arm-pinsn.c b/gdb/arm-pinsn.c
new file mode 100644 (file)
index 0000000..2da8fdc
--- /dev/null
@@ -0,0 +1,271 @@
+/* Print ARM instructions for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "arm-opcode.h"
+
+extern char *reg_names[];
+
+static char *shift_names[] = {
+    "lsl", "lsr", "asr", "ror",
+};
+
+static char *cond_names[] = {
+       "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
+       "hi", "ls", "ge", "lt", "gt", "le", "", "nv"
+};
+
+static char float_precision[] = "sdep";
+static char float_rounding[] = " pmz";
+static float float_immed[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 0.5, 10.0 };
+
+static void print_ldr_str_offset();
+static void print_ldc_stc_offset();
+static long immediate_value();
+\f
+/* Print the ARM instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+    unsigned long ins;
+    register struct opcode *op;
+    register char *p;
+    register int i, c;
+    int s, e, val;
+
+    ins = read_memory_integer(memaddr, 4);
+    for (i = 0, op = opcodes; i < N_OPCODES; i++, op++)
+       if ((ins & op->mask) == op->value) break;
+    assert(i != N_OPCODES);
+    
+    for (p = op->assembler; *p;) {
+       c = *p++;
+       if (c == '%') {
+           s = e = 0;
+           while (isdigit(*p))
+               s = s*10 + (*p++ - '0');
+           if (*p == '-') {
+               p++;
+               while (isdigit(*p))
+                   e = e*10 + (*p++ - '0');
+           } else
+               e = s;
+           assert(s >= 0 && s <= 31 && e >= 0 && e <= 31);
+           val = (ins >> s) & ((1 << (e + 1 - s)) - 1);
+           switch (*p++) {
+           case '%' :
+               putc('%', stream);
+               break;
+           case 'd' :
+               fprintf(stream, "%d", val);
+               break;
+           case 'x' :
+               fprintf(stream, "%x", val);
+               break;
+           case 'r' :
+               assert(val >= 0 && val <= 15);
+               fprintf(stream, "%s", reg_names[val]);
+               break;
+           case 'c' :
+               fprintf(stream, "%s", cond_names[ins >> 28]);
+               break;
+           case '\'' :
+               assert(*p);
+               c = *p++;
+               if (val)
+                   putc(c, stream);
+               break;
+           case '`' :
+               assert(*p);
+               c = *p++;
+               if (!val)
+                   putc(c, stream);
+               break;
+           case '?' :
+               assert(*p);
+               c = *p++;
+               assert(*p);
+               if (val)
+                   p++;
+               else
+                   c = *p++;
+               putc(c, stream);
+               break;
+           case 'p' :
+               if (((ins >> 12) & 0xf) == 0xf)
+                   putc('p', stream);
+               break;
+           case 'o' :
+               if (ins & (1<<25)) {
+                   int immed = immediate_value(ins & 0xfff);
+                   fprintf (stream, "#%d (0x%x)", immed, immed);
+               } else {
+                   int operand2 = ins & 0xfff;
+                   /* in operand2 :
+                      bits 0-3 are the base register
+                      bits 5-6 are the shift (0=lsl, 1=lsr, 2=asr, 3=ror)
+                      if bit 4 is zero then bits 7-11 are an immediate shift count
+                      else bit 7 must be zero and bits 8-11 are the register
+                      to be used as a shift count.
+                      Note: no shift at all is encoded as "reg lsl #0" */
+                   fprintf (stream, "%s", reg_names[operand2 & 0xf]);
+                   if (operand2 & 0xff0) {
+                       /* ror #0 is really rrx (rotate right extend) */
+                       if ((operand2 & 0xff0) == 0x060)
+                           fprintf (stream, ", rrx");
+                       else {
+                           fprintf (stream, ", %s ",
+                                    shift_names[(operand2 >> 5) & 3]);
+                           if (operand2 & (1<<4)) /* register shift */
+                               fprintf (stream, "%s",
+                                        reg_names[operand2 >> 8]);
+                           else        /* immediate shift */
+                               fprintf (stream, "#%d",
+                                        operand2 >> 7);
+                       }
+                   }
+               }
+               break;
+           case 'a' :
+               fprintf (stream, "[%s", reg_names[(ins >> 16) & 0xf]);
+               if (ins & (1<<24)) {
+                   fprintf (stream, ", ");
+                   print_ldr_str_offset (ins, stream);
+                   putc (']', stream);
+                   if (ins & (1<<21)) putc('!', stream);
+                   /* If it is a pc relative load, then it is probably
+                      a constant so print it */
+                   if (((ins >> 16) & 0xf) == 15 &&
+                       (ins & (1<<25)) == 0 &&
+                       (ins & (1<<20))) {
+                       int addr = memaddr + 8 +
+                           (ins & 0xfff) * ((ins & (1<<23)) ? 1 : -1);
+                       fprintf (stream, " (contents=");
+                       print_address (read_memory_integer(addr, 4), stream);
+                       fprintf (stream, ")");
+                   }
+               } else {
+                   fprintf (stream, "]," );
+                   print_ldr_str_offset (ins, stream);
+               }
+               break;
+           case 'b' :
+               print_address (memaddr + 8 + (((int)ins << 8) >> 6), stream);
+               break;
+           case 'A' :
+               fprintf (stream, "[%s", reg_names[(ins >> 16) & 0xf]);
+               if (ins & (1<<24)) {
+                   fprintf (stream, ", ");
+                   print_ldc_stc_offset (ins, stream);
+                   putc(']', stream);
+                   if (ins & (1<<21))
+                       putc('!', stream);
+               } else {
+                   fprintf (stream, "], ");
+                   print_ldc_stc_offset (ins, stream);
+               }
+               break;
+           case 'm' :
+               {
+                   int regnum, first = 1;
+                   putc('{', stream);
+                   for (regnum = 0; regnum < 16; regnum++)
+                       if (ins & (1<<regnum)) {
+                           if (!first)
+                               putc (',', stream);
+                           first = 0;
+                           fprintf (stream, "%s", reg_names[regnum]);
+                       }
+                   putc('}', stream);
+               }
+               break;
+           case 'P' :
+               val = ((ins >> 18) & 2) | ((ins >> 7) & 1);
+               putc(float_precision[val], stream);
+               break;
+           case 'Q' :
+               val = ((ins >> 21) & 2) | ((ins >> 15) & 1);
+               putc(float_precision[val], stream);
+               break;
+           case 'R' :
+               val = ((ins >> 5) & 3);
+               if (val) putc(float_rounding[val], stream);
+               break;
+           case 'f' :
+               assert(val >= 0 && val <= 15);
+               if (val > 7)
+                   fprintf (stream, "#%3.1f", float_immed[val - 8]);
+               else
+                   fprintf (stream, "f%d", val);
+               break;
+           default:
+               abort();
+           }
+       } else
+           putc(c, stream);
+    }
+    return 4;
+}
+
+static long
+immediate_value(operand)
+int operand;
+{
+    int val = operand & 0xff;
+    int shift = 2*(operand >> 8);
+    /* immediate value is (val ror shift) */
+    return (val >> shift) | (val << (32 - shift));
+}
+
+static void
+print_ldr_str_offset(ins, stream)
+unsigned long ins;
+FILE *stream;
+{
+    if ((ins & (1<<25)) == 0)
+       fprintf (stream, "#%d",
+                (ins & 0xfff) * ((ins & (1<<23)) ? 1 : -1));
+    else {
+       fprintf (stream, "%s%s", reg_names[ins & 0xf],
+                (ins & (1<<23)) ? "" : "-");
+       if (ins & 0xff0)
+           fprintf (stream, ", %s #%d",
+                    shift_names[(ins >> 5) & 3],
+                    (ins >> 7) & 0x1f);
+    }
+}
+
+static void
+print_ldc_stc_offset(ins, stream)
+unsigned long ins;
+FILE *stream;
+{
+    fprintf (stream, "#%d",
+            4 * (ins & 0xff) * ((ins & (1<<23)) ? 1 : -1));
+}
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
new file mode 100644 (file)
index 0000000..b4fe1b5
--- /dev/null
@@ -0,0 +1,406 @@
+/* Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "arm-opcode.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#define N_TXTADDR(hdr) 0x8000
+#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
+
+#include "gdbcore.h"
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+
+\f
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+/* Structure to describe the chain of shared libraries used
+   by the execfile.
+   e.g. prog shares Xt which shares X11 which shares c. */
+
+struct shared_library {
+    struct exec_header header;
+    char name[SHLIBLEN];
+    CORE_ADDR text_start;      /* CORE_ADDR of 1st byte of text, this file */
+    long data_offset;          /* offset of data section in file */
+    int chan;                  /* file descriptor for the file */
+    struct shared_library *shares; /* library this one shares */
+};
+static struct shared_library *shlib = 0;
+
+/* Hook for `exec_file_command' command to call.  */
+
+extern void (*exec_file_display_hook) ();
+   
+static CORE_ADDR unshared_text_start;
+
+/* extended header from exec file (for shared library info) */
+
+static struct exec_header exec_header;
+
+void
+exec_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+
+  /* Eliminate all traces of old exec file.
+     Mark text segment as empty.  */
+
+  if (execfile)
+    free (execfile);
+  execfile = 0;
+  data_start = 0;
+  data_end -= exec_data_start;
+  text_start = 0;
+  unshared_text_start = 0;
+  text_end = 0;
+  exec_data_start = 0;
+  exec_data_end = 0;
+  if (execchan >= 0)
+    close (execchan);
+  execchan = -1;
+  if (shlib) {
+      close_shared_library(shlib);
+      shlib = 0;
+  }
+
+  /* Now open and digest the file the user requested, if any.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+
+      execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+                       &execfile);
+      if (execchan < 0)
+       perror_with_name (filename);
+
+      {
+       struct stat st_exec;
+
+#ifdef HEADER_SEEK_FD
+       HEADER_SEEK_FD (execchan);
+#endif
+       
+       val = myread (execchan, &exec_header, sizeof exec_header);
+       exec_aouthdr = exec_header.a_exec;
+
+       if (val < 0)
+         perror_with_name (filename);
+
+       text_start = 0x8000;
+
+       /* Look for shared library if needed */
+       if (exec_header.a_exec.a_magic & MF_USES_SL)
+           shlib = open_shared_library(exec_header.a_shlibname, text_start);
+
+       text_offset = N_TXTOFF (exec_aouthdr);
+       exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+
+       if (shlib) {
+           unshared_text_start = shared_text_end(shlib) & ~0x7fff;
+           stack_start = shlib->header.a_exec.a_sldatabase;
+           stack_end = STACK_END_ADDR;
+       } else
+           unshared_text_start = 0x8000;
+       text_end = unshared_text_start + exec_aouthdr.a_text;
+
+       exec_data_start = unshared_text_start + exec_aouthdr.a_text;
+        exec_data_end = exec_data_start + exec_aouthdr.a_data;
+
+       data_start = exec_data_start;
+       data_end += exec_data_start;
+
+       fstat (execchan, &st_exec);
+       exec_mtime = st_exec.st_mtime;
+      }
+
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No exec file now.\n");
+
+  /* Tell display code (if any) about the changed file name.  */
+  if (exec_file_display_hook)
+    (*exec_file_display_hook) (filename);
+}
+
+/* Read from the program's memory (except for inferior processes).
+   This function is misnamed, since it only reads, never writes; and
+   since it will use the core file and/or executable file as necessary.
+
+   It should be extended to write as well as read, FIXME, for patching files.
+
+   Return 0 if address could be read, EIO if addresss out of bounds.  */
+
+int
+xfer_core_file (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  register int i;
+  register int val;
+  int xferchan;
+  char **xferfile;
+  int fileptr;
+  int returnval = 0;
+
+  while (len > 0)
+    {
+      xferfile = 0;
+      xferchan = 0;
+
+      /* Determine which file the next bunch of addresses reside in,
+        and where in the file.  Set the file's read/write pointer
+        to point at the proper place for the desired address
+        and set xferfile and xferchan for the correct file.
+
+        If desired address is nonexistent, leave them zero.
+
+        i is set to the number of bytes that can be handled
+        along with the next address.
+
+        We put the most likely tests first for efficiency.  */
+
+      /* Note that if there is no core file
+        data_start and data_end are equal.  */
+      if (memaddr >= data_start && memaddr < data_end)
+       {
+         i = min (len, data_end - memaddr);
+         fileptr = memaddr - data_start + data_offset;
+         xferfile = &corefile;
+         xferchan = corechan;
+       }
+      /* Note that if there is no core file
+        stack_start and stack_end define the shared library data.  */
+      else if (memaddr >= stack_start && memaddr < stack_end)
+       {
+           if (corechan < 0) {
+               struct shared_library *lib;
+               for (lib = shlib; lib; lib = lib->shares)
+                   if (memaddr >= lib->header.a_exec.a_sldatabase &&
+                       memaddr < lib->header.a_exec.a_sldatabase +
+                         lib->header.a_exec.a_data)
+                       break;
+               if (lib) {
+                   i = min (len, lib->header.a_exec.a_sldatabase +
+                            lib->header.a_exec.a_data - memaddr);
+                   fileptr = lib->data_offset + memaddr -
+                       lib->header.a_exec.a_sldatabase;
+                   xferfile = execfile;
+                   xferchan = lib->chan;
+               }
+           } else {
+               i = min (len, stack_end - memaddr);
+               fileptr = memaddr - stack_start + stack_offset;
+               xferfile = &corefile;
+               xferchan = corechan;
+           }
+       }
+      else if (corechan < 0
+              && memaddr >= exec_data_start && memaddr < exec_data_end)
+       {
+         i = min (len, exec_data_end - memaddr);
+         fileptr = memaddr - exec_data_start + exec_data_offset;
+         xferfile = &execfile;
+         xferchan = execchan;
+       }
+      else if (memaddr >= text_start && memaddr < text_end)
+       {
+           struct shared_library *lib;
+           for (lib = shlib; lib; lib = lib->shares)
+               if (memaddr >= lib->text_start &&
+                   memaddr < lib->text_start + lib->header.a_exec.a_text)
+                   break;
+           if (lib) {
+               i = min (len, lib->header.a_exec.a_text +
+                        lib->text_start - memaddr);
+               fileptr = memaddr - lib->text_start + text_offset;
+               xferfile = &execfile;
+               xferchan = lib->chan;
+           } else {
+               i = min (len, text_end - memaddr);
+               fileptr = memaddr - unshared_text_start + text_offset;
+               xferfile = &execfile;
+               xferchan = execchan;
+           }
+       }
+      else if (memaddr < text_start)
+       {
+         i = min (len, text_start - memaddr);
+       }
+      else if (memaddr >= text_end
+              && memaddr < (corechan >= 0? data_start : exec_data_start))
+       {
+         i = min (len, data_start - memaddr);
+       }
+      else if (corechan >= 0
+              && memaddr >= data_end && memaddr < stack_start)
+       {
+         i = min (len, stack_start - memaddr);
+       }
+      else if (corechan < 0 && memaddr >= exec_data_end)
+       {
+         i = min (len, - memaddr);
+       }
+      else if (memaddr >= stack_end && stack_end != 0)
+       {
+         i = min (len, - memaddr);
+       }
+      else
+       {
+         /* Address did not classify into one of the known ranges.
+            This shouldn't happen; we catch the endpoints.  */
+         fatal ("Internal: Bad case logic in xfer_core_file.");
+       }
+
+      /* Now we know which file to use.
+        Set up its pointer and transfer the data.  */
+      if (xferfile)
+       {
+         if (*xferfile == 0)
+           if (xferfile == &execfile)
+             error ("No program file to examine.");
+           else
+             error ("No core dump file or running program to examine.");
+         val = lseek (xferchan, fileptr, 0);
+         if (val < 0)
+           perror_with_name (*xferfile);
+         val = myread (xferchan, myaddr, i);
+         if (val < 0)
+           perror_with_name (*xferfile);
+       }
+      /* If this address is for nonexistent memory,
+        read zeros if reading, or do nothing if writing.
+        Actually, we never right.  */
+      else
+       {
+         bzero (myaddr, i);
+         returnval = EIO;
+       }
+
+      memaddr += i;
+      myaddr += i;
+      len -= i;
+    }
+  return returnval;
+}
+\f
+/* APCS (ARM procedure call standard) defines the following prologue:
+
+   mov         ip, sp
+  [stmfd       sp!, {a1,a2,a3,a4}]
+   stmfd       sp!, {...,fp,ip,lr,pc}
+  [stfe                f7, [sp, #-12]!]
+  [stfe                f6, [sp, #-12]!]
+  [stfe                f5, [sp, #-12]!]
+  [stfe                f4, [sp, #-12]!]
+   sub         fp, ip, #nn     // nn == 20 or 4 depending on second ins
+*/
+
+CORE_ADDR
+skip_prologue(pc)
+CORE_ADDR pc;
+{
+    union insn_fmt op;
+    CORE_ADDR skip_pc = pc;
+
+    op.ins = read_memory_integer(skip_pc, 4);
+    /* look for the "mov ip,sp" */
+    if (op.generic.type != TYPE_ARITHMETIC ||
+       op.arith.opcode != OPCODE_MOV ||
+       op.arith.dest != SPTEMP ||
+       op.arith.operand2 != SP) return pc;
+    skip_pc += 4;
+    /* skip the "stmfd sp!,{a1,a2,a3,a4}" if its there */
+    op.ins = read_memory_integer(skip_pc, 4);
+    if (op.generic.type == TYPE_BLOCK_BRANCH &&
+       op.generic.subtype == SUBTYPE_BLOCK &&
+       op.block.mask == 0xf &&
+       op.block.base == SP &&
+       op.block.is_load == 0 &&
+       op.block.writeback == 1 &&
+       op.block.increment == 0 &&
+       op.block.before == 1) skip_pc += 4;
+    /* skip the "stmfd sp!,{...,fp,ip,lr,pc} */
+    op.ins = read_memory_integer(skip_pc, 4);
+    if (op.generic.type != TYPE_BLOCK_BRANCH ||
+       op.generic.subtype != SUBTYPE_BLOCK ||
+       /* the mask should look like 110110xxxxxx0000 */
+       (op.block.mask & 0xd800) != 0xd800 ||
+       op.block.base != SP ||
+       op.block.is_load != 0 ||
+       op.block.writeback != 1 ||
+       op.block.increment != 0 ||
+       op.block.before != 1) return pc;
+    skip_pc += 4;
+    /* check for "sub fp,ip,#nn" */
+    op.ins = read_memory_integer(skip_pc, 4);
+    if (op.generic.type != TYPE_ARITHMETIC ||
+       op.arith.opcode != OPCODE_SUB ||
+       op.arith.dest != FP ||
+       op.arith.operand1 != SPTEMP) return pc;
+    return skip_pc + 4;
+}
+
+static void
+print_fpu_flags(flags)
+int flags;
+{
+    if (flags & (1 << 0)) fputs("IVO ", stdout);
+    if (flags & (1 << 1)) fputs("DVZ ", stdout);
+    if (flags & (1 << 2)) fputs("OFL ", stdout);
+    if (flags & (1 << 3)) fputs("UFL ", stdout);
+    if (flags & (1 << 4)) fputs("INX ", stdout);
+    putchar('\n');
+}
+
+void
+arm_float_info()
+{
+    register unsigned long status = read_register(FPS_REGNUM);
+    int type;
+
+    type = (status >> 24) & 127;
+    printf("%s FPU type %d\n",
+          (status & (1<<31)) ? "Hardware" : "Software",
+          type);
+    fputs("mask: ", stdout);
+    print_fpu_flags(status >> 16);
+    fputs("flags: ", stdout);
+    print_fpu_flags(status);
+}
diff --git a/gdb/arm-xdep.c b/gdb/arm-xdep.c
new file mode 100644 (file)
index 0000000..b397974
--- /dev/null
@@ -0,0 +1,274 @@
+/* Acorn Risc Machine host machine support.
+   Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "arm-opcode.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#define N_TXTADDR(hdr) 0x8000
+#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
+
+#include "gdbcore.h"
+
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+  register int regno;
+  register unsigned int regaddr;
+  char buf[MAX_REGISTER_RAW_SIZE];
+  register int i;
+
+  struct user u;
+  unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+  offset = ptrace (PT_READ_U, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+  registers_fetched ();
+  
+  for (regno = 0; regno < 16; regno++)
+    {
+      regaddr = offset + regno * 4;
+      *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid, regaddr, 0);
+      if (regno == PC_REGNUM)
+         *(int *)&buf[0] = GET_PC_PART(*(int *)&buf[0]);
+      supply_register (regno, buf);
+    }
+  *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid, offset + PC*4);
+  supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */
+
+  /* read the floating point registers */
+  offset = (char *) &u.u_fp_regs - (char *)&u;
+  *(int *)buf = ptrace (PT_READ_U, inferior_pid, offset, 0);
+  supply_register (FPS_REGNUM, buf);
+  for (regno = 16; regno < 24; regno++) {
+      regaddr = offset + 4 + 12 * (regno - 16);
+      for (i = 0; i < 12; i += sizeof(int))
+         *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid, regaddr + i, 0);
+      supply_register (regno, buf);
+  }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+
+  struct user u;
+  unsigned long value;
+  unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+  offset = ptrace (PT_READ_U, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+  if (regno >= 0) {
+      if (regno >= 16) return;
+      regaddr = offset + 4 * regno;
+      errno = 0;
+      value = read_register(regno);
+      if (regno == PC_REGNUM)
+         value = SET_PC_PART(read_register (PS_REGNUM), value);
+      ptrace (PT_WRITE_U, inferior_pid, regaddr, value);
+      if (errno != 0)
+       {
+         sprintf (buf, "writing register number %d", regno);
+         perror_with_name (buf);
+       }
+    }
+  else for (regno = 0; regno < 15; regno++)
+    {
+      regaddr = offset + regno * 4;
+      errno = 0;
+      value = read_register(regno);
+      if (regno == PC_REGNUM)
+         value = SET_PC_PART(read_register (PS_REGNUM), value);
+      ptrace (6, inferior_pid, regaddr, value);
+      if (errno != 0)
+       {
+         sprintf (buf, "writing all regs, number %d", regno);
+         perror_with_name (buf);
+       }
+    }
+}
+\f
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+/* Structure to describe the chain of shared libraries used
+   by the execfile.
+   e.g. prog shares Xt which shares X11 which shares c. */
+
+struct shared_library {
+    struct exec_header header;
+    char name[SHLIBLEN];
+    CORE_ADDR text_start;      /* CORE_ADDR of 1st byte of text, this file */
+    long data_offset;          /* offset of data section in file */
+    int chan;                  /* file descriptor for the file */
+    struct shared_library *shares; /* library this one shares */
+};
+static struct shared_library *shlib = 0;
+
+/* Hook for `exec_file_command' command to call.  */
+
+extern void (*exec_file_display_hook) ();
+   
+static CORE_ADDR unshared_text_start;
+
+/* extended header from exec file (for shared library info) */
+
+static struct exec_header exec_header;
+\f
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+       struct user u;
+
+       unsigned int reg_offset, fp_reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name ("Not a core file: reading upage");
+       if (val != sizeof u)
+         error ("Not a core file: could only read %d bytes", val);
+
+       /* We are depending on exec_file_command having been called
+          previously to set exec_data_start.  Since the executable
+          and the core file share the same text segment, the address
+          of the data segment will be the same in both.  */
+       data_start = exec_data_start;
+
+       data_end = data_start + NBPG * u.u_dsize;
+       stack_start = stack_end - NBPG * u.u_ssize;
+       data_offset = NBPG * UPAGES;
+       stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+       /* Some machines put an absolute address in here and some put
+          the offset in the upage of the regs.  */
+       reg_offset = (int) u.u_ar0;
+       if (reg_offset > NBPG * UPAGES)
+         reg_offset -= KERNEL_U_ADDR;
+       fp_reg_offset = (char *) &u.u_fp_regs - (char *)&u;
+
+       /* I don't know where to find this info.
+          So, for now, mark it as not available.  */
+       N_SET_MAGIC (core_aouthdr, 0);
+
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < NUM_REGS; regno++)
+           {
+             char buf[MAX_REGISTER_RAW_SIZE];
+
+             if (regno < 16)
+                 val = lseek (corechan, reg_offset + 4 * regno, 0);
+             else if (regno < 24)
+                 val = lseek (corechan, fp_reg_offset + 4 + 12*(regno - 24), 0);
+             else if (regno == 24)
+                 val = lseek (corechan, fp_reg_offset, 0);
+             else if (regno == 25)
+                 val = lseek (corechan, reg_offset + 4 * PC, 0);
+             if (val < 0
+                 || (val = myread (corechan, buf, sizeof buf)) < 0)
+               {
+                 char * buffer = (char *) alloca (strlen (reg_names[regno])
+                                                  + 30);
+                 strcpy (buffer, "Reading register ");
+                 strcat (buffer, reg_names[regno]);
+                                                  
+                 perror_with_name (buffer);
+               }
+
+             if (regno == PC_REGNUM)
+                 *(int *)buf = GET_PC_PART(*(int *)buf);
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
new file mode 100644 (file)
index 0000000..7971166
--- /dev/null
@@ -0,0 +1,650 @@
+/* Get info from stack frames;
+   convert between frames, blocks, functions and pc values.
+   Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "value.h"             /* for read_register */
+#include "target.h"            /* for target_has_stack */
+
+/* Required by INIT_EXTRA_FRAME_INFO on 88k.  */
+#include <setjmp.h>
+#include <obstack.h>
+
+CORE_ADDR read_pc ();          /* In infcmd.c */
+
+/* Start and end of object file containing the entry point.
+   STARTUP_FILE_END is the first address of the next file.
+   This file is assumed to be a startup file
+   and frames with pc's inside it
+   are treated as nonexistent.
+
+   Setting these variables is necessary so that backtraces do not fly off
+   the bottom of the stack.  */
+CORE_ADDR startup_file_start;
+CORE_ADDR startup_file_end;
+
+/* Is ADDR outside the startup file?  Note that if your machine
+   has a way to detect the bottom of the stack, there is no need
+   to call this function from FRAME_CHAIN_VALID; the reason for
+   doing so is that some machines have no way of detecting bottom
+   of stack.  */
+int
+outside_startup_file (addr)
+     CORE_ADDR addr;
+{
+  return !(addr >= startup_file_start && addr < startup_file_end);
+}
+
+/* Address of innermost stack frame (contents of FP register) */
+
+static FRAME current_frame;
+
+/*
+ * Cache for frame addresses already read by gdb.  Valid only while
+ * inferior is stopped.  Control variables for the frame cache should
+ * be local to this module.
+ */
+struct obstack frame_cache_obstack;
+
+/* Return the innermost (currently executing) stack frame.  */
+
+FRAME
+get_current_frame ()
+{
+  /* We assume its address is kept in a general register;
+     param.h says which register.  */
+
+  return current_frame;
+}
+
+void
+set_current_frame (frame)
+     FRAME frame;
+{
+  current_frame = frame;
+}
+
+FRAME
+create_new_frame (addr, pc)
+     FRAME_ADDR addr;
+     CORE_ADDR pc;
+{
+  struct frame_info *fci;      /* Same type as FRAME */
+
+  fci = (struct frame_info *)
+    obstack_alloc (&frame_cache_obstack,
+                  sizeof (struct frame_info));
+
+  /* Arbitrary frame */
+  fci->next = (struct frame_info *) 0;
+  fci->prev = (struct frame_info *) 0;
+  fci->frame = addr;
+  fci->next_frame = 0;         /* Since arbitrary */
+  fci->pc = pc;
+
+#ifdef INIT_EXTRA_FRAME_INFO
+  INIT_EXTRA_FRAME_INFO (fci);
+#endif
+
+  return fci;
+}
+
+/* Return the frame that called FRAME.
+   If FRAME is the original frame (it has no caller), return 0.  */
+
+FRAME
+get_prev_frame (frame)
+     FRAME frame;
+{
+  /* We're allowed to know that FRAME and "struct frame_info *" are
+     the same */
+  return get_prev_frame_info (frame);
+}
+
+/* Return the frame that FRAME calls (0 if FRAME is the innermost
+   frame).  */
+
+FRAME
+get_next_frame (frame)
+     FRAME frame;
+{
+  /* We're allowed to know that FRAME and "struct frame_info *" are
+     the same */
+  return frame->next;
+}
+
+/*
+ * Flush the entire frame cache.
+ */
+void
+flush_cached_frames ()
+{
+  /* Since we can't really be sure what the first object allocated was */
+  obstack_free (&frame_cache_obstack, 0);
+  obstack_init (&frame_cache_obstack);
+
+  current_frame = (struct frame_info *) 0; /* Invalidate cache */
+}
+
+/* Return a structure containing various interesting information
+   about a specified stack frame.  */
+/* How do I justify including this function?  Well, the FRAME
+   identifier format has gone through several changes recently, and
+   it's not completely inconceivable that it could happen again.  If
+   it does, have this routine around will help */
+
+struct frame_info *
+get_frame_info (frame)
+     FRAME frame;
+{
+  return frame;
+}
+
+/* If a machine allows frameless functions, it should define a macro
+   FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) in param.h.  FI is the struct
+   frame_info for the frame, and FRAMELESS should be set to nonzero
+   if it represents a frameless function invocation.  */
+
+/* Return nonzero if the function for this frame has a prologue.  Many
+   machines can define FRAMELESS_FUNCTION_INVOCATION to just call this
+   function.  */
+
+int
+frameless_look_for_prologue (frame)
+     FRAME frame;
+{
+  CORE_ADDR func_start, after_prologue;
+  func_start = (get_pc_function_start (frame->pc) +
+               FUNCTION_START_OFFSET);
+  if (func_start)
+    {
+      after_prologue = func_start;
+      SKIP_PROLOGUE (after_prologue);
+      return after_prologue == func_start;
+    }
+  else
+    /* If we can't find the start of the function, we don't really
+       know whether the function is frameless, but we should be able
+       to get a reasonable (i.e. best we can do under the
+       circumstances) backtrace by saying that it isn't.  */
+    return 0;
+}
+
+#if !defined (INIT_FRAME_PC)
+#define INIT_FRAME_PC(fromleaf, prev) \
+  prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) : \
+             prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
+#endif
+
+/* Return a structure containing various interesting information
+   about the frame that called NEXT_FRAME.  Returns NULL
+   if there is no such frame.  */
+
+struct frame_info *
+get_prev_frame_info (next_frame)
+     FRAME next_frame;
+{
+  FRAME_ADDR address;
+  struct frame_info *prev;
+  int fromleaf = 0;
+
+  /* If the requested entry is in the cache, return it.
+     Otherwise, figure out what the address should be for the entry
+     we're about to add to the cache. */
+
+  if (!next_frame)
+    {
+      if (!current_frame)
+       {
+         error ("You haven't set up a process's stack to examine.");
+       }
+
+      return current_frame;
+    }
+
+  /* If we have the prev one, return it */
+  if (next_frame->prev)
+    return next_frame->prev;
+
+  /* On some machines it is possible to call a function without
+     setting up a stack frame for it.  On these machines, we
+     define this macro to take two args; a frameinfo pointer
+     identifying a frame and a variable to set or clear if it is
+     or isn't leafless.  */
+#ifdef FRAMELESS_FUNCTION_INVOCATION
+  /* Still don't want to worry about this except on the innermost
+     frame.  This macro will set FROMLEAF if NEXT_FRAME is a
+     frameless function invocation.  */
+  if (!(next_frame->next))
+    {
+      FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf);
+      if (fromleaf)
+       address = next_frame->frame;
+    }
+#endif
+
+  if (!fromleaf)
+    {
+      /* Two macros defined in tm.h specify the machine-dependent
+        actions to be performed here.
+        First, get the frame's chain-pointer.
+        If that is zero, the frame is the outermost frame or a leaf
+        called by the outermost frame.  This means that if start
+        calls main without a frame, we'll return 0 (which is fine
+        anyway).
+
+        Nope; there's a problem.  This also returns when the current
+        routine is a leaf of main.  This is unacceptable.  We move
+        this to after the ffi test; I'd rather have backtraces from
+        start go curfluy than have an abort called from main not show
+        main.  */
+      address = FRAME_CHAIN (next_frame);
+      if (!FRAME_CHAIN_VALID (address, next_frame))
+       return 0;
+      address = FRAME_CHAIN_COMBINE (address, next_frame);
+    }
+
+  prev = (struct frame_info *)
+    obstack_alloc (&frame_cache_obstack,
+                  sizeof (struct frame_info));
+
+  if (next_frame)
+    next_frame->prev = prev;
+  prev->next = next_frame;
+  prev->prev = (struct frame_info *) 0;
+  prev->frame = address;
+  prev->next_frame = prev->next ? prev->next->frame : 0;
+
+#ifdef INIT_EXTRA_FRAME_INFO
+  INIT_EXTRA_FRAME_INFO(prev);
+#endif
+
+  /* This entry is in the frame queue now, which is good since
+     FRAME_SAVED_PC may use that queue to figure out it's value
+     (see m-sparc.h).  We want the pc saved in the inferior frame. */
+  INIT_FRAME_PC(fromleaf, prev);
+
+  return prev;
+}
+
+CORE_ADDR
+get_frame_pc (frame)
+     FRAME frame;
+{
+  struct frame_info *fi;
+  fi = get_frame_info (frame);
+  return fi->pc;
+}
+
+#if defined (FRAME_FIND_SAVED_REGS)
+/* Find the addresses in which registers are saved in FRAME.  */
+
+void
+get_frame_saved_regs (frame_info_addr, saved_regs_addr)
+     struct frame_info *frame_info_addr;
+     struct frame_saved_regs *saved_regs_addr;
+{
+  FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr);
+}
+#endif
+
+/* Return the innermost lexical block in execution
+   in a specified stack frame.  The frame address is assumed valid.  */
+
+struct block *
+get_frame_block (frame)
+     FRAME frame;
+{
+  struct frame_info *fi;
+  CORE_ADDR pc;
+
+  fi = get_frame_info (frame);
+
+  pc = fi->pc;
+  if (fi->next_frame != 0)
+    /* We are not in the innermost frame.  We need to subtract one to
+       get the correct block, in case the call instruction was the
+       last instruction of the block.  If there are any machines on
+       which the saved pc does not point to after the call insn, we
+       probably want to make fi->pc point after the call insn anyway.  */
+    --pc;
+  return block_for_pc (pc);
+}
+
+struct block *
+get_current_block ()
+{
+  return block_for_pc (read_pc ());
+}
+
+CORE_ADDR
+get_pc_function_start (pc)
+     CORE_ADDR pc;
+{
+  register struct block *bl = block_for_pc (pc);
+  register struct symbol *symbol;
+  if (bl == 0 || (symbol = block_function (bl)) == 0)
+    {
+      register int misc_index = find_pc_misc_function (pc);
+      if (misc_index >= 0)
+       return misc_function_vector[misc_index].address;
+      return 0;
+    }
+  bl = SYMBOL_BLOCK_VALUE (symbol);
+  return BLOCK_START (bl);
+}
+
+/* Return the symbol for the function executing in frame FRAME.  */
+
+struct symbol *
+get_frame_function (frame)
+     FRAME frame;
+{
+  register struct block *bl = get_frame_block (frame);
+  if (bl == 0)
+    return 0;
+  return block_function (bl);
+}
+\f
+/* Return the blockvector immediately containing the innermost lexical block
+   containing the specified pc value, or 0 if there is none.
+   PINDEX is a pointer to the index value of the block.  If PINDEX
+   is NULL, we don't pass this information back to the caller.  */
+
+struct blockvector *
+blockvector_for_pc (pc, pindex)
+     register CORE_ADDR pc;
+     int *pindex;
+{
+  register struct block *b;
+  register int bot, top, half;
+  register struct symtab *s;
+  struct blockvector *bl;
+
+  /* First search all symtabs for one whose file contains our pc */
+  s = find_pc_symtab (pc);
+  if (s == 0)
+    return 0;
+
+  bl = BLOCKVECTOR (s);
+  b = BLOCKVECTOR_BLOCK (bl, 0);
+
+  /* Then search that symtab for the smallest block that wins.  */
+  /* Use binary search to find the last block that starts before PC.  */
+
+  bot = 0;
+  top = BLOCKVECTOR_NBLOCKS (bl);
+
+  while (top - bot > 1)
+    {
+      half = (top - bot + 1) >> 1;
+      b = BLOCKVECTOR_BLOCK (bl, bot + half);
+      if (BLOCK_START (b) <= pc)
+       bot += half;
+      else
+       top = bot + half;
+    }
+
+  /* Now search backward for a block that ends after PC.  */
+
+  while (bot >= 0)
+    {
+      b = BLOCKVECTOR_BLOCK (bl, bot);
+      if (BLOCK_END (b) > pc)
+       {
+         if (pindex)
+           *pindex = bot;
+         return bl;
+       }
+      bot--;
+    }
+
+  return 0;
+}
+
+/* Return the innermost lexical block containing the specified pc value,
+   or 0 if there is none.  */
+
+struct block *
+block_for_pc (pc)
+     register CORE_ADDR pc;
+{
+  register struct blockvector *bl;
+  int index;
+
+  bl = blockvector_for_pc (pc, &index);
+  if (bl)
+    return BLOCKVECTOR_BLOCK (bl, index);
+  return 0;
+}
+
+/* Return the function containing pc value PC.
+   Returns 0 if function is not known.  */
+
+struct symbol *
+find_pc_function (pc)
+     CORE_ADDR pc;
+{
+  register struct block *b = block_for_pc (pc);
+  if (b == 0)
+    return 0;
+  return block_function (b);
+}
+
+/* These variables are used to cache the most recent result
+ * of find_pc_partial_function. */
+
+static CORE_ADDR cache_pc_function_low = 0;
+static CORE_ADDR cache_pc_function_high = 0;
+static char *cache_pc_function_name = 0;
+
+/* Clear cache, e.g. when symbol table is discarded. */
+
+void
+clear_pc_function_cache()
+{
+  cache_pc_function_low = 0;
+  cache_pc_function_high = 0;
+  cache_pc_function_name = (char *)0;
+}
+
+/* Finds the "function" (text symbol) that is smaller than PC
+   but greatest of all of the potential text symbols.  Sets
+   *NAME and/or *ADDRESS conditionally if that pointer is non-zero.
+   Returns 0 if it couldn't find anything, 1 if it did.  On a zero
+   return, *NAME and *ADDRESS are always set to zero.  On a 1 return,
+   *NAME and *ADDRESS contain real information.  */
+
+int
+find_pc_partial_function (pc, name, address)
+     CORE_ADDR pc;
+     char **name;
+     CORE_ADDR *address;
+{
+  struct partial_symtab *pst;
+  struct symbol *f;
+  int miscfunc;
+  struct partial_symbol *psb;
+
+  if (pc >= cache_pc_function_low && pc < cache_pc_function_high)
+    {
+       if (address)
+           *address = cache_pc_function_low;
+       if (name)
+           *name = cache_pc_function_name;
+       return 1;
+    }
+
+  pst = find_pc_psymtab (pc);
+  if (pst)
+    {
+      if (pst->readin)
+       {
+         /* The information we want has already been read in.
+            We can go to the already readin symbols and we'll get
+            the best possible answer.  */
+         f = find_pc_function (pc);
+         if (!f)
+           {
+           return_error:
+             /* No available symbol.  */
+             if (name != 0)
+               *name = 0;
+             if (address != 0)
+               *address = 0;
+             return 0;
+           }
+
+         cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
+         cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
+         cache_pc_function_name = SYMBOL_NAME (f);
+         if (name)
+           *name = cache_pc_function_name;
+         if (address)
+           *address = cache_pc_function_low;
+         return 1;
+       }
+
+      /* Get the information from a combination of the pst
+        (static symbols), and the misc function vector (extern
+        symbols).  */
+      miscfunc = find_pc_misc_function (pc);
+      psb = find_pc_psymbol (pst, pc);
+
+      if (!psb && miscfunc == -1)
+       {
+         goto return_error;
+       }
+      if (psb
+         && (miscfunc == -1
+             || (SYMBOL_VALUE_ADDRESS (psb)
+                 >= misc_function_vector[miscfunc].address)))
+       {
+         /* This case isn't being cached currently. */
+         if (address)
+           *address = SYMBOL_VALUE_ADDRESS (psb);
+         if (name)
+           *name = SYMBOL_NAME (psb);
+         return 1;
+       }
+    }
+  else
+    /* Must be in the misc function stuff.  */
+    {
+      miscfunc = find_pc_misc_function (pc);
+      if (miscfunc == -1)
+       goto return_error;
+    }
+
+  {
+    if (misc_function_vector[miscfunc].type == mf_text)
+      cache_pc_function_low = misc_function_vector[miscfunc].address;
+    else
+      /* It is a transfer table for Sun shared libraries.  */
+      cache_pc_function_low = pc - FUNCTION_START_OFFSET;
+  }
+  cache_pc_function_name = misc_function_vector[miscfunc].name;
+  if (miscfunc < misc_function_count && 1 /* FIXME mf_text again? */ )
+    cache_pc_function_high = misc_function_vector[miscfunc+1].address;
+  else
+    cache_pc_function_high = cache_pc_function_low + 1;
+  if (address)
+    *address = cache_pc_function_low;
+  if (name)
+    *name = cache_pc_function_name;
+  return 1;
+}
+
+/* Find the misc function whose address is the largest
+   while being less than PC.  Return its index in misc_function_vector.
+   Returns -1 if PC is not in suitable range.  */
+
+int
+find_pc_misc_function (pc)
+     register CORE_ADDR pc;
+{
+  register int lo = 0;
+  register int hi = misc_function_count-1;
+  register int new;
+
+  /* Note that the last thing in the vector is always _etext.  */
+  /* Actually, "end", now that non-functions
+     go on the misc_function_vector.  */
+
+  /* Above statement is not *always* true - fix for case where there are */
+  /* no misc functions at all (ie no symbol table has been read). */
+  if (hi < 0) return -1;        /* no misc functions recorded */
+
+  /* trivial reject range test */
+  if (pc < misc_function_vector[0].address ||
+      pc > misc_function_vector[hi].address)
+    return -1;
+
+  /* Note that the following search will not return hi if
+     pc == misc_function_vector[hi].address.  If "end" points to the
+     first unused location, this is correct and the above test
+     simply needs to be changed to
+     "pc >= misc_function_vector[hi].address".  */
+  do {
+    new = (lo + hi) >> 1;
+    if (misc_function_vector[new].address == pc)
+      return new;              /* an exact match */
+    else if (misc_function_vector[new].address > pc)
+      hi = new;
+    else
+      lo = new;
+  } while (hi-lo != 1);
+
+  /* if here, we had no exact match, so return the lower choice */
+  return lo;
+}
+
+/* Return the innermost stack frame executing inside of the specified block,
+   or zero if there is no such frame.  */
+
+FRAME
+block_innermost_frame (block)
+     struct block *block;
+{
+  struct frame_info *fi;
+  register FRAME frame;
+  register CORE_ADDR start = BLOCK_START (block);
+  register CORE_ADDR end = BLOCK_END (block);
+
+  frame = 0;
+  while (1)
+    {
+      frame = get_prev_frame (frame);
+      if (frame == 0)
+       return 0;
+      fi = get_frame_info (frame);
+      if (fi->pc >= start && fi->pc < end)
+       return frame;
+    }
+}
+
+void
+_initialize_blockframe ()
+{
+  obstack_init (&frame_cache_obstack);
+}
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
new file mode 100644 (file)
index 0000000..6bc621d
--- /dev/null
@@ -0,0 +1,2259 @@
+/* Everything about breakpoints, for GDB.
+   Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "expression.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "value.h"
+#include "ctype.h"
+#include "command.h"
+#include "inferior.h"
+#include "target.h"
+#include <string.h>
+
+extern int addressprint;               /* Print machine addresses? */
+extern int demangle;                   /* Print de-mangled symbol names? */
+
+extern int catch_errors ();
+extern void set_next_address ();       /* ...for x/ command */
+
+/* Are we executing breakpoint commands?  */
+static int executing_breakpoint_commands;
+
+/* States of enablement of breakpoint.
+   `temporary' means disable when hit.
+   `delete' means delete when hit.  */
+
+enum enable { disabled, enabled, temporary, delete};
+
+/* Not that the ->silent field is not currently used by any commands
+   (though the code is in there if it was to be and set_raw_breakpoint
+   does set it to 0).  I implemented it because I thought it would be
+   useful for a hack I had to put in; I'm going to leave it in because
+   I can see how there might be times when it would indeed be useful */
+
+/* This is for a breakpoint or a watchpoint.  */
+
+struct breakpoint
+{
+  struct breakpoint *next;
+  /* Number assigned to distinguish breakpoints.  */
+  int number;
+  /* Address to break at, or NULL if not a breakpoint.  */
+  CORE_ADDR address;
+  /* Line number of this address.  Redundant.  Only matters if address
+     is non-NULL.  */
+  int line_number;
+  /* Symtab of file of this address.  Redundant.  Only matters if address
+     is non-NULL.  */
+  struct symtab *symtab;
+  /* Zero means disabled; remember the info but don't break here.  */
+  enum enable enable;
+  /* Non-zero means a silent breakpoint (don't print frame info
+     if we stop here). */
+  unsigned char silent;
+  /* Number of stops at this breakpoint that should
+     be continued automatically before really stopping.  */
+  int ignore_count;
+  /* "Real" contents of byte where breakpoint has been inserted.
+     Valid only when breakpoints are in the program.  Under the complete
+     control of the target insert_breakpoint and remove_breakpoint routines.
+     No other code should assume anything about the value(s) here.  */
+  char shadow_contents[BREAKPOINT_MAX];
+  /* Nonzero if this breakpoint is now inserted.  Only matters if address
+     is non-NULL.  */
+  char inserted;
+  /* Nonzero if this is not the first breakpoint in the list
+     for the given address.  Only matters if address is non-NULL.  */
+  char duplicate;
+  /* Chain of command lines to execute when this breakpoint is hit.  */
+  struct command_line *commands;
+  /* Stack depth (address of frame).  If nonzero, break only if fp
+     equals this.  */
+  FRAME_ADDR frame;
+  /* Conditional.  Break only if this expression's value is nonzero.  */
+  struct expression *cond;
+
+  /* String we used to set the breakpoint (malloc'd).  Only matters if
+     address is non-NULL.  */
+  char *addr_string;
+  /* String form of the breakpoint condition (malloc'd), or NULL if there
+     is no condition.  */
+  char *cond_string;
+
+  /* The expression we are watching, or NULL if not a watchpoint.  */
+  struct expression *exp;
+  /* The largest block within which it is valid, or NULL if it is
+     valid anywhere (e.g. consists just of global symbols).  */
+  struct block *exp_valid_block;
+  /* Value of the watchpoint the last time we checked it.  */
+  value val;
+};
+
+#define ALL_BREAKPOINTS(b)  for (b = breakpoint_chain; b; b = b->next)
+
+/* Chain of all breakpoints defined.  */
+
+struct breakpoint *breakpoint_chain;
+
+/* Number of last breakpoint made.  */
+
+static int breakpoint_count;
+
+/* Set breakpoint count to NUM.  */
+static void
+set_breakpoint_count (num)
+     int num;
+{
+  breakpoint_count = num;
+  set_internalvar (lookup_internalvar ("bpnum"),
+                  value_from_long (builtin_type_int, (LONGEST) num));
+}
+
+/* Default address, symtab and line to put a breakpoint at
+   for "break" command with no arg.
+   if default_breakpoint_valid is zero, the other three are
+   not valid, and "break" with no arg is an error.
+
+   This set by print_stack_frame, which calls set_default_breakpoint.  */
+
+int default_breakpoint_valid;
+CORE_ADDR default_breakpoint_address;
+struct symtab *default_breakpoint_symtab;
+int default_breakpoint_line;
+
+static void delete_breakpoint ();
+void breakpoint_auto_delete ();
+
+/* Flag indicating extra verbosity for xgdb.  */
+extern int xgdb_verbose;
+\f
+/* *PP is a string denoting a breakpoint.  Get the number of the breakpoint.
+   Advance *PP after the string and any trailing whitespace.
+
+   Currently the string can either be a number or "$" followed by the name
+   of a convenience variable.  Making it an expression wouldn't work well
+   for map_breakpoint_numbers (e.g. "4 + 5 + 6").  */
+static int
+get_number (pp)
+     char **pp;
+{
+  int retval;
+  char *p = *pp;
+
+  if (p == NULL)
+    /* Empty line means refer to the last breakpoint.  */
+    return breakpoint_count;
+  else if (*p == '$')
+    {
+      /* Make a copy of the name, so we can null-terminate it
+        to pass to lookup_internalvar().  */
+      char *varname;
+      char *start = ++p;
+      value val;
+
+      while (isalnum (*p) || *p == '_')
+       p++;
+      varname = (char *) alloca (p - start + 1);
+      strncpy (varname, start, p - start);
+      varname[p - start] = '\0';
+      val = value_of_internalvar (lookup_internalvar (varname));
+      if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_INT)
+       error (
+"Convenience variables used to specify breakpoints must have integer values."
+              );
+      retval = (int) value_as_long (val);
+    }
+  else
+    {
+      while (*p >= '0' && *p <= '9')
+       ++p;
+      if (p == *pp)
+       /* There is no number here.  (e.g. "cond a == b").  */
+       error_no_arg ("breakpoint number");
+      retval = atoi (*pp);
+    }
+  if (!(isspace (*p) || *p == '\0'))
+    error ("breakpoint number expected");
+  while (isspace (*p))
+    p++;
+  *pp = p;
+  return retval;
+}
+\f
+/* condition N EXP -- set break condition of breakpoint N to EXP.  */
+
+static void
+condition_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register struct breakpoint *b;
+  char *p;
+  register int bnum;
+
+  if (arg == 0)
+    error_no_arg ("breakpoint number");
+
+  p = arg;
+  bnum = get_number (&p);
+
+  ALL_BREAKPOINTS (b)
+    if (b->number == bnum)
+      {
+       if (b->cond)
+         {
+           free (b->cond);
+           b->cond = 0;
+         }
+       if (b->cond_string != NULL)
+         free (b->cond_string);
+
+       if (*p == 0)
+         {
+           b->cond = 0;
+           b->cond_string = NULL;
+           if (from_tty)
+             printf ("Breakpoint %d now unconditional.\n", bnum);
+         }
+       else
+         {
+           arg = p;
+           /* I don't know if it matters whether this is the string the user
+              typed in or the decompiled expression.  */
+           b->cond_string = savestring (arg, strlen (arg));
+           b->cond = parse_c_1 (&arg, block_for_pc (b->address), 0);
+           if (*arg)
+             error ("Junk at end of expression");
+         }
+       return;
+      }
+
+  error ("No breakpoint number %d.", bnum);
+}
+
+static void
+commands_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register struct breakpoint *b;
+  char *p;
+  register int bnum;
+  struct command_line *l;
+
+  /* If we allowed this, we would have problems with when to
+     free the storage, if we change the commands currently
+     being read from.  */
+
+  if (executing_breakpoint_commands)
+    error ("Can't use the \"commands\" command among a breakpoint's commands.");
+
+  p = arg;
+  bnum = get_number (&p);
+  if (p && *p)
+    error ("Unexpected extra arguments following breakpoint number.");
+      
+  ALL_BREAKPOINTS (b)
+    if (b->number == bnum)
+      {
+       if (input_from_terminal_p ())
+         {
+           printf ("Type commands for when breakpoint %d is hit, one per line.\n\
+End with a line saying just \"end\".\n", bnum);
+           fflush (stdout);
+         }
+       l = read_command_lines ();
+       free_command_lines (&b->commands);
+       b->commands = l;
+       return;
+      }
+  error ("No breakpoint number %d.", bnum);
+}
+\f
+/* insert_breakpoints is used when starting or continuing the program.
+   remove_breakpoints is used when the program stops.
+   Both return zero if successful,
+   or an `errno' value if could not write the inferior.  */
+
+int
+insert_breakpoints ()
+{
+  register struct breakpoint *b;
+  int val = 0;
+  int disabled_breaks = 0;
+
+  ALL_BREAKPOINTS (b)
+    if (b->address != NULL
+       && b->enable != disabled
+       && ! b->inserted
+       && ! b->duplicate)
+      {
+       val = target_insert_breakpoint(b->address, b->shadow_contents);
+       if (val)
+         {
+           /* Can't set the breakpoint.  */
+#if defined (DISABLE_UNSETTABLE_BREAK)
+           if (DISABLE_UNSETTABLE_BREAK (b->address))
+             {
+               val = 0;
+               b->enable = disabled;
+               if (!disabled_breaks)
+                 {
+                   fprintf (stderr,
+                        "Cannot insert breakpoint %d:\n", b->number);
+                   printf_filtered ("Disabling shared library breakpoints:\n");
+                 }
+               disabled_breaks = 1;
+               printf_filtered ("%d ", b->number);
+             }
+           else
+#endif
+             {
+               fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number);
+               memory_error (val, b->address); /* which bombs us out */
+             }
+         }
+       else
+         b->inserted = 1;
+      }
+  if (disabled_breaks)
+    printf_filtered ("\n");
+  return val;
+}
+
+int
+remove_breakpoints ()
+{
+  register struct breakpoint *b;
+  int val;
+
+#ifdef BREAKPOINT_DEBUG
+  printf ("Removing breakpoints.\n");
+#endif /* BREAKPOINT_DEBUG */
+
+  ALL_BREAKPOINTS (b)
+    if (b->address != NULL && b->inserted)
+      {
+       val = target_remove_breakpoint(b->address, b->shadow_contents);
+       if (val)
+         return val;
+       b->inserted = 0;
+#ifdef BREAKPOINT_DEBUG
+       printf ("Removed breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
+               b->address, b->shadow_contents[0], b->shadow_contents[1]);
+#endif /* BREAKPOINT_DEBUG */
+      }
+
+  return 0;
+}
+
+/* Clear the "inserted" flag in all breakpoints.
+   This is done when the inferior is loaded.  */
+
+void
+mark_breakpoints_out ()
+{
+  register struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    b->inserted = 0;
+}
+
+/* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at PC.
+   When continuing from a location with a breakpoint,
+   we actually single step once before calling insert_breakpoints.  */
+
+int
+breakpoint_here_p (pc)
+     CORE_ADDR pc;
+{
+  register struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    if (b->enable != disabled && b->address == pc)
+      return 1;
+
+  return 0;
+}
+\f
+/* bpstat stuff.  External routines' interfaces are documented
+   in breakpoint.h.  */
+void
+bpstat_clear (bsp)
+     bpstat *bsp;
+{
+  bpstat p;
+  bpstat q;
+
+  if (bsp == 0)
+    return;
+  p = *bsp;
+  while (p != NULL)
+    {
+      q = p->next;
+      if (p->old_val != NULL)
+       value_free (p->old_val);
+      free (p);
+      p = q;
+    }
+  *bsp = NULL;
+}
+
+bpstat
+bpstat_copy (bs)
+     bpstat bs;
+{
+  bpstat p = NULL;
+  bpstat tmp;
+  bpstat retval;
+
+  if (bs == NULL)
+    return bs;
+
+  for (; bs != NULL; bs = bs->next)
+    {
+      tmp = (bpstat) xmalloc (sizeof (*tmp));
+      bcopy (bs, tmp, sizeof (*tmp));
+      if (p == NULL)
+       /* This is the first thing in the chain.  */
+       retval = tmp;
+      else
+       p->next = tmp;
+      p = tmp;
+    }
+  p->next = NULL;
+  return retval;
+}
+
+int
+bpstat_num (bsp)
+     bpstat *bsp;
+{
+  struct breakpoint *b;
+
+  if ((*bsp) == NULL)
+    return 0;                  /* No more breakpoint values */
+  else
+    {
+      b = (*bsp)->breakpoint_at;
+      *bsp = (*bsp)->next;
+      if (b == NULL)
+       return -1;              /* breakpoint that's been deleted since */
+      else
+        return b->number;      /* We have its number */
+    }
+}
+
+void
+bpstat_clear_actions (bs)
+     bpstat bs;
+{
+  for (; bs != NULL; bs = bs->next)
+    {
+      bs->commands = NULL;
+      if (bs->old_val != NULL)
+       {
+         value_free (bs->old_val);
+         bs->old_val = NULL;
+       }
+    }
+}
+
+/* Execute all the commands associated with all the breakpoints at this
+   location.  Any of these commands could cause the process to proceed
+   beyond this point, etc.  We look out for such changes by checking
+   the global "breakpoint_proceeded" after each command.  */
+void
+bpstat_do_actions (bsp)
+     bpstat *bsp;
+{
+  bpstat bs;
+
+top:
+  bs = *bsp;
+
+  executing_breakpoint_commands = 1;
+  breakpoint_proceeded = 0;
+  for (; bs != NULL; bs = bs->next)
+    {
+      while (bs->commands)
+       {
+         char *line = bs->commands->line;
+         bs->commands = bs->commands->next;
+         execute_command (line, 0);
+         /* If the inferior is proceeded by the command, bomb out now.
+            The bpstat chain has been blown away by wait_for_inferior.
+            But since execution has stopped again, there is a new bpstat
+            to look at, so start over.  */
+         if (breakpoint_proceeded)
+           goto top;
+       }
+    }
+  clear_momentary_breakpoints ();
+
+  executing_breakpoint_commands = 0;
+}
+
+int
+bpstat_print (bs)
+     bpstat bs;
+{
+  /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
+     which has since been deleted.  */
+  if (bs == NULL || bs->breakpoint_at == NULL)
+    return 0;
+  
+  /* If bpstat_stop_status says don't print, OK, we won't.  An example
+     circumstance is when we single-stepped for both a watchpoint and
+     for a "stepi" instruction.  The bpstat says that the watchpoint
+     explains the stop, but we shouldn't print because the watchpoint's
+     value didn't change -- and the real reason we are stopping here
+     rather than continuing to step (as the watchpoint would've had us do)
+     is because of the "stepi".  */
+  if (!bs->print)
+    return 0;
+
+  if (bs->breakpoint_at->address != NULL)
+    {
+      /* I think the user probably only wants to see one breakpoint
+        number, not all of them.  */
+      printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number);
+      return 0;
+    }
+      
+  if (bs->old_val != NULL)
+    {
+      printf_filtered ("\nWatchpoint %d, ", bs->breakpoint_at->number);
+      print_expression (bs->breakpoint_at->exp, stdout);
+      printf_filtered ("\nOld value = ");
+      value_print (bs->old_val, stdout, 0, Val_pretty_default);
+      printf_filtered ("\nNew value = ");
+      value_print (bs->breakpoint_at->val, stdout, 0,
+                  Val_pretty_default);
+      printf_filtered ("\n");
+      value_free (bs->old_val);
+      bs->old_val = NULL;
+      return 1;
+    }
+
+  fprintf_filtered (stderr, "gdb internal error: in bpstat_print\n");
+  return 0;
+}
+
+/* Evaluate the expression EXP and return 1 if value is zero.
+   This is used inside a catch_errors to evaluate the breakpoint condition. 
+   The argument is a "struct expression *" that has been cast to int to 
+   make it pass through catch_errors.  */
+
+static int
+breakpoint_cond_eval (exp)
+     int exp;
+{
+  return value_zerop (evaluate_expression ((struct expression *)exp));
+}
+
+/* Allocate a new bpstat and chain it to the current one.  */
+
+static bpstat
+bpstat_alloc (b, cbs)
+     register struct breakpoint *b;
+     bpstat cbs;                       /* Current "bs" value */
+{
+  bpstat bs;
+
+  bs = (bpstat) xmalloc (sizeof (*bs));
+  cbs->next = bs;
+  bs->breakpoint_at = b;
+  /* If the condition is false, etc., don't do the commands.  */
+  bs->commands = NULL;
+  bs->momentary = b->number == -3;
+  bs->old_val = NULL;
+  return bs;
+}
+
+/* Determine whether we stopped at a breakpoint, etc, or whether we
+   don't understand this stop.  Result is a chain of bpstat's such that:
+
+       if we don't understand the stop, the result is a null pointer.
+
+       if we understand why we stopped, the result is not null, and
+       the first element of the chain contains summary "stop" and
+       "print" flags for the whole chain.
+
+       Each element of the chain refers to a particular breakpoint or
+       watchpoint at which we have stopped.  (We may have stopped for
+       several reasons.)
+
+       Each element of the chain has valid next, breakpoint_at,
+       commands, FIXME??? fields.
+
+ */
+
+       
+bpstat
+bpstat_stop_status (pc, frame_address)
+     CORE_ADDR *pc;
+     FRAME_ADDR frame_address;
+{
+  register struct breakpoint *b;
+  int stop = 0;
+  int print = 0;
+  CORE_ADDR bp_addr;
+  /* True if we've hit a breakpoint (as opposed to a watchpoint).  */
+  int real_breakpoint = 0;
+  /* Root of the chain of bpstat's */
+  struct bpstat__struct root_bs[1];
+  /* Pointer to the last thing in the chain currently.  */
+  bpstat bs = root_bs;
+
+  /* Get the address where the breakpoint would have been.  */
+  bp_addr = *pc - DECR_PC_AFTER_BREAK;
+
+  ALL_BREAKPOINTS (b)
+    {
+      int this_bp_stop;
+      int this_bp_print;
+
+      if (b->enable == disabled)
+       continue;
+      if (b->address != NULL && b->address != bp_addr)
+       continue;
+
+      bs = bpstat_alloc (b, bs);       /* Alloc a bpstat to explain stop */
+
+      this_bp_stop = 1;
+      this_bp_print = 1;
+
+      if (b->exp != NULL)              /* Watchpoint */
+       {
+         int within_current_scope;
+         if (b->exp_valid_block != NULL)
+           within_current_scope =
+             contained_in (get_selected_block (), b->exp_valid_block);
+         else
+           within_current_scope = 1;
+
+         if (within_current_scope)
+           {
+             value new_val = evaluate_expression (b->exp);
+             release_value (new_val);
+             if (!value_equal (b->val, new_val))
+               {
+                 bs->old_val = b->val;
+                 b->val = new_val;
+                 /* We will stop here */
+               }
+             else
+               {
+                 /* Nothing changed, don't do anything.  */
+                 value_free (new_val);
+                 continue;
+                 /* We won't stop here */
+               }
+           }
+         else
+           {
+             /* This seems like the only logical thing to do because
+                if we temporarily ignored the watchpoint, then when
+                we reenter the block in which it is valid it contains
+                garbage (in the case of a function, it may have two
+                garbage values, one before and one after the prologue).
+                So we can't even detect the first assignment to it and
+                watch after that (since the garbage may or may not equal
+                the first value assigned).  */
+             b->enable = disabled;
+             printf_filtered ("\
+Watchpoint %d disabled because the program has left the block in\n\
+which its expression is valid.\n", b->number);
+             /* We won't stop here */
+             /* FIXME, maybe we should stop here!!! */
+             continue;
+           }
+       }
+      else
+       real_breakpoint = 1;
+
+      if (b->frame && b->frame != frame_address)
+       this_bp_stop = 0;
+      else
+       {
+         int value_zero;
+
+         if (b->cond)
+           {
+             /* Need to select the frame, with all that implies
+                so that the conditions will have the right context.  */
+             select_frame (get_current_frame (), 0);
+             value_zero
+               = catch_errors (breakpoint_cond_eval, (int)(b->cond),
+                               "Error occurred in testing breakpoint condition.");
+             free_all_values ();
+           }
+         if (b->cond && value_zero)
+           {
+             this_bp_stop = 0;
+           }
+         else if (b->ignore_count > 0)
+           {
+             b->ignore_count--;
+             this_bp_stop = 0;
+           }
+         else
+           {
+             /* We will stop here */
+             if (b->enable == temporary)
+               b->enable = disabled;
+             bs->commands = b->commands;
+             if (b->silent)
+               this_bp_print = 0;
+             if (bs->commands && !strcmp ("silent", bs->commands->line))
+               {
+                 bs->commands = bs->commands->next;
+                 this_bp_print = 0;
+               }
+           }
+       }
+      if (this_bp_stop)
+       stop = 1;
+      if (this_bp_print)
+       print = 1;
+    }
+
+  bs->next = NULL;             /* Terminate the chain */
+  bs = root_bs->next;          /* Re-grab the head of the chain */
+  if (bs)
+    {
+      bs->stop = stop;
+      bs->print = print;
+#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
+      if (real_breakpoint)
+       {
+         *pc = bp_addr;
+#if defined (SHIFT_INST_REGS)
+         {
+           CORE_ADDR pc = read_register (PC_REGNUM);
+           CORE_ADDR npc = read_register (NPC_REGNUM);
+           if (pc != npc)
+             {
+               write_register (NNPC_REGNUM, npc);
+               write_register (NPC_REGNUM, pc);
+             }
+         }
+#else /* No SHIFT_INST_REGS.  */
+         write_pc (bp_addr);
+#endif /* No SHIFT_INST_REGS.  */
+       }
+#endif /* DECR_PC_AFTER_BREAK != 0.  */
+    }
+  return bs;
+}
+
+int 
+bpstat_should_step ()
+{
+  struct breakpoint *b;
+  ALL_BREAKPOINTS (b)
+    if (b->enable != disabled && b->exp != NULL)
+      return 1;
+  return 0;
+}
+\f
+/* Print information on breakpoint number BNUM, or -1 if all.
+   If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS
+   is nonzero, process only watchpoints.  */
+
+static void
+breakpoint_1 (bnum, watchpoints)
+     int bnum;
+     int watchpoints;
+{
+  register struct breakpoint *b;
+  register struct command_line *l;
+  register struct symbol *sym;
+  CORE_ADDR last_addr = (CORE_ADDR)-1;
+  int header_printed = 0;
+  
+  ALL_BREAKPOINTS (b)
+    if (bnum == -1 || bnum == b->number)
+      {
+       if (b->address == NULL && !watchpoints)
+         {
+           if (bnum == -1)
+             continue;
+           error ("That is a watchpoint, not a breakpoint.");
+         }
+       if (b->address != NULL && watchpoints)
+         {
+           if (bnum == -1)
+             continue;
+           error ("That is a breakpoint, not a watchpoint.");
+         }
+
+       if (!header_printed)
+         {
+           if (watchpoints)
+             printf_filtered ("    Enb   Expression\n");
+           else if (addressprint)
+             printf_filtered ("    Enb   Address    Where\n");
+           else
+             printf_filtered ("    Enb   Where\n");
+           header_printed = 1;
+         }
+
+       printf_filtered ("#%-3d %c ", b->number, "nyod"[(int) b->enable]);
+       if (b->address == NULL)
+         print_expression (b->exp, stdout);
+       else
+         {
+           if (addressprint)
+             printf_filtered (" 0x%08x ", b->address);
+
+           last_addr = b->address;
+           if (b->symtab)
+             {
+               sym = find_pc_function (b->address);
+               if (sym)
+                 {
+                   fputs_filtered (" in ", stdout);
+                   fputs_demangled (SYMBOL_NAME (sym), stdout, 1);
+                   fputs_filtered (" at ", stdout);
+                 }
+               fputs_filtered (b->symtab->filename, stdout);
+               printf_filtered (":%d", b->line_number);
+             }
+           else
+             print_address_symbolic (b->address, stdout, demangle);
+         }
+
+       printf_filtered ("\n");
+
+       if (b->frame)
+         printf_filtered ("\tstop only in stack frame at 0x%x\n", b->frame);
+       if (b->cond)
+         {
+           printf_filtered ("\tstop only if ");
+           print_expression (b->cond, stdout);
+           printf_filtered ("\n");
+         }
+       if (b->ignore_count)
+         printf_filtered ("\tignore next %d hits\n", b->ignore_count);
+       if ((l = b->commands))
+         while (l)
+           {
+             fputs_filtered ("\t", stdout);
+             fputs_filtered (l->line, stdout);
+             fputs_filtered ("\n", stdout);
+             l = l->next;
+           }
+      }
+
+  if (!header_printed)
+    {
+      char *which = watchpoints ? "watch" : "break";
+      if (bnum == -1)
+       printf_filtered ("No %spoints.\n", which);
+      else
+       printf_filtered ("No %spoint numbered %d.\n", which, bnum);
+    }
+
+  /* Compare against (CORE_ADDR)-1 in case some compiler decides
+     that a comparison of an unsigned with -1 is always false.  */
+  if (last_addr != (CORE_ADDR)-1)
+    set_next_address (last_addr);
+}
+
+static void
+breakpoints_info (bnum_exp, from_tty)
+     char *bnum_exp;
+     int from_tty;
+{
+  int bnum = -1;
+
+  if (bnum_exp)
+    bnum = parse_and_eval_address (bnum_exp);
+
+  breakpoint_1 (bnum, 0);
+}
+
+static void
+watchpoints_info (bnum_exp, from_tty)
+     char *bnum_exp;
+     int from_tty;
+{
+  int bnum = -1;
+
+  if (bnum_exp)
+    bnum = parse_and_eval_address (bnum_exp);
+
+  breakpoint_1 (bnum, 1);
+}
+
+/* Print a message describing any breakpoints set at PC.  */
+
+static void
+describe_other_breakpoints (pc)
+     register CORE_ADDR pc;
+{
+  register int others = 0;
+  register struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    if (b->address == pc)
+      others++;
+  if (others > 0)
+    {
+      printf ("Note: breakpoint%s ", (others > 1) ? "s" : "");
+      ALL_BREAKPOINTS (b)
+       if (b->address == pc)
+         {
+           others--;
+           printf ("%d%s%s ",
+                   b->number,
+                   (b->enable == disabled) ? " (disabled)" : "",
+                   (others > 1) ? "," : ((others == 1) ? " and" : ""));
+         }
+      printf ("also set at pc 0x%x.\n", pc);
+    }
+}
+\f
+/* Set the default place to put a breakpoint
+   for the `break' command with no arguments.  */
+
+void
+set_default_breakpoint (valid, addr, symtab, line)
+     int valid;
+     CORE_ADDR addr;
+     struct symtab *symtab;
+     int line;
+{
+  default_breakpoint_valid = valid;
+  default_breakpoint_address = addr;
+  default_breakpoint_symtab = symtab;
+  default_breakpoint_line = line;
+}
+
+/* Rescan breakpoints at address ADDRESS,
+   marking the first one as "first" and any others as "duplicates".
+   This is so that the bpt instruction is only inserted once.  */
+
+static void
+check_duplicates (address)
+     CORE_ADDR address;
+{
+  register struct breakpoint *b;
+  register int count = 0;
+
+  ALL_BREAKPOINTS (b)
+    if (b->enable != disabled && b->address == address)
+      {
+       count++;
+       b->duplicate = count > 1;
+      }
+}
+
+/* Low level routine to set a breakpoint.
+   Takes as args the three things that every breakpoint must have.
+   Returns the breakpoint object so caller can set other things.
+   Does not set the breakpoint number!
+   Does not print anything.  */
+
+static struct breakpoint *
+set_raw_breakpoint (sal)
+     struct symtab_and_line sal;
+{
+  register struct breakpoint *b, *b1;
+
+  b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
+  bzero (b, sizeof *b);
+  b->address = sal.pc;
+  b->symtab = sal.symtab;
+  b->line_number = sal.line;
+  b->enable = enabled;
+  b->next = 0;
+  b->silent = 0;
+  b->ignore_count = 0;
+  b->commands = NULL;
+  b->frame = NULL;
+
+  /* Add this breakpoint to the end of the chain
+     so that a list of breakpoints will come out in order
+     of increasing numbers.  */
+
+  b1 = breakpoint_chain;
+  if (b1 == 0)
+    breakpoint_chain = b;
+  else
+    {
+      while (b1->next)
+       b1 = b1->next;
+      b1->next = b;
+    }
+
+  check_duplicates (sal.pc);
+
+  return b;
+}
+
+/* Set a breakpoint that will evaporate an end of command
+   at address specified by SAL.
+   Restrict it to frame FRAME if FRAME is nonzero.  */
+
+void
+set_momentary_breakpoint (sal, frame)
+     struct symtab_and_line sal;
+     FRAME frame;
+{
+  register struct breakpoint *b;
+  b = set_raw_breakpoint (sal);
+  b->number = -3;
+  b->enable = delete;
+  b->frame = (frame ? FRAME_FP (frame) : 0);
+}
+
+void
+clear_momentary_breakpoints ()
+{
+  register struct breakpoint *b;
+  ALL_BREAKPOINTS (b)
+    if (b->number == -3)
+      {
+       delete_breakpoint (b);
+       break;
+      }
+}
+\f
+/* Tell the user we have just set a breakpoint B.  */
+static void
+mention (b)
+     struct breakpoint *b;
+{
+  if (b->exp)
+    {
+      printf_filtered ("Watchpoint %d: ", b->number);
+      print_expression (b->exp, stdout);
+    }
+  else
+    {
+      printf_filtered ("Breakpoint %d at 0x%x", b->number, b->address);
+      if (b->symtab)
+       printf_filtered (": file %s, line %d.",
+                        b->symtab->filename, b->line_number);
+    }
+  printf_filtered ("\n");
+}
+
+#if 0
+/* Nobody calls this currently. */
+/* Set a breakpoint from a symtab and line.
+   If TEMPFLAG is nonzero, it is a temporary breakpoint.
+   ADDR_STRING is a malloc'd string holding the name of where we are
+   setting the breakpoint.  This is used later to re-set it after the
+   program is relinked and symbols are reloaded.
+   Print the same confirmation messages that the breakpoint command prints.  */
+
+void
+set_breakpoint (s, line, tempflag, addr_string)
+     struct symtab *s;
+     int line;
+     int tempflag;
+     char *addr_string;
+{
+  register struct breakpoint *b;
+  struct symtab_and_line sal;
+  
+  sal.symtab = s;
+  sal.line = line;
+  sal.pc = find_line_pc (sal.symtab, sal.line);
+  if (sal.pc == 0)
+    error ("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename);
+  else
+    {
+      describe_other_breakpoints (sal.pc);
+
+      b = set_raw_breakpoint (sal);
+      set_breakpoint_count (breakpoint_count + 1);
+      b->number = breakpoint_count;
+      b->cond = 0;
+      b->addr_string = addr_string;
+      if (tempflag)
+       b->enable = temporary;
+
+      mention (b);
+    }
+}
+#endif
+\f
+/* Set a breakpoint according to ARG (function, linenum or *address)
+   and make it temporary if TEMPFLAG is nonzero. */
+
+static void
+break_command_1 (arg, tempflag, from_tty)
+     char *arg;
+     int tempflag, from_tty;
+{
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  register struct expression *cond = 0;
+  register struct breakpoint *b;
+
+  /* Pointers in arg to the start, and one past the end, of the condition.  */
+  char *cond_start = NULL;
+  char *cond_end;
+  /* Pointers in arg to the start, and one past the end,
+     of the address part.  */
+  char *addr_start = NULL;
+  char *addr_end;
+  
+  int i;
+  CORE_ADDR pc;
+
+  sals.sals = NULL;
+  sals.nelts = 0;
+
+  sal.line = sal.pc = sal.end = 0;
+  sal.symtab = 0;
+
+  /* If no arg given, or if first arg is 'if ', use the default breakpoint. */
+
+  if (!arg || (arg[0] == 'i' && arg[1] == 'f' 
+              && (arg[2] == ' ' || arg[2] == '\t')))
+    {
+      if (default_breakpoint_valid)
+       {
+         sals.sals = (struct symtab_and_line *) 
+           xmalloc (sizeof (struct symtab_and_line));
+         sal.pc = default_breakpoint_address;
+         sal.line = default_breakpoint_line;
+         sal.symtab = default_breakpoint_symtab;
+         sals.sals[0] = sal;
+         sals.nelts = 1;
+       }
+      else
+       error ("No default breakpoint address now.");
+    }
+  else
+    {
+      addr_start = arg;
+
+      /* Force almost all breakpoints to be in terms of the
+        current_source_symtab (which is decode_line_1's default).  This
+        should produce the results we want almost all of the time while
+        leaving default_breakpoint_* alone.  */
+      if (default_breakpoint_valid
+         && (!current_source_symtab
+             || (arg && (*arg == '+' || *arg == '-'))))
+       sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
+                             default_breakpoint_line);
+      else
+       sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0);
+
+      addr_end = arg;
+    }
+  
+  if (! sals.nelts) 
+    return;
+
+  for (i = 0; i < sals.nelts; i++)
+    {
+      sal = sals.sals[i];
+      if (sal.pc == 0 && sal.symtab != 0)
+       {
+         pc = find_line_pc (sal.symtab, sal.line);
+         if (pc == 0)
+           error ("No line %d in file \"%s\".",
+                  sal.line, sal.symtab->filename);
+       }
+      else 
+       pc = sal.pc;
+      
+      while (arg && *arg)
+       {
+         if (arg[0] == 'i' && arg[1] == 'f'
+             && (arg[2] == ' ' || arg[2] == '\t'))
+           {
+             arg += 2;
+             cond_start = arg;
+             cond = parse_c_1 (&arg, block_for_pc (pc), 0);
+             cond_end = arg;
+           }
+         else
+           error ("Junk at end of arguments.");
+       }
+      sals.sals[i].pc = pc;
+    }
+
+  for (i = 0; i < sals.nelts; i++)
+    {
+      sal = sals.sals[i];
+
+      if (from_tty)
+       describe_other_breakpoints (sal.pc);
+
+      b = set_raw_breakpoint (sal);
+      set_breakpoint_count (breakpoint_count + 1);
+      b->number = breakpoint_count;
+      b->cond = cond;
+      
+      if (addr_start)
+       b->addr_string = savestring (addr_start, addr_end - addr_start);
+      if (cond_start)
+       b->cond_string = savestring (cond_start, cond_end - cond_start);
+                                    
+      if (tempflag)
+       b->enable = temporary;
+
+      mention (b);
+    }
+
+  if (sals.nelts > 1)
+    {
+      printf ("Multiple breakpoints were set.\n");
+      printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+    }
+  free (sals.sals);
+}
+
+void
+break_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  break_command_1 (arg, 0, from_tty);
+}
+
+static void
+tbreak_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  break_command_1 (arg, 1, from_tty);
+}
+
+static void
+watch_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct breakpoint *b;
+  struct symtab_and_line sal;
+
+  sal.pc = NULL;
+  sal.symtab = NULL;
+  sal.line = 0;
+  
+  b = set_raw_breakpoint (sal);
+  set_breakpoint_count (breakpoint_count + 1);
+  b->number = breakpoint_count;
+  innermost_block = NULL;
+  b->exp = parse_c_expression (arg);
+  b->exp_valid_block = innermost_block;
+  b->val = evaluate_expression (b->exp);
+  release_value (b->val);
+  b->cond = 0;
+  b->cond_string = NULL;
+  mention (b);
+}
+\f
+/*
+ * Helper routine for the until_command routine in infcmd.c.  Here
+ * because it uses the mechanisms of breakpoints.
+ */
+void
+until_break_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  FRAME prev_frame = get_prev_frame (selected_frame);
+
+  clear_proceed_status ();
+
+  /* Set a breakpoint where the user wants it and at return from
+     this function */
+  
+  if (default_breakpoint_valid)
+    sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
+                         default_breakpoint_line);
+  else
+    sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0);
+  
+  if (sals.nelts != 1)
+    error ("Couldn't get information on specified line.");
+  
+  sal = sals.sals[0];
+  free (sals.sals);            /* malloc'd, so freed */
+  
+  if (*arg)
+    error ("Junk at end of arguments.");
+  
+  if (sal.pc == 0 && sal.symtab != 0)
+    sal.pc = find_line_pc (sal.symtab, sal.line);
+  
+  if (sal.pc == 0)
+    error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
+  
+  set_momentary_breakpoint (sal, selected_frame);
+  
+  /* Keep within the current frame */
+  
+  if (prev_frame)
+    {
+      struct frame_info *fi;
+      
+      fi = get_frame_info (prev_frame);
+      sal = find_pc_line (fi->pc, 0);
+      sal.pc = fi->pc;
+      set_momentary_breakpoint (sal, prev_frame);
+    }
+  
+  proceed (-1, -1, 0);
+}
+\f
+/* Set a breakpoint at the catch clause for NAME.  */
+static int
+catch_breakpoint (name)
+     char *name;
+{
+}
+
+static int
+disable_catch_breakpoint ()
+{
+}
+
+static int
+delete_catch_breakpoint ()
+{
+}
+
+static int
+enable_catch_breakpoint ()
+{
+}
+
+struct sal_chain
+{
+  struct sal_chain *next;
+  struct symtab_and_line sal;
+};
+
+/* For each catch clause identified in ARGS, run FUNCTION
+   with that clause as an argument.  */
+static struct symtabs_and_lines
+map_catch_names (args, function)
+     char *args;
+     int (*function)();
+{
+  register char *p = args;
+  register char *p1;
+  struct symtabs_and_lines sals;
+  struct sal_chain *sal_chain = 0;
+
+  if (p == 0)
+    error_no_arg ("one or more catch names");
+
+  sals.nelts = 0;
+  sals.sals = NULL;
+
+  while (*p)
+    {
+      p1 = p;
+      /* Don't swallow conditional part.  */
+      if (p1[0] == 'i' && p1[1] == 'f'
+         && (p1[2] == ' ' || p1[2] == '\t'))
+       break;
+
+      if (isalpha (*p1))
+       {
+         p1++;
+         while (isalnum (*p1) || *p1 == '_' || *p1 == '$')
+           p1++;
+       }
+
+      if (*p1 && *p1 != ' ' && *p1 != '\t')
+       error ("Arguments must be catch names.");
+
+      *p1 = 0;
+#if 0
+      if (function (p))
+       {
+         struct sal_chain *next
+           = (struct sal_chain *)alloca (sizeof (struct sal_chain));
+         next->next = sal_chain;
+         next->sal = get_catch_sal (p);
+         sal_chain = next;
+         goto win;
+       }
+#endif
+      printf ("No catch clause for exception %s.\n", p);
+    win:
+      p = p1;
+      while (*p == ' ' || *p == '\t') p++;
+    }
+}
+
+/* This shares a lot of code with `print_frame_label_vars' from stack.c.  */
+
+static struct symtabs_and_lines
+get_catch_sals (this_level_only)
+     int this_level_only;
+{
+  extern struct blockvector *blockvector_for_pc ();
+  register struct blockvector *bl;
+  register struct block *block = get_frame_block (selected_frame);
+  int index, have_default = 0;
+  struct frame_info *fi = get_frame_info (selected_frame);
+  CORE_ADDR pc = fi->pc;
+  struct symtabs_and_lines sals;
+  struct sal_chain *sal_chain = 0;
+  char *blocks_searched;
+
+  sals.nelts = 0;
+  sals.sals = NULL;
+
+  if (block == 0)
+    error ("No symbol table info available.\n");
+
+  bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
+  blocks_searched = (char *) alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+  bzero (blocks_searched, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+
+  while (block != 0)
+    {
+      CORE_ADDR end = BLOCK_END (block) - 4;
+      int last_index;
+
+      if (bl != blockvector_for_pc (end, &index))
+       error ("blockvector blotch");
+      if (BLOCKVECTOR_BLOCK (bl, index) != block)
+       error ("blockvector botch");
+      last_index = BLOCKVECTOR_NBLOCKS (bl);
+      index += 1;
+
+      /* Don't print out blocks that have gone by.  */
+      while (index < last_index
+            && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < pc)
+       index++;
+
+      while (index < last_index
+            && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < end)
+       {
+         if (blocks_searched[index] == 0)
+           {
+             struct block *b = BLOCKVECTOR_BLOCK (bl, index);
+             int nsyms;
+             register int i;
+             register struct symbol *sym;
+
+             nsyms = BLOCK_NSYMS (b);
+
+             for (i = 0; i < nsyms; i++)
+               {
+                 sym = BLOCK_SYM (b, i);
+                 if (! strcmp (SYMBOL_NAME (sym), "default"))
+                   {
+                     if (have_default)
+                       continue;
+                     have_default = 1;
+                   }
+                 if (SYMBOL_CLASS (sym) == LOC_LABEL)
+                   {
+                     struct sal_chain *next = (struct sal_chain *)
+                       alloca (sizeof (struct sal_chain));
+                     next->next = sal_chain;
+                     next->sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0);
+                     sal_chain = next;
+                   }
+               }
+             blocks_searched[index] = 1;
+           }
+         index++;
+       }
+      if (have_default)
+       break;
+      if (sal_chain && this_level_only)
+       break;
+
+      /* After handling the function's top-level block, stop.
+        Don't continue to its superblock, the block of
+        per-file symbols.  */
+      if (BLOCK_FUNCTION (block))
+       break;
+      block = BLOCK_SUPERBLOCK (block);
+    }
+
+  if (sal_chain)
+    {
+      struct sal_chain *tmp_chain;
+
+      /* Count the number of entries.  */
+      for (index = 0, tmp_chain = sal_chain; tmp_chain;
+          tmp_chain = tmp_chain->next)
+       index++;
+
+      sals.nelts = index;
+      sals.sals = (struct symtab_and_line *)
+       xmalloc (index * sizeof (struct symtab_and_line));
+      for (index = 0; sal_chain; sal_chain = sal_chain->next, index++)
+       sals.sals[index] = sal_chain->sal;
+    }
+
+  return sals;
+}
+
+/* Commands to deal with catching exceptions.  */
+
+void
+catch_command_1 (arg, tempflag, from_tty)
+     char *arg;
+     int tempflag;
+     int from_tty;
+{
+  /* First, translate ARG into something we can deal with in terms
+     of breakpoints.  */
+
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  register struct expression *cond = 0;
+  register struct breakpoint *b;
+  char *save_arg;
+  int i;
+  CORE_ADDR pc;
+
+  sal.line = sal.pc = sal.end = 0;
+  sal.symtab = 0;
+
+  /* If no arg given, or if first arg is 'if ', all active catch clauses
+     are breakpointed. */
+
+  if (!arg || (arg[0] == 'i' && arg[1] == 'f' 
+              && (arg[2] == ' ' || arg[2] == '\t')))
+    {
+      /* Grab all active catch clauses.  */
+      sals = get_catch_sals (0);
+    }
+  else
+    {
+      /* Grab selected catch clauses.  */
+      error ("catch NAME not implemeneted");
+      sals = map_catch_names (arg, catch_breakpoint);
+    }
+
+  if (! sals.nelts) 
+    return;
+
+  save_arg = arg;
+  for (i = 0; i < sals.nelts; i++)
+    {
+      sal = sals.sals[i];
+      if (sal.pc == 0 && sal.symtab != 0)
+       {
+         pc = find_line_pc (sal.symtab, sal.line);
+         if (pc == 0)
+           error ("No line %d in file \"%s\".",
+                  sal.line, sal.symtab->filename);
+       }
+      else 
+       pc = sal.pc;
+      
+      while (arg && *arg)
+       {
+         if (arg[0] == 'i' && arg[1] == 'f'
+             && (arg[2] == ' ' || arg[2] == '\t'))
+           cond = (struct expression *) parse_c_1 ((arg += 2, &arg),
+                                                   block_for_pc (pc), 0);
+         else
+           error ("Junk at end of arguments.");
+       }
+      arg = save_arg;
+      sals.sals[i].pc = pc;
+    }
+
+  for (i = 0; i < sals.nelts; i++)
+    {
+      sal = sals.sals[i];
+
+      if (from_tty)
+       describe_other_breakpoints (sal.pc);
+
+      b = set_raw_breakpoint (sal);
+      b->number = ++breakpoint_count;
+      b->cond = cond;
+      if (tempflag)
+       b->enable = temporary;
+
+      printf ("Breakpoint %d at 0x%x", b->number, b->address);
+      if (b->symtab)
+       printf (": file %s, line %d.", b->symtab->filename, b->line_number);
+      printf ("\n");
+    }
+
+  if (sals.nelts > 1)
+    {
+      printf ("Multiple breakpoints were set.\n");
+      printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+    }
+  free (sals.sals);
+}
+
+/* Disable breakpoints on all catch clauses described in ARGS.  */
+static void
+disable_catch (args)
+     char *args;
+{
+  /* Map the disable command to catch clauses described in ARGS.  */
+}
+
+/* Enable breakpoints on all catch clauses described in ARGS.  */
+static void
+enable_catch (args)
+     char *args;
+{
+  /* Map the disable command to catch clauses described in ARGS.  */
+}
+
+/* Delete breakpoints on all catch clauses in the active scope.  */
+static void
+delete_catch (args)
+     char *args;
+{
+  /* Map the delete command to catch clauses described in ARGS.  */
+}
+
+static void
+catch_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  catch_command_1 (arg, 0, from_tty);
+}
+\f
+static void
+clear_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register struct breakpoint *b, *b1;
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  register struct breakpoint *found;
+  int i;
+
+  if (arg)
+    {
+      sals = decode_line_spec (arg, 1);
+    }
+  else
+    {
+      sals.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+      sal.line = default_breakpoint_line;
+      sal.symtab = default_breakpoint_symtab;
+      sal.pc = 0;
+      if (sal.symtab == 0)
+       error ("No source file specified.");
+
+      sals.sals[0] = sal;
+      sals.nelts = 1;
+    }
+
+  for (i = 0; i < sals.nelts; i++)
+    {
+      /* If exact pc given, clear bpts at that pc.
+        But if sal.pc is zero, clear all bpts on specified line.  */
+      sal = sals.sals[i];
+      found = (struct breakpoint *) 0;
+      while (breakpoint_chain
+            && (sal.pc ? breakpoint_chain->address == sal.pc
+                : (breakpoint_chain->symtab == sal.symtab
+                   && breakpoint_chain->line_number == sal.line)))
+       {
+         b1 = breakpoint_chain;
+         breakpoint_chain = b1->next;
+         b1->next = found;
+         found = b1;
+       }
+
+      ALL_BREAKPOINTS (b)
+       while (b->next
+              && b->next->address != NULL
+              && (sal.pc ? b->next->address == sal.pc
+                  : (b->next->symtab == sal.symtab
+                     && b->next->line_number == sal.line)))
+         {
+           b1 = b->next;
+           b->next = b1->next;
+           b1->next = found;
+           found = b1;
+         }
+
+      if (found == 0)
+       {
+         if (arg)
+           error ("No breakpoint at %s.", arg);
+         else
+           error ("No breakpoint at this line.");
+       }
+
+      if (found->next) from_tty = 1; /* Always report if deleted more than one */
+      if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : "");
+      while (found)
+       {
+         if (from_tty) printf ("%d ", found->number);
+         b1 = found->next;
+         delete_breakpoint (found);
+         found = b1;
+       }
+      if (from_tty) putchar ('\n');
+    }
+  free (sals.sals);
+}
+\f
+/* Delete breakpoint in BS if they are `delete' breakpoints.
+   This is called after any breakpoint is hit, or after errors.  */
+
+void
+breakpoint_auto_delete (bs)
+     bpstat bs;
+{
+  for (; bs; bs = bs->next)
+    if (bs->breakpoint_at && bs->breakpoint_at->enable == delete)
+      delete_breakpoint (bs->breakpoint_at);
+}
+
+/* Delete a breakpoint and clean up all traces of it in the data structures. */
+
+static void
+delete_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  register struct breakpoint *b;
+  register bpstat bs;
+
+  if (bpt->inserted)
+      target_remove_breakpoint(bpt->address, bpt->shadow_contents);
+
+  if (breakpoint_chain == bpt)
+    breakpoint_chain = bpt->next;
+
+  ALL_BREAKPOINTS (b)
+    if (b->next == bpt)
+      {
+       b->next = bpt->next;
+       break;
+      }
+
+  check_duplicates (bpt->address);
+
+  free_command_lines (&bpt->commands);
+  if (bpt->cond)
+    free (bpt->cond);
+  if (bpt->cond_string != NULL)
+    free (bpt->cond_string);
+  if (bpt->addr_string != NULL)
+    free (bpt->addr_string);
+
+  if (xgdb_verbose && bpt->number >=0)
+    printf ("breakpoint #%d deleted\n", bpt->number);
+
+  /* Be sure no bpstat's are pointing at it after it's been freed.  */
+  /* FIXME, how can we find all bpstat's?  We just check stop_bpstat for now. */
+  for (bs = stop_bpstat; bs; bs = bs->next)
+    if (bs->breakpoint_at == bpt)
+      bs->breakpoint_at = NULL;
+  free (bpt);
+}
+
+static void map_breakpoint_numbers ();
+
+static void
+delete_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+
+  if (arg == 0)
+    {
+      /* Ask user only if there are some breakpoints to delete.  */
+      if (!from_tty
+         || (breakpoint_chain && query ("Delete all breakpoints? ", 0, 0)))
+       {
+         /* No arg; clear all breakpoints.  */
+         while (breakpoint_chain)
+           delete_breakpoint (breakpoint_chain);
+       }
+    }
+  else
+    map_breakpoint_numbers (arg, delete_breakpoint);
+}
+
+static void
+breakpoint_re_set_one (bint)
+     int bint;
+{
+  struct breakpoint *b = (struct breakpoint *)bint;  /* get past catch_errs */
+  int i;
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  char *s;
+
+  if (b->address != NULL && b->addr_string != NULL)
+    {
+      s = b->addr_string;
+      sals = decode_line_1 (&s, 1, (struct symtab *)NULL, 0);
+      for (i = 0; i < sals.nelts; i++)
+       {
+         sal = sals.sals[i];
+         
+         b->symtab = sal.symtab;
+         b->line_number = sal.line;
+         if (sal.pc == 0 && sal.symtab != 0)
+           {
+             sal.pc = find_line_pc (sal.symtab, sal.line);
+             if (sal.pc == 0)
+               error ("No line %d in file \"%s\".",
+                      sal.line, sal.symtab->filename);
+           }
+         b->address = sal.pc;
+
+         if (b->cond_string != NULL)
+           {
+             s = b->cond_string;
+             b->cond = parse_c_1 (&s, block_for_pc (sal.pc), 0);
+           }
+         
+         check_duplicates (b->address);
+
+         mention (b);
+       }
+      free (sals.sals);
+    }
+  else
+    {
+      /* Anything without a string can't be re-set. */
+      delete_breakpoint (b);
+    }
+}
+
+/* Re-set all breakpoints after symbols have been re-loaded.  */
+void
+breakpoint_re_set ()
+{
+  struct breakpoint *b;
+  
+  ALL_BREAKPOINTS (b)
+    {
+      b->symtab = 0;           /* Be sure we don't point to old dead symtab */
+      (void) catch_errors (breakpoint_re_set_one, (int) b, 
+                          "Error in re-setting breakpoint");
+    }
+
+  /* Blank line to finish off all those mention() messages we just printed.  */
+  printf_filtered ("\n");
+}
+\f
+/* Set ignore-count of breakpoint number BPTNUM to COUNT.
+   If from_tty is nonzero, it prints a message to that effect,
+   which ends with a period (no newline).  */
+
+void
+set_ignore_count (bptnum, count, from_tty)
+     int bptnum, count, from_tty;
+{
+  register struct breakpoint *b;
+
+  if (count < 0)
+    count = 0;
+
+  ALL_BREAKPOINTS (b)
+    if (b->number == bptnum)
+      {
+       b->ignore_count = count;
+       if (!from_tty)
+         return;
+       else if (count == 0)
+         printf ("Will stop next time breakpoint %d is reached.", bptnum);
+       else if (count == 1)
+         printf ("Will ignore next crossing of breakpoint %d.", bptnum);
+       else
+         printf ("Will ignore next %d crossings of breakpoint %d.",
+                 count, bptnum);
+       return;
+      }
+
+  error ("No breakpoint number %d.", bptnum);
+}
+
+/* Clear the ignore counts of all breakpoints.  */
+void
+breakpoint_clear_ignore_counts ()
+{
+  struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    b->ignore_count = 0;
+}
+
+/* Command to set ignore-count of breakpoint N to COUNT.  */
+
+static void
+ignore_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *p = args;
+  register int num;
+
+  if (p == 0)
+    error_no_arg ("a breakpoint number");
+  
+  num = get_number (&p);
+
+  if (*p == 0)
+    error ("Second argument (specified ignore-count) is missing.");
+
+  set_ignore_count (num, parse_and_eval_address (p), from_tty);
+  printf ("\n");
+}
+\f
+/* Call FUNCTION on each of the breakpoints
+   whose numbers are given in ARGS.  */
+
+static void
+map_breakpoint_numbers (args, function)
+     char *args;
+     void (*function) ();
+{
+  register char *p = args;
+  char *p1;
+  register int num;
+  register struct breakpoint *b;
+
+  if (p == 0)
+    error_no_arg ("one or more breakpoint numbers");
+
+  while (*p)
+    {
+      p1 = p;
+      
+      num = get_number (&p1);
+
+      ALL_BREAKPOINTS (b)
+       if (b->number == num)
+         {
+           function (b);
+           goto win;
+         }
+      printf ("No breakpoint number %d.\n", num);
+    win:
+      p = p1;
+    }
+}
+
+static void
+enable_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = enabled;
+
+  if (xgdb_verbose && bpt->number >= 0)
+    printf ("breakpoint #%d enabled\n", bpt->number);
+
+  check_duplicates (bpt->address);
+  if (bpt->val != NULL)
+    {
+      value_free (bpt->val);
+
+      bpt->val = evaluate_expression (bpt->exp);
+      release_value (bpt->val);
+    }
+}
+
+static void
+enable_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  struct breakpoint *bpt;
+  if (args == 0)
+    ALL_BREAKPOINTS (bpt)
+      enable_breakpoint (bpt);
+  else
+    map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+static void
+disable_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = disabled;
+
+  if (xgdb_verbose && bpt->number >= 0)
+    printf ("breakpoint #%d disabled\n", bpt->number);
+
+  check_duplicates (bpt->address);
+}
+
+static void
+disable_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  register struct breakpoint *bpt;
+  if (args == 0)
+    ALL_BREAKPOINTS (bpt)
+      disable_breakpoint (bpt);
+  else
+    map_breakpoint_numbers (args, disable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = temporary;
+
+  check_duplicates (bpt->address);
+}
+
+static void
+enable_once_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  map_breakpoint_numbers (args, enable_once_breakpoint);
+}
+
+static void
+enable_delete_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  bpt->enable = delete;
+
+  check_duplicates (bpt->address);
+}
+
+static void
+enable_delete_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  map_breakpoint_numbers (args, enable_delete_breakpoint);
+}
+\f
+/*
+ * Use default_breakpoint_'s, or nothing if they aren't valid.
+ */
+struct symtabs_and_lines
+decode_line_spec_1 (string, funfirstline)
+     char *string;
+     int funfirstline;
+{
+  struct symtabs_and_lines sals;
+  if (string == 0)
+    error ("Empty line specification.");
+  if (default_breakpoint_valid)
+    sals = decode_line_1 (&string, funfirstline,
+                         default_breakpoint_symtab, default_breakpoint_line);
+  else
+    sals = decode_line_1 (&string, funfirstline, (struct symtab *)NULL, 0);
+  if (*string)
+    error ("Junk at end of line specification: %s", string);
+  return sals;
+}
+\f
+
+/* Chain containing all defined enable commands.  */
+
+extern struct cmd_list_element 
+  *enablelist, *disablelist,
+  *deletelist, *enablebreaklist;
+
+extern struct cmd_list_element *cmdlist;
+
+void
+_initialize_breakpoint ()
+{
+  breakpoint_chain = 0;
+  /* Don't bother to call set_breakpoint_count.  $bpnum isn't useful
+     before a breakpoint is set.  */
+  breakpoint_count = 0;
+
+  add_com ("ignore", class_breakpoint, ignore_command,
+          "Set ignore-count of breakpoint number N to COUNT.");
+
+  add_com ("commands", class_breakpoint, commands_command,
+          "Set commands to be executed when a breakpoint is hit.\n\
+Give breakpoint number as argument after \"commands\".\n\
+With no argument, the targeted breakpoint is the last one set.\n\
+The commands themselves follow starting on the next line.\n\
+Type a line containing \"end\" to indicate the end of them.\n\
+Give \"silent\" as the first line to make the breakpoint silent;\n\
+then no output is printed when it is hit, except what the commands print.");
+
+  add_com ("condition", class_breakpoint, condition_command,
+          "Specify breakpoint number N to break only if COND is true.\n\
+N is an integer; COND is a C expression to be evaluated whenever\n\
+breakpoint N is reached.  Actually break only when COND is nonzero.");
+
+  add_com ("tbreak", class_breakpoint, tbreak_command,
+          "Set a temporary breakpoint.  Args like \"break\" command.\n\
+Like \"break\" except the breakpoint is only enabled temporarily,\n\
+so it will be disabled when hit.  Equivalent to \"break\" followed\n\
+by using \"enable once\" on the breakpoint number.");
+
+  add_prefix_cmd ("enable", class_breakpoint, enable_command,
+                 "Enable some breakpoints.\n\
+Give breakpoint numbers (separated by spaces) as arguments.\n\
+With no subcommand, breakpoints are enabled until you command otherwise.\n\
+This is used to cancel the effect of the \"disable\" command.\n\
+With a subcommand you can enable temporarily.",
+                 &enablelist, "enable ", 1, &cmdlist);
+
+  add_abbrev_prefix_cmd ("breakpoints", class_breakpoint, enable_command,
+                 "Enable some breakpoints.\n\
+Give breakpoint numbers (separated by spaces) as arguments.\n\
+This is used to cancel the effect of the \"disable\" command.\n\
+May be abbreviated to simply \"enable\".\n",
+                 &enablebreaklist, "enable breakpoints ", 1, &enablelist);
+
+  add_cmd ("once", no_class, enable_once_command,
+          "Enable breakpoints for one hit.  Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\
+See the \"tbreak\" command which sets a breakpoint and enables it once.",
+          &enablebreaklist);
+
+  add_cmd ("delete", no_class, enable_delete_command,
+          "Enable breakpoints and delete when hit.  Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it is deleted.",
+          &enablebreaklist);
+
+  add_cmd ("delete", no_class, enable_delete_command,
+          "Enable breakpoints and delete when hit.  Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it is deleted.",
+          &enablelist);
+
+  add_cmd ("once", no_class, enable_once_command,
+          "Enable breakpoints for one hit.  Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\
+See the \"tbreak\" command which sets a breakpoint and enables it once.",
+          &enablelist);
+
+  add_prefix_cmd ("disable", class_breakpoint, disable_command,
+          "Disable some breakpoints.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To disable all breakpoints, give no argument.\n\
+A disabled breakpoint is not forgotten, but has no effect until reenabled.",
+                 &disablelist, "disable ", 1, &cmdlist);
+  add_com_alias ("dis", "disable", class_breakpoint, 1);
+  add_com_alias ("disa", "disable", class_breakpoint, 1);
+
+  add_cmd ("breakpoints", class_alias, disable_command,
+          "Disable some breakpoints.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To disable all breakpoints, give no argument.\n\
+A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\
+This command may be abbreviated \"disable\".",
+          &disablelist);
+
+  add_prefix_cmd ("delete", class_breakpoint, delete_command,
+          "Delete some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.\n\
+\n\
+Also a prefix command for deletion of other GDB objects.\n\
+The \"unset\" command is also an alias for \"delete\".",
+                 &deletelist, "delete ", 1, &cmdlist);
+  add_com_alias ("d", "delete", class_breakpoint, 1);
+  add_com_alias ("unset", "delete", class_alias, 1);
+
+  add_cmd ("breakpoints", class_alias, delete_command,
+          "Delete some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.\n\
+This command may be abbreviated \"delete\".",
+          &deletelist);
+
+  add_com ("clear", class_breakpoint, clear_command,
+          "Clear breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, all breakpoints in that line are cleared.\n\
+If function is specified, breakpoints at beginning of function are cleared.\n\
+If an address is specified, breakpoints at that address are cleared.\n\n\
+With no argument, clears all breakpoints in the line that the selected frame\n\
+is executing in.\n\
+\n\
+See also the \"delete\" command which clears breakpoints by number.");
+
+  add_com ("break", class_breakpoint, break_command,
+          "Set breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, break at start of code for that line.\n\
+If function is specified, break at start of code for that function.\n\
+If an address is specified, break at that exact address.\n\
+With no arg, uses current execution address of selected stack frame.\n\
+This is useful for breaking on return to a stack frame.\n\
+\n\
+Multiple breakpoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.");
+  add_com_alias ("b", "break", class_run, 1);
+  add_com_alias ("br", "break", class_run, 1);
+  add_com_alias ("bre", "break", class_run, 1);
+  add_com_alias ("brea", "break", class_run, 1);
+
+  add_info ("breakpoints", breakpoints_info,
+           "Status of all breakpoints, or breakpoint number NUMBER.\n\
+Second column is \"y\" for enabled breakpoint, \"n\" for disabled,\n\
+\"o\" for enabled once (disable when hit), \"d\" for enable but delete when hit.\n\
+Then come the address and the file/line number.\n\n\
+Convenience variable \"$_\" and default examine address for \"x\"\n\
+are set to the address of the last breakpoint listed.\n\n\
+Convenience variable \"$bpnum\" contains the number of the last\n\
+breakpoint set.");
+
+  add_com ("catch", class_breakpoint, catch_command,
+         "Set breakpoints to catch exceptions that are raised.\n\
+Argument may be a single exception to catch, multiple exceptions\n\
+to catch, or the default exception \"default\".  If no arguments\n\
+are given, breakpoints are set at all exception handlers catch clauses\n\
+within the current scope.\n\
+\n\
+A condition specified for the catch applies to all breakpoints set\n\
+with this command\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.");
+
+  add_com ("watch", class_breakpoint, watch_command,
+          "Set a watchpoint for an expression.\n\
+A watchpoint stops execution of your program whenever the value of\n\
+an expression changes.");
+
+  add_info ("watchpoints", watchpoints_info,
+           "Status of all watchpoints, or watchpoint number NUMBER.\n\
+Second column is \"y\" for enabled watchpoints, \"n\" for disabled.");
+}
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
new file mode 100644 (file)
index 0000000..00ee8c5
--- /dev/null
@@ -0,0 +1,129 @@
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (BREAKPOINT_H)
+#define BREAKPOINT_H 1
+
+/* This is the maximum number of bytes a breakpoint instruction can take.
+   Feel free to increase it.  It's just used in a few places to size
+   arrays that should be independent of the target architecture.  */
+
+#define        BREAKPOINT_MAX  10
+
+extern void breakpoint_re_set ();
+extern void clear_momentary_breakpoints ();
+extern void set_momentary_breakpoint ();
+extern void set_ignore_count ();
+extern void set_default_breakpoint ();
+
+extern void mark_breakpoints_out ();
+extern void breakpoint_auto_delete ();
+extern void breakpoint_clear_ignore_counts ();
+
+/* The following are for displays, which aren't really breakpoints, but
+   here is as good a place as any for them.  */
+
+extern void disable_current_display ();
+extern void do_displays ();
+extern void disable_display ();
+extern void clear_displays ();
+
+\f
+/* The follow stuff is an abstract data type "bpstat" ("breakpoint status").
+   This provides the ability to determine whether we have stopped at a
+   breakpoint, and what we should do about it.  */
+
+typedef struct bpstat__struct *bpstat;
+
+/* Interface:  */
+
+/* Clear a bpstat so that it says we are not at any breakpoint.
+   Also free any storage that is part of a bpstat.  */
+void bpstat_clear();
+
+/* Return a copy of a bpstat.  Like "bs1 = bs2" but all storage that
+   is part of the bpstat is copied as well.  */
+bpstat bpstat_copy();
+
+/* Get a bpstat associated with having just stopped at address *PC
+   and frame address FRAME_ADDRESS.  Update *PC to point at the
+   breakpoint (if we hit a breakpoint).  */
+bpstat bpstat_stop_status (/* CORE_ADDR *pc; FRAME_ADDR frame_address */);
+
+/* Nonzero if we should print the frame.  */
+#define bpstat_should_print(bs) ((bs) != NULL && (bs)->print)
+
+/* Nonzero if we should stop.  */
+#define bpstat_stop(bs) ((bs) != NULL && (bs)->stop)
+
+/* Nonzero if we hit a momentary breakpoint.  */
+#define bpstat_momentary_breakpoint(bs) ((bs) != NULL && (bs)->momentary)
+
+/* Nonzero if a signal that we got in wait() was due to circumstances
+   explained by the BS.  */
+/* Currently that is true iff we have hit a breakpoint.  */
+#define bpstat_explains_signal(bs) ((bs) != NULL)
+
+/* Nonzero if we should step constantly (e.g. watchpoints on machines
+   without hardware support).  This isn't related to a specific bpstat,
+   just to things like whether watchpoints are set.  */
+int bpstat_should_step (/* void */);
+
+/* Print a message indicating what happened.  Returns nonzero to
+   say that only the source line should be printed after this (zero
+   return means print the frame as well as the source line).  */
+int bpstat_print (/* bpstat bs */);
+
+/* Return the breakpoint number of the first breakpoint we are stopped
+   at.  *BSP upon return is a bpstat which points to the remaining
+   breakpoints stopped at (but which is not guaranteed to be good for
+   anything but further calls to bpstat_num).
+   Return 0 if passed a bpstat which does not indicate any breakpoints.  */
+int bpstat_num (/* bpstat *bsp; */);
+
+/* Perform actions associated with having stopped at *BSP.  */
+void bpstat_do_actions (/* bpstat bs; */);
+
+/* Modify BS so that the actions will not be performed.  */
+void bpstat_clear_actions (/* bpstat bs; */);
+
+
+/* Implementation:  */
+#include "value.h"
+struct bpstat__struct
+{
+  /* Linked list because there can be two breakpoints at the
+     same place, and a bpstat reflects the fact that both have been hit.  */
+  bpstat next;
+  /* Breakpoint that we are at.  */
+  struct breakpoint *breakpoint_at;
+  /* Commands left to be done.  */
+  struct command_line *commands;
+  /* Old value associated with a watchpoint.  */
+  value old_val;
+  /* Nonzero if we should print the frame.  Only significant for the first
+     bpstat in the chain.  */
+  char print;
+  /* Nonzero if we should stop.  Only significant for the first bpstat in
+     the chain.  */
+  char stop;
+  /* Nonzero if we hit a momentary breakpoint.  Only significant for the
+     first bpstat in the chain.  */
+  char momentary;
+};
+#endif /* breakpoint.h not already included.  */
diff --git a/gdb/coffread.c b/gdb/coffread.c
new file mode 100644 (file)
index 0000000..0e6b2c7
--- /dev/null
@@ -0,0 +1,1969 @@
+/* Read coff symbol tables and convert to internal format, for GDB.
+   Design and support routines derived from dbxread.c, and UMAX COFF
+   specific routines written 9/1/87 by David D. Johnson, Brown University.
+   Revised 11/27/87 ddj@cs.brown.edu
+   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "bfd.h"
+#include "libcoff.h"           /* FIXME secret internal data from BFD */
+#include "symfile.h"
+
+#include <intel-coff.h>
+#include <obstack.h>
+#include <string.h>
+
+static void add_symbol_to_list ();
+static void read_coff_symtab ();
+static void patch_opaque_types ();
+static struct type *decode_function_type ();
+static struct type *decode_type ();
+static struct type *decode_base_type ();
+static struct type *read_enum_type ();
+static struct type *read_struct_type ();
+static void finish_block ();
+static struct blockvector *make_blockvector ();
+static struct symbol *process_coff_symbol ();
+static int init_stringtab ();
+static void free_stringtab ();
+static char *getfilename ();
+static char *getsymname ();
+static int init_lineno ();
+static void enter_linenos ();
+static void read_one_sym ();
+
+extern int fclose ();
+extern void free_all_symtabs ();
+extern void free_all_psymtabs ();
+
+/* external routines from the BFD library -- undocumented interface used
+   by GDB to read symbols.  Move to libcoff.h.  FIXME-SOMEDAY!  */
+extern void bfd_coff_swap_sym (/* symfile_bfd, &sym */);
+extern void bfd_coff_swap_aux (/* symfile_bfd, &aux, type, sclass */);
+extern void bfd_coff_swap_lineno (/* symfile_bfd, &lineno */);
+
+
+/* Name of source file whose symbol data we are now processing.
+   This comes from a symbol named ".file".  */
+
+static char *last_source_file;
+
+/* Core address of start and end of text of current source file.
+   This comes from a ".text" symbol where x_nlinno > 0.  */
+
+static CORE_ADDR cur_src_start_addr;
+static CORE_ADDR cur_src_end_addr;
+
+/* Core address of the end of the first object file.  */
+static CORE_ADDR first_object_file_end;
+
+/* End of the text segment of the executable file,
+   as found in the symbol _etext.  */
+
+static CORE_ADDR end_of_text_addr;
+
+/* The addresses of the symbol table stream and number of symbols
+   of the object file we are reading (as copied into core).  */
+
+static FILE *nlist_stream_global;
+static int nlist_nsyms_global;
+
+/* The entry point (starting address) of the file, if it is an executable.  */
+
+static CORE_ADDR entry_point;
+
+/* The index in the symbol table of the last coff symbol that was processed.  */
+
+static int symnum;
+
+/* Vector of types defined so far, indexed by their coff symnum.  */
+
+static struct typevector *type_vector;
+
+/* Number of elements allocated for type_vector currently.  */
+
+static int type_vector_length;
+
+/* Vector of line number information.  */
+
+static struct linetable *line_vector;
+
+/* Index of next entry to go in line_vector_index.  */
+
+static int line_vector_index;
+
+/* Last line number recorded in the line vector.  */
+
+static int prev_line_number;
+
+/* Number of elements allocated for line_vector currently.  */
+
+static int line_vector_length;
+
+#ifdef TDESC
+#define SEM
+int int_sem_val = 's' << 24 | 'e' << 16 | 'm' << 8 | '.';
+int temp_sem_val;
+int last_coffsem = 2;
+int last_coffsyn = 0;
+int debug_info = 0;    /*used by tdesc */
+extern int tdesc_handle;
+extern int safe_to_init_tdesc_context;
+#endif
+
+/* Chain of typedefs of pointers to empty struct/union types.
+   They are chained thru the SYMBOL_VALUE_CHAIN.  */
+
+#define HASHSIZE 127
+static struct symbol *opaque_type_chain[HASHSIZE];
+
+/* Record the symbols defined for each context in a list.
+   We don't create a struct block for the context until we
+   know how long to make it.  */
+
+struct pending
+{
+  struct pending *next;
+  struct symbol *symbol;
+};
+
+/* Here are the three lists that symbols are put on.  */
+
+struct pending *file_symbols;  /* static at top level, and types */
+
+struct pending *global_symbols;        /* global functions and variables */
+
+struct pending *local_symbols; /* everything local to lexical context */
+
+/* List of unclosed lexical contexts
+   (that will become blocks, eventually).  */
+
+struct context_stack
+{
+  struct context_stack *next;
+  struct pending *locals;
+  struct pending_block *old_blocks;
+  struct symbol *name;
+  CORE_ADDR start_addr;
+  int depth;
+};
+
+struct context_stack *context_stack;
+
+/* Nonzero if within a function (so symbols should be local,
+   if nothing says specifically).  */
+
+int within_function;
+
+/* List of blocks already made (lexical contexts already closed).
+   This is used at the end to make the blockvector.  */
+
+struct pending_block
+{
+  struct pending_block *next;
+  struct block *block;
+};
+
+struct pending_block *pending_blocks;
+
+extern CORE_ADDR startup_file_start;   /* From blockframe.c */
+extern CORE_ADDR startup_file_end;     /* From blockframe.c */
+
+/* Complaints about various problems in the file being read  */
+
+struct complaint ef_complaint = 
+  {"Unmatched .ef symbol(s) ignored starting at symnum %d", 0, 0};
+
+\f
+/* Look up a coff type-number index.  Return the address of the slot
+   where the type for that index is stored.
+   The type-number is in INDEX. 
+
+   This can be used for finding the type associated with that index
+   or for associating a new type with the index.  */
+
+static struct type **
+coff_lookup_type (index)
+     register int index;
+{
+  if (index >= type_vector_length)
+    {
+      int old_vector_length = type_vector_length;
+
+      type_vector_length *= 2;
+      if (type_vector_length < index) {
+       type_vector_length = index * 2;
+      }
+      type_vector = (struct typevector *)
+       xrealloc (type_vector, sizeof (struct typevector)
+                               + type_vector_length * sizeof (struct type *));
+      bzero (&type_vector->type[ old_vector_length ],
+            (type_vector_length - old_vector_length) * sizeof(struct type *));
+    }
+  return &type_vector->type[index];
+}
+
+/* Make sure there is a type allocated for type number index
+   and return the type object.
+   This can create an empty (zeroed) type object.  */
+
+static struct type *
+coff_alloc_type (index)
+     int index;
+{
+  register struct type **type_addr = coff_lookup_type (index);
+  register struct type *type = *type_addr;
+
+  /* If we are referring to a type not known at all yet,
+     allocate an empty type for it.
+     We will fill it in later if we find out how.  */
+  if (type == 0)
+    {
+      type = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+      bzero (type, sizeof (struct type));
+      *type_addr = type;
+    }
+  return type;
+}
+\f
+/* maintain the lists of symbols and blocks */
+
+/* Add a symbol to one of the lists of symbols.  */
+static void
+add_symbol_to_list (symbol, listhead)
+     struct symbol *symbol;
+     struct pending **listhead;
+{
+  register struct pending *link
+    = (struct pending *) xmalloc (sizeof (struct pending));
+
+  link->next = *listhead;
+  link->symbol = symbol;
+  *listhead = link;
+}
+
+/* Take one of the lists of symbols and make a block from it.
+   Put the block on the list of pending blocks.  */
+
+static void
+finish_block (symbol, listhead, old_blocks, start, end)
+     struct symbol *symbol;
+     struct pending **listhead;
+     struct pending_block *old_blocks;
+     CORE_ADDR start, end;
+{
+  register struct pending *next, *next1;
+  register struct block *block;
+  register struct pending_block *pblock;
+  struct pending_block *opblock;
+  register int i;
+
+  /* Count the length of the list of symbols.  */
+
+  for (next = *listhead, i = 0; next; next = next->next, i++);
+
+  block = (struct block *)
+           obstack_alloc (symbol_obstack, sizeof (struct block) + (i - 1) * sizeof (struct symbol *));
+
+  /* Copy the symbols into the block.  */
+
+  BLOCK_NSYMS (block) = i;
+  for (next = *listhead; next; next = next->next)
+    BLOCK_SYM (block, --i) = next->symbol;
+
+  BLOCK_START (block) = start;
+  BLOCK_END (block) = end;
+  BLOCK_SUPERBLOCK (block) = 0;        /* Filled in when containing block is made */
+
+  /* Put the block in as the value of the symbol that names it.  */
+
+  if (symbol)
+    {
+      SYMBOL_BLOCK_VALUE (symbol) = block;
+      BLOCK_FUNCTION (block) = symbol;
+    }
+  else
+    BLOCK_FUNCTION (block) = 0;
+
+  /* Now free the links of the list, and empty the list.  */
+
+  for (next = *listhead; next; next = next1)
+    {
+      next1 = next->next;
+      free (next);
+    }
+  *listhead = 0;
+
+  /* Install this block as the superblock
+     of all blocks made since the start of this scope
+     that don't have superblocks yet.  */
+
+  opblock = 0;
+  for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next)
+    {
+      if (BLOCK_SUPERBLOCK (pblock->block) == 0)
+       BLOCK_SUPERBLOCK (pblock->block) = block;
+      opblock = pblock;
+    }
+
+  /* Record this block on the list of all blocks in the file.
+     Put it after opblock, or at the beginning if opblock is 0.
+     This puts the block in the list after all its subblocks.  */
+
+  pblock = (struct pending_block *) xmalloc (sizeof (struct pending_block));
+  pblock->block = block;
+  if (opblock)
+    {
+      pblock->next = opblock->next;
+      opblock->next = pblock;
+    }
+  else
+    {
+      pblock->next = pending_blocks;
+      pending_blocks = pblock;
+    }
+}
+
+static struct blockvector *
+make_blockvector ()
+{
+  register struct pending_block *next, *next1;
+  register struct blockvector *blockvector;
+  register int i;
+
+  /* Count the length of the list of blocks.  */
+
+  for (next = pending_blocks, i = 0; next; next = next->next, i++);
+
+  blockvector = (struct blockvector *)
+                 obstack_alloc (symbol_obstack, sizeof (struct blockvector) + (i - 1) * sizeof (struct block *));
+
+  /* Copy the blocks into the blockvector.
+     This is done in reverse order, which happens to put
+     the blocks into the proper order (ascending starting address).
+     finish_block has hair to insert each block into the list
+     after its subblocks in order to make sure this is true.  */
+
+  BLOCKVECTOR_NBLOCKS (blockvector) = i;
+  for (next = pending_blocks; next; next = next->next)
+    BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
+
+  /* Now free the links of the list, and empty the list.  */
+
+  for (next = pending_blocks; next; next = next1)
+    {
+      next1 = next->next;
+      free (next);
+    }
+  pending_blocks = 0;
+
+  return blockvector;
+}
+
+/* Manage the vector of line numbers.  */
+
+static
+record_line (line, pc)
+     int line;
+     CORE_ADDR pc;
+{
+  struct linetable_entry *e;
+  /* Make sure line vector is big enough.  */
+
+  if (line_vector_index + 2 >= line_vector_length)
+    {
+      line_vector_length *= 2;
+      line_vector = (struct linetable *)
+       xrealloc (line_vector, sizeof (struct linetable)
+                 + (line_vector_length
+                    * sizeof (struct linetable_entry)));
+    }
+
+  e = line_vector->item + line_vector_index++;
+  e->line = line; e->pc = pc;
+}
+\f
+/* Start a new symtab for a new source file.
+   This is called when a COFF ".file" symbol is seen;
+   it indicates the start of data for one original source file.  */
+
+static void
+start_symtab ()
+{
+  file_symbols = 0;
+  global_symbols = 0;
+  context_stack = 0;
+  within_function = 0;
+  last_source_file = 0;
+#ifdef TDESC
+  last_coffsem = 2;
+  last_coffsyn = 0;
+#endif
+
+  /* Initialize the source file information for this file.  */
+
+  line_vector_index = 0;
+  line_vector_length = 1000;
+  prev_line_number = -2;       /* Force first line number to be explicit */
+  line_vector = (struct linetable *)
+    xmalloc (sizeof (struct linetable)
+            + line_vector_length * sizeof (struct linetable_entry));
+}
+
+/* Save the vital information from when starting to read a file,
+   for use when closing off the current file.
+   NAME is the file name the symbols came from, START_ADDR is the first
+   text address for the file, and SIZE is the number of bytes of text.  */
+
+static void
+complete_symtab (name, start_addr, size)
+    char *name;
+    CORE_ADDR start_addr;
+    unsigned int size;
+{
+  last_source_file = savestring (name, strlen (name));
+  cur_src_start_addr = start_addr;
+  cur_src_end_addr = start_addr + size;
+
+  if (entry_point < cur_src_end_addr
+      && entry_point >= cur_src_start_addr)
+    {
+      startup_file_start = cur_src_start_addr;
+      startup_file_end = cur_src_end_addr;
+    }
+}
+
+/* Finish the symbol definitions for one main source file,
+   close off all the lexical contexts for that file
+   (creating struct block's for them), then make the
+   struct symtab for that file and put it in the list of all such. */
+
+static void
+end_symtab ()
+{
+  register struct symtab *symtab;
+  register struct context_stack *cstk;
+  register struct blockvector *blockvector;
+  register struct linetable *lv;
+
+  /* Finish the lexical context of the last function in the file.  */
+
+  if (context_stack)
+    {
+      cstk = context_stack;
+      context_stack = 0;
+      /* Make a block for the local symbols within.  */
+      finish_block (cstk->name, &local_symbols, cstk->old_blocks,
+                   cstk->start_addr, cur_src_end_addr);
+      free (cstk);
+    }
+
+  /* Ignore a file that has no functions with real debugging info.  */
+  if (pending_blocks == 0 && file_symbols == 0 && global_symbols == 0)
+    {
+      free (line_vector);
+      line_vector = 0;
+      line_vector_length = -1;
+      last_source_file = 0;
+      return;
+    }
+
+  /* Create the two top-level blocks for this file.  */
+  finish_block (0, &file_symbols, 0, cur_src_start_addr, cur_src_end_addr);
+  finish_block (0, &global_symbols, 0, cur_src_start_addr, cur_src_end_addr);
+
+  /* Create the blockvector that points to all the file's blocks.  */
+  blockvector = make_blockvector ();
+
+  /* Now create the symtab object for this source file.  */
+  symtab = (struct symtab *) xmalloc (sizeof (struct symtab));
+  symtab->free_ptr = 0;
+
+  /* Fill in its components.  */
+  symtab->blockvector = blockvector;
+  symtab->free_code = free_linetable;
+  symtab->filename = last_source_file;
+  lv = line_vector;
+  lv->nitems = line_vector_index;
+  symtab->linetable = (struct linetable *)
+    xrealloc (lv, (sizeof (struct linetable)
+                  + lv->nitems * sizeof (struct linetable_entry)));
+  symtab->nlines = 0;
+  symtab->line_charpos = 0;
+
+#ifdef TDESC
+  symtab->coffsem = last_coffsem;
+  symtab->coffsyn = last_coffsyn;
+#endif
+
+  /* Link the new symtab into the list of such.  */
+  symtab->next = symtab_list;
+  symtab_list = symtab;
+
+  /* Reinitialize for beginning of new file. */
+  line_vector = 0;
+  line_vector_length = -1;
+  last_source_file = 0;
+}
+\f
+static void
+record_misc_function (name, address)
+     char *name;
+     CORE_ADDR address;
+{
+#ifdef TDESC
+  /* We don't want TDESC entry points on the misc_function_vector */
+  if (name[0] == '@') return;
+#endif
+  /* mf_text isn't true, but apparently COFF doesn't tell us what it really
+     is, so this guess is more useful than mf_unknown.  */
+  prim_record_misc_function (savestring (name, strlen (name)),
+                            address,
+                            (int)mf_text);
+}
+\f
+/* coff_symfile_init ()
+   is the coff-specific initialization routine for reading symbols.
+   It is passed a struct sym_fns which contains, among other things,
+   the BFD for the file whose symbols are being read, and a slot for
+   a pointer to "private data" which we fill with cookies and other
+   treats for coff_symfile_read ().
+
+   We will only be called if this is a COFF or COFF-like file.
+   BFD handles figuring out the format of the file, and code in symtab.c
+   uses BFD's determination to vector to us.
+
+   The ultimate result is a new symtab (or, FIXME, eventually a psymtab).  */
+
+struct coff_symfile_info {
+  file_ptr min_lineno_offset;          /* Where in file lowest line#s are */
+  file_ptr max_lineno_offset;          /* 1+last byte of line#s in file */
+};
+
+void
+coff_symfile_init (sf)
+     struct sym_fns *sf;
+{
+  bfd *abfd = sf->sym_bfd;
+
+  /* Allocate struct to keep track of the symfile */
+  /* FIXME memory leak */
+  sf->sym_private = xmalloc (sizeof (struct coff_symfile_info));
+
+#if defined (TDESC)
+  safe_to_init_tdesc_context  = 0;
+#endif
+
+  /* Save startup file's range of PC addresses to help blockframe.c
+     decide where the bottom of the stack is.  */
+  if (bfd_get_file_flags (abfd) & EXEC_P)
+    {
+      /* Executable file -- record its entry point so we'll recognize
+        the startup file because it contains the entry point.  */
+      entry_point = bfd_get_start_address (abfd);
+    }
+  else
+    {
+      /* Examination of non-executable.o files.  Short-circuit this stuff.  */
+      /* ~0 will not be in any file, we hope.  */
+      entry_point = ~0;
+      /* set the startup file to be an empty range.  */
+      startup_file_start = 0;
+      startup_file_end = 0;
+    }
+}
+
+/* This function is called for every section; it finds the outer limits
+   of the line table (minimum and maximum file offset) so that the
+   mainline code can read the whole thing for efficiency.  */
+
+static void
+find_linenos (abfd, asect, vpinfo)
+     bfd *abfd;
+     sec_ptr asect;
+     void *vpinfo;
+{
+  struct coff_symfile_info *info;
+  int size, count;
+  file_ptr offset, maxoff;
+
+/* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
+  count = asect->lineno_count;
+/* End of warning */
+
+  if (count == 0)
+    return;
+  size = count * sizeof (struct lineno);
+
+  info = (struct coff_symfile_info *)vpinfo;
+/* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
+  offset = asect->line_filepos;
+/* End of warning */
+
+  if (offset < info->min_lineno_offset || info->min_lineno_offset == 0)
+    info->min_lineno_offset = offset;
+
+  maxoff = offset + size;
+  if (maxoff > info->max_lineno_offset)
+    info->max_lineno_offset = maxoff;
+}
+
+
+/* Read a symbol file, after initialization by coff_symfile_init.  */
+/* FIXME!  Addr and Mainline are not used yet -- this will not work for
+   shared libraries or add_file!  */
+
+void
+coff_symfile_read (sf, addr, mainline)
+     struct sym_fns *sf;
+     CORE_ADDR addr;
+     int mainline;
+{
+  struct coff_symfile_info *info = (struct coff_symfile_info *)sf->sym_private;
+  bfd *abfd = sf->sym_bfd;
+  char *name = bfd_get_filename (abfd);
+  int desc;
+  register int val;
+  int num_symbols;
+  int symtab_offset;
+  int stringtab_offset;
+
+  symfile_bfd = abfd;                  /* Kludge for swap routines */
+
+/* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
+   desc = fileno ((FILE *)(abfd->iostream));           /* File descriptor */
+   num_symbols = bfd_get_symcount (abfd);      /* How many syms */
+   symtab_offset = obj_sym_filepos (abfd);     /* Symbol table file offset */
+   stringtab_offset = symtab_offset + num_symbols * SYMESZ;  /* String tab */
+/* End of warning */
+
+#ifdef TDESC
+  debug_info = text_hdr.s_relptr;
+  if (tdesc_handle)
+    {
+       dc_terminate (tdesc_handle);
+       tdesc_handle = 0;
+    }
+#endif
+
+  /* Read the line number table, all at once.  */
+  info->min_lineno_offset = 0;
+  info->max_lineno_offset = 0;
+  bfd_map_over_sections (abfd, find_linenos, info);
+
+  val = init_lineno (desc, info->min_lineno_offset, 
+                    info->max_lineno_offset - info->min_lineno_offset);
+  if (val < 0)
+    error ("\"%s\": error reading line numbers\n", name);
+
+  /* Now read the string table, all at once.  */
+
+  val = init_stringtab (desc, stringtab_offset);
+  if (val < 0)
+    {
+      free_all_symtabs ();             /* FIXME blows whole symtab */
+      printf ("\"%s\": can't get string table", name);
+      fflush (stdout);
+      return;
+    }
+  make_cleanup (free_stringtab, 0);
+
+  /* Position to read the symbol table.  Do not read it all at once. */
+  val = lseek (desc, (long)symtab_offset, 0);
+  if (val < 0)
+    perror_with_name (name);
+
+  init_misc_bunches ();
+  make_cleanup (discard_misc_bunches, 0);
+
+  /* Now that the executable file is positioned at symbol table,
+     process it and define symbols accordingly.  */
+
+  read_coff_symtab (desc, num_symbols);
+
+  patch_opaque_types ();
+
+  /* Sort symbols alphabetically within each block.  */
+
+  sort_all_symtab_syms ();
+
+  /* Go over the misc symbol bunches and install them in vector.  */
+
+  condense_misc_bunches (0);
+
+  /* Make a default for file to list.  */
+
+  select_source_symtab (0);    /* FIXME, this might be too slow, see dbxread */
+}
+
+void
+coff_symfile_discard ()
+{
+  /* There seems to be nothing to do here.  */
+}
+
+void
+coff_new_init ()
+{
+  /* There seems to be nothing to do except free_all_symtabs and set
+     symfile to zero, which is done by our caller.  */
+}
+\f
+/* Simplified internal version of coff symbol table information */
+
+struct coff_symbol {
+  char *c_name;
+  int c_symnum;                /* symbol number of this entry */
+  int c_nsyms;         /* 1 if syment only, 2 if syment + auxent, etc */
+  long c_value;
+  int c_sclass;
+  int c_secnum;
+  unsigned int c_type;
+};
+
+/* Given pointers to a symbol table in coff style exec file,
+   analyze them and create struct symtab's describing the symbols.
+   NSYMS is the number of symbols in the symbol table.
+   We read them one at a time using read_one_sym ().  */
+
+static void
+read_coff_symtab (desc, nsyms)
+     int desc;
+     int nsyms;
+{
+  int newfd;                   /* Avoid multiple closes on same desc */
+  FILE *stream; 
+  register struct context_stack *new;
+  struct coff_symbol coff_symbol;
+  register struct coff_symbol *cs = &coff_symbol;
+  static SYMENT main_sym;
+  static AUXENT main_aux;
+  struct coff_symbol fcn_cs_saved;
+  static SYMENT fcn_sym_saved;
+  static AUXENT fcn_aux_saved;
+
+  /* A .file is open.  */
+  int in_source_file = 0;
+  int num_object_files = 0;
+  int next_file_symnum = -1;
+
+  /* Name of the current file.  */
+  char *filestring = "";
+  int depth;
+  int fcn_first_line;
+  int fcn_last_line;
+  int fcn_start_addr;
+  long fcn_line_ptr;
+  struct cleanup *old_chain;
+
+
+  newfd = dup (desc);
+  if (newfd == -1)
+    fatal ("Too many open files");
+  stream = fdopen (newfd, "r");
+
+  old_chain = make_cleanup (free_all_symtabs, 0);
+  make_cleanup (fclose, stream);
+  nlist_stream_global = stream;
+  nlist_nsyms_global = nsyms;
+  last_source_file = 0;
+  bzero (opaque_type_chain, sizeof opaque_type_chain);
+
+  type_vector_length = 160;
+  type_vector = (struct typevector *)
+               xmalloc (sizeof (struct typevector)
+                               + type_vector_length * sizeof (struct type *));
+  bzero (type_vector->type, type_vector_length * sizeof (struct type *));
+
+  start_symtab ();
+
+  symnum = 0;
+  while (symnum < nsyms)
+    {
+      QUIT;                    /* Make this command interruptable.  */
+      read_one_sym (cs, &main_sym, &main_aux);
+
+#ifdef SEM
+      temp_sem_val = cs->c_name[0] << 24 | cs->c_name[1] << 16 |
+                     cs->c_name[2] << 8 | cs->c_name[3];
+      if (int_sem_val == temp_sem_val)
+        last_coffsem = (int) strtol (cs->c_name+4, (char **) NULL, 10);
+#endif
+
+      if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE)
+       {
+         if (last_source_file)
+           end_symtab ();
+
+         start_symtab ();
+         complete_symtab ("_globals_", 0, first_object_file_end);
+         /* done with all files, everything from here on out is globals */
+       }
+
+      /* Special case for file with type declarations only, no text.  */
+      if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG)
+       complete_symtab (filestring, 0, 0);
+
+      /* Typedefs should not be treated as symbol definitions.  */
+      if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF)
+       {
+         /* record as misc function.  if we get '.bf' next,
+          * then we undo this step
+          */
+         record_misc_function (cs->c_name, cs->c_value);
+
+         fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+         fcn_start_addr = cs->c_value;
+         fcn_cs_saved = *cs;
+         fcn_sym_saved = main_sym;
+         fcn_aux_saved = main_aux;
+         continue;
+       }
+
+      switch (cs->c_sclass)
+       {
+         case C_EFCN:
+         case C_EXTDEF:
+         case C_ULABEL:
+         case C_USTATIC:
+         case C_LINE:
+         case C_ALIAS:
+         case C_HIDDEN:
+           printf ("Bad n_sclass = %d\n", cs->c_sclass);
+           break;
+
+         case C_FILE:
+           /*
+            * c_value field contains symnum of next .file entry in table
+            * or symnum of first global after last .file.
+            */
+           next_file_symnum = cs->c_value;
+           filestring = getfilename (&main_aux);
+           /*
+            * Complete symbol table for last object file
+            * containing debugging information.
+            */
+           if (last_source_file)
+             {
+               end_symtab ();
+               start_symtab ();
+             }
+           in_source_file = 1;
+           break;
+
+          case C_STAT:
+           if (cs->c_name[0] == '.') {
+                   if (strcmp (cs->c_name, _TEXT) == 0) {
+                           if (++num_object_files == 1) {
+                                   /* last address of startup file */
+                                   first_object_file_end = cs->c_value +
+                                           main_aux.x_scn.x_scnlen;
+                           }
+                           /* Check for in_source_file deals with case of
+                              a file with debugging symbols
+                              followed by a later file with no symbols.  */
+                           if (in_source_file)
+                             complete_symtab (filestring, cs->c_value,
+                                              main_aux.x_scn.x_scnlen);
+                           in_source_file = 0;
+                   }
+                   /* flush rest of '.' symbols */
+                   break;
+           }
+           else if (cs->c_type == T_NULL
+                    && cs->c_name[0] == 'L'
+                    && (strncmp (cs->c_name, "LI%", 3) == 0
+                        || strncmp (cs->c_name,"LC%",3) == 0
+                        || strncmp (cs->c_name,"LP%",3) == 0
+                        || strncmp (cs->c_name,"LPB%",4) == 0
+                        || strncmp (cs->c_name,"LBB%",4) == 0
+                        || strncmp (cs->c_name,"LBE%",4) == 0
+                        || strncmp (cs->c_name,"LPBX%",5) == 0))
+             /* At least on a 3b1, gcc generates swbeg and string labels
+                that look like this.  Ignore them.  */
+             break;
+           /* fall in for static symbols that don't start with '.' */
+         case C_EXT:
+           if (cs->c_sclass == C_EXT &&
+               cs->c_secnum == N_ABS &&
+               strcmp (cs->c_name, _ETEXT) == 0)
+                   end_of_text_addr = cs->c_value;
+           if (cs->c_type == T_NULL) {
+                   if (cs->c_secnum <= 1) {    /* text or abs */
+                           record_misc_function (cs->c_name, cs->c_value);
+                           break;
+                   } else {
+                           cs->c_type = T_INT;
+                   }
+           }
+           (void) process_coff_symbol (cs, &main_aux);
+           break;
+
+         case C_FCN:
+           if (strcmp (cs->c_name, ".bf") == 0)
+             {
+               within_function = 1;
+
+               /* value contains address of first non-init type code */
+               /* main_aux.x_sym.x_misc.x_lnsz.x_lnno
+                           contains line number of '{' } */
+               fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno;
+
+               new = (struct context_stack *)
+                 xmalloc (sizeof (struct context_stack));
+               new->depth = depth = 0;
+               new->next = 0;
+               context_stack = new;
+               new->locals = 0;
+               new->old_blocks = pending_blocks;
+               new->start_addr = fcn_start_addr;
+               fcn_cs_saved.c_name = getsymname (&fcn_sym_saved);
+               new->name = process_coff_symbol (&fcn_cs_saved,
+                                                &fcn_aux_saved);
+             }
+           else if (strcmp (cs->c_name, ".ef") == 0)
+             {
+                     /* the value of .ef is the address of epilogue code;
+                      * not useful for gdb
+                      */
+               /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno
+                           contains number of lines to '}' */
+               new = context_stack;
+               if (new == 0)
+                 {
+                   complain (&ef_complaint, cs->c_symnum);
+                   within_function = 0;
+                   break;
+                 }
+               fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno;
+               enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line);
+
+               finish_block (new->name, &local_symbols, new->old_blocks,
+                             new->start_addr,
+#if defined (FUNCTION_EPILOGUE_SIZE)
+                             /* This macro should be defined only on
+                                machines where the
+                                fcn_aux_saved.x_sym.x_misc.x_fsize
+                                field is always zero.
+                                So use the .bf record information that
+                                points to the epilogue and add the size
+                                of the epilogue.  */
+                             cs->c_value + FUNCTION_EPILOGUE_SIZE
+#else
+                             fcn_cs_saved.c_value +
+                                 fcn_aux_saved.x_sym.x_misc.x_fsize
+#endif
+                             );
+               context_stack = 0;
+               within_function = 0;
+               free (new);
+             }
+           break;
+
+         case C_BLOCK:
+           if (strcmp (cs->c_name, ".bb") == 0)
+             {
+               new = (struct context_stack *)
+                           xmalloc (sizeof (struct context_stack));
+               depth++;
+               new->depth = depth;
+               new->next = context_stack;
+               context_stack = new;
+               new->locals = local_symbols;
+               new->old_blocks = pending_blocks;
+               new->start_addr = cs->c_value;
+               new->name = 0;
+               local_symbols = 0;
+             }
+           else if (strcmp (cs->c_name, ".eb") == 0)
+             {
+               new = context_stack;
+               if (new == 0 || depth != new->depth)
+                 error ("Invalid symbol data: .bb/.eb symbol mismatch at symbol %d.",
+                        symnum);
+               if (local_symbols && context_stack->next)
+                 {
+                   /* Make a block for the local symbols within.  */
+                   finish_block (0, &local_symbols, new->old_blocks,
+                                 new->start_addr, cs->c_value);
+                 }
+               depth--;
+               local_symbols = new->locals;
+               context_stack = new->next;
+               free (new);
+             }
+           break;
+#ifdef TDESC
+          case C_VERSION:
+            if (strcmp (cs->c_name, ".coffsyn") == 0)
+               last_coffsyn = cs->c_value;
+           else if ((strcmp (cs->c_name, ".coffsem") == 0) &&
+                     (cs->c_value != 0))
+               last_coffsem = cs->c_value;
+            break;
+#endif
+
+         default:
+#ifdef TDESC
+           if ((strcmp (cs->c_name, ".coffsem") == 0) &&
+               (cs->c_value != 0))
+             last_coffsem = cs->c_value;
+            else
+#endif
+           (void) process_coff_symbol (cs, &main_aux);
+           break;
+       }
+    }
+
+  if (last_source_file)
+    end_symtab ();
+  fclose (stream);
+  discard_cleanups (old_chain);
+}
+\f
+/* Routines for reading headers and symbols from executable.  */
+
+#ifdef FIXME
+/* Move these XXXMAGIC symbol defns into BFD!  */
+
+/* Read COFF file header, check magic number,
+   and return number of symbols. */
+read_file_hdr (chan, file_hdr)
+    int chan;
+    FILHDR *file_hdr;
+{
+  lseek (chan, 0L, 0);
+  if (myread (chan, (char *)file_hdr, FILHSZ) < 0)
+    return -1;
+
+  switch (file_hdr->f_magic)
+    {
+#ifdef MC68MAGIC
+    case MC68MAGIC:
+#endif
+#ifdef NS32GMAGIC
+      case NS32GMAGIC:
+      case NS32SMAGIC:
+#endif
+#ifdef I386MAGIC
+    case I386MAGIC:
+#endif
+#ifdef CLIPPERMAGIC
+    case CLIPPERMAGIC:
+#endif
+#if defined (MC68KWRMAGIC) \
+  && (!defined (MC68MAGIC) || MC68KWRMAGIC != MC68MAGIC)
+    case MC68KWRMAGIC:
+#endif
+#ifdef MC68KROMAGIC
+    case MC68KROMAGIC:
+    case MC68KPGMAGIC:
+#endif
+#ifdef MC88DGMAGIC
+    case MC88DGMAGIC:
+#endif      
+#ifdef MC88MAGIC
+    case MC88MAGIC:
+#endif      
+#ifdef I960ROMAGIC
+    case I960ROMAGIC:          /* Intel 960 */
+#endif
+#ifdef I960RWMAGIC
+    case I960RWMAGIC:          /* Intel 960 */
+#endif
+       return file_hdr->f_nsyms;
+
+      default:
+#ifdef BADMAG
+       if (BADMAG(file_hdr))
+         return -1;
+       else
+         return file_hdr->f_nsyms;
+#else
+       return -1;
+#endif
+    }
+}
+#endif
+
+
+static void
+read_one_sym (cs, sym, aux)
+    register struct coff_symbol *cs;
+    register SYMENT *sym;
+    register AUXENT *aux;
+{
+  AUXENT temp_aux;
+  int i;
+
+  cs->c_symnum = symnum;
+  fread ((char *)sym, SYMESZ, 1, nlist_stream_global);
+  bfd_coff_swap_sym (symfile_bfd, sym);
+  cs->c_nsyms = (sym->n_numaux & 0xff) + 1;
+  if (cs->c_nsyms >= 2)
+    {
+    fread ((char *)aux, AUXESZ, 1, nlist_stream_global);
+    bfd_coff_swap_aux (symfile_bfd, aux, sym->n_type, sym->n_sclass);
+    /* If more than one aux entry, read past it (only the first aux
+       is important). */
+    for (i = 2; i < cs->c_nsyms; i++)
+      fread ((char *)&temp_aux, AUXESZ, 1, nlist_stream_global);
+    }
+  cs->c_name = getsymname (sym);
+  cs->c_value = sym->n_value;
+  cs->c_sclass = (sym->n_sclass & 0xff);
+  cs->c_secnum = sym->n_scnum;
+  cs->c_type = (unsigned) sym->n_type;
+
+  symnum += cs->c_nsyms;
+}
+\f
+/* Support for string table handling */
+
+static char *stringtab = NULL;
+
+static int
+init_stringtab (chan, offset)
+    int chan;
+    long offset;
+{
+  long length;
+  int val;
+  unsigned char lengthbuf[4];
+
+  if (stringtab)
+    {
+      free (stringtab);
+      stringtab = NULL;
+    }
+
+  if (lseek (chan, offset, 0) < 0)
+    return -1;
+
+  val = myread (chan, (char *)lengthbuf, sizeof lengthbuf);
+  length = bfd_h_getlong (symfile_bfd, lengthbuf);
+
+  /* If no string table is needed, then the file may end immediately
+     after the symbols.  Just return with `stringtab' set to null. */
+  if (val != sizeof length || length < sizeof length)
+    return 0;
+
+  stringtab = (char *) xmalloc (length);
+  if (stringtab == NULL)
+    return -1;
+
+  bcopy (&length, stringtab, sizeof length);
+  if (length == sizeof length)         /* Empty table -- just the count */
+    return 0;
+
+  val = myread (chan, stringtab + sizeof length, length - sizeof length);
+  if (val != length - sizeof length || stringtab[length - 1] != '\0')
+    return -1;
+
+  return 0;
+}
+
+static void
+free_stringtab ()
+{
+  if (stringtab)
+    free (stringtab);
+  stringtab = NULL;
+}
+
+static char *
+getsymname (symbol_entry)
+    SYMENT *symbol_entry;
+{
+  static char buffer[SYMNMLEN+1];
+  char *result;
+
+  if (symbol_entry->n_zeroes == 0)
+    {
+      result = stringtab + symbol_entry->n_offset;
+    }
+  else
+    {
+      strncpy (buffer, symbol_entry->n_name, SYMNMLEN);
+      buffer[SYMNMLEN] = '\0';
+      result = buffer;
+    }
+  return result;
+}
+
+static char *
+getfilename (aux_entry)
+    AUXENT *aux_entry;
+{
+  static char buffer[BUFSIZ];
+  register char *temp;
+  char *result;
+  extern char *rindex ();
+
+#ifndef COFF_NO_LONG_FILE_NAMES
+  if (aux_entry->x_file.x_n.x_zeroes == 0)
+    strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset);
+  else
+#endif /* COFF_NO_LONG_FILE_NAMES */
+    {
+#if defined (x_name)
+      /* Data General.  */
+      strncpy (buffer, aux_entry->x_name, FILNMLEN);
+#else
+      strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN);
+#endif
+      buffer[FILNMLEN] = '\0';
+    }
+  result = buffer;
+  if ((temp = rindex (result, '/')) != NULL)
+    result = temp + 1;
+  return (result);
+}
+\f
+/* Support for line number handling */
+static char *linetab = NULL;
+static long linetab_offset;
+static unsigned long linetab_size;
+
+/* Read in all the line numbers for fast lookups later.  */
+static int
+init_lineno (chan, offset, size)
+    int chan;
+    long offset;
+    int size;
+{
+  int val;
+  register char *p, *q;
+
+  if (lseek (chan, offset, 0) < 0)
+    return -1;
+  
+  linetab = (char *) xmalloc (size);
+
+  val = myread (chan, linetab, size);
+  if (val != size)
+    return -1;
+
+  /* Swap all entries */
+  q = linetab + size;
+  for (p = linetab; p < q; p += LINESZ)
+    bfd_coff_swap_lineno (symfile_bfd, (LINENO *)p);
+
+  linetab_offset = offset;
+  linetab_size = size;
+  make_cleanup (free, linetab);                /* Be sure it gets de-allocated. */
+  return 0;
+}
+
+#if !defined (L_LNNO32)
+#define L_LNNO32(lp) ((lp)->l_lnno)
+#endif
+
+static void
+enter_linenos (file_offset, first_line, last_line)
+    long file_offset;
+    register int first_line;
+    register int last_line;
+{
+  register char *rawptr;
+  struct lineno lptr;
+
+  if (file_offset < linetab_offset)
+    {
+      fprintf (stderr, "\nInvalid symbol file: file_offset < linetab_offset.");
+      return;
+    }
+  
+  rawptr = &linetab[file_offset - linetab_offset];
+
+  /* skip first line entry for each function */
+  rawptr += LINESZ;
+  /* line numbers start at one for the first line of the function */
+  first_line--;
+
+  /* Bcopy since occaisionally rawptr isn't pointing at long
+     boundaries.  FIXME we need to byteswap here!!!  */  
+  for (bcopy (rawptr, &lptr, LINESZ);
+       L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line;
+       rawptr += LINESZ, bcopy (rawptr, &lptr, LINESZ))
+    {
+      record_line (first_line + L_LNNO32 (&lptr), lptr.l_addr.l_paddr);
+    }
+}
+\f
+static int
+hashname (name)
+     char *name;
+{
+  register char *p = name;
+  register int total = p[0];
+  register int c;
+
+  c = p[1];
+  total += c << 2;
+  if (c)
+    {
+      c = p[2];
+      total += c << 4;
+      if (c)
+       total += p[3] << 6;
+    }
+  
+  return total % HASHSIZE;
+}
+
+static void
+patch_type (type, real_type)
+    struct type *type;
+    struct type *real_type;
+{
+  register struct type *target = TYPE_TARGET_TYPE (type);
+  register struct type *real_target = TYPE_TARGET_TYPE (real_type);
+  int field_size = TYPE_NFIELDS (real_target) * sizeof (struct field);
+
+  TYPE_LENGTH (target) = TYPE_LENGTH (real_target);
+  TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target);
+  TYPE_FIELDS (target) = (struct field *)
+                               obstack_alloc (symbol_obstack, field_size);
+
+  bcopy (TYPE_FIELDS (real_target), TYPE_FIELDS (target), field_size);
+
+  if (TYPE_NAME (real_target))
+    {
+      if (TYPE_NAME (target))
+       free (TYPE_NAME (target));
+      TYPE_NAME (target) = concat (TYPE_NAME (real_target), "", "");
+    }
+}
+
+/* Patch up all appropriate typdef symbols in the opaque_type_chains
+   so that they can be used to print out opaque data structures properly */
+
+static void
+patch_opaque_types ()
+{
+  struct symtab *s;
+
+  /* Look at each symbol in the per-file block of each symtab.  */
+  for (s = symtab_list; s; s = s->next)
+    {
+      register struct block *b;
+      register int i;
+
+      /* Go through the per-file symbols only */
+      b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1);
+      for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
+       {
+         register struct symbol *real_sym;
+
+         /* Find completed typedefs to use to fix opaque ones.
+            Remove syms from the chain when their types are stored,
+            but search the whole chain, as there may be several syms
+            from different files with the same name.  */
+         real_sym = BLOCK_SYM (b, i);
+         if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF &&
+             SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE &&
+             TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR &&
+             TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0)
+           {
+             register char *name = SYMBOL_NAME (real_sym);
+             register int hash = hashname (name);
+             register struct symbol *sym, *prev;
+
+             prev = 0;
+             for (sym = opaque_type_chain[hash]; sym;)
+               {
+                 if (name[0] == SYMBOL_NAME (sym)[0] &&
+                     !strcmp (name + 1, SYMBOL_NAME (sym) + 1))
+                   {
+                     if (prev)
+                       SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym);
+                     else
+                       opaque_type_chain[hash] = SYMBOL_VALUE_CHAIN (sym);
+
+                     patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym));
+
+                     if (prev)
+                       sym = SYMBOL_VALUE_CHAIN (prev);
+                     else
+                       sym = opaque_type_chain[hash];
+                   }
+                 else
+                   {
+                     prev = sym;
+                     sym = SYMBOL_VALUE_CHAIN (sym);
+                   }
+               }
+           }
+       }
+    }
+}
+\f
+#if defined (clipper)
+#define BELIEVE_PCC_PROMOTION 1
+#endif
+
+static struct symbol *
+process_coff_symbol (cs, aux)
+     register struct coff_symbol *cs;
+     register AUXENT *aux;
+{
+  register struct symbol *sym
+    = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+  char *name;
+#ifdef NAMES_HAVE_UNDERSCORE
+  int offset = 1;
+#else
+  int offset = 0;
+#endif
+
+  bzero (sym, sizeof (struct symbol));
+  name = cs->c_name;
+  name = (name[0] == '_' ? name + offset : name);
+  SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, name, strlen (name));
+
+  /* default assumptions */
+  SYMBOL_VALUE (sym) = cs->c_value;
+  SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+  if (ISFCN (cs->c_type))
+    {
+      SYMBOL_TYPE (sym) = 
+       lookup_function_type (decode_function_type (cs, cs->c_type, aux));
+      SYMBOL_CLASS (sym) = LOC_BLOCK;
+      if (cs->c_sclass == C_STAT)
+       add_symbol_to_list (sym, &file_symbols);
+      else if (cs->c_sclass == C_EXT)
+       add_symbol_to_list (sym, &global_symbols);
+    }
+  else
+    {
+      SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux);
+      switch (cs->c_sclass)
+       {
+         case C_NULL:
+           break;
+
+         case C_AUTO:
+           SYMBOL_CLASS (sym) = LOC_LOCAL;
+           add_symbol_to_list (sym, &local_symbols);
+           break;
+
+         case C_EXT:
+           SYMBOL_CLASS (sym) = LOC_STATIC;
+           SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
+           add_symbol_to_list (sym, &global_symbols);
+           break;
+
+         case C_STAT:
+           SYMBOL_CLASS (sym) = LOC_STATIC;
+           SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
+           if (within_function) {
+             /* Static symbol of local scope */
+             add_symbol_to_list (sym, &local_symbols);
+           }
+           else {
+             /* Static symbol at top level of file */
+             add_symbol_to_list (sym, &file_symbols);
+           }
+           break;
+
+         case C_REG:
+           SYMBOL_CLASS (sym) = LOC_REGISTER;
+           add_symbol_to_list (sym, &local_symbols);
+           break;
+
+         case C_LABEL:
+           break;
+
+         case C_ARG:
+           SYMBOL_CLASS (sym) = LOC_ARG;
+           add_symbol_to_list (sym, &local_symbols);
+#if !defined (BELIEVE_PCC_PROMOTION)
+           /* If PCC says a parameter is a short or a char,
+              it is really an int.  */
+           if (SYMBOL_TYPE (sym) == builtin_type_char
+               || SYMBOL_TYPE (sym) == builtin_type_short)
+             SYMBOL_TYPE (sym) = builtin_type_int;
+           else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
+                    || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
+             SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
+#endif
+           break;
+
+         case C_REGPARM:
+           SYMBOL_CLASS (sym) = LOC_REGPARM;
+           add_symbol_to_list (sym, &local_symbols);
+#if !defined (BELIEVE_PCC_PROMOTION)
+           /* If PCC says a parameter is a short or a char,
+              it is really an int.  */
+           if (SYMBOL_TYPE (sym) == builtin_type_char
+               || SYMBOL_TYPE (sym) == builtin_type_short)
+             SYMBOL_TYPE (sym) = builtin_type_int;
+           else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
+                    || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
+             SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
+#endif
+           break;
+           
+         case C_TPDEF:
+           SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+           SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+           /* If type has no name, give it one */
+           if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 
+               && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
+             TYPE_NAME (SYMBOL_TYPE (sym))
+                                         = concat (SYMBOL_NAME (sym), "", "");
+
+           /* Keep track of any type which points to empty structured type,
+               so it can be filled from a definition from another file */
+           if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR &&
+               TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0)
+             {
+               register int i = hashname (SYMBOL_NAME (sym));
+
+               SYMBOL_VALUE_CHAIN (sym) = opaque_type_chain[i];
+               opaque_type_chain[i] = sym;
+             }
+           add_symbol_to_list (sym, &file_symbols);
+           break;
+
+         case C_STRTAG:
+         case C_UNTAG:
+         case C_ENTAG:
+           SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+           SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+           if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
+               && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
+             TYPE_NAME (SYMBOL_TYPE (sym))
+               = concat ("",
+                         (cs->c_sclass == C_ENTAG
+                          ? "enum "
+                          : (cs->c_sclass == C_STRTAG
+                             ? "struct " : "union ")),
+                         SYMBOL_NAME (sym));
+           add_symbol_to_list (sym, &file_symbols);
+           break;
+
+         default:
+           break;
+       }
+    }
+  return sym;
+}
+\f
+/* Decode a coff type specifier;
+   return the type that is meant.  */
+
+static
+struct type *
+decode_type (cs, c_type, aux)
+     register struct coff_symbol *cs;
+     unsigned int c_type;
+     register AUXENT *aux;
+{
+  register struct type *type = 0;
+  unsigned int new_c_type;
+
+  if (c_type & ~N_BTMASK)
+    {
+      new_c_type = DECREF (c_type);
+      if (ISPTR (c_type))
+       {
+         type = decode_type (cs, new_c_type, aux);
+         type = lookup_pointer_type (type);
+       }
+      else if (ISFCN (c_type))
+       {
+         type = decode_type (cs, new_c_type, aux);
+         type = lookup_function_type (type);
+       }
+      else if (ISARY (c_type))
+       {
+         int i, n;
+         register unsigned short *dim;
+         struct type *base_type;
+
+         /* Define an array type.  */
+         /* auxent refers to array, not base type */
+         if (aux->x_sym.x_tagndx == 0)
+           cs->c_nsyms = 1;
+
+         /* shift the indices down */
+         dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0];
+         i = 1;
+         n = dim[0];
+         for (i = 0; *dim && i < DIMNUM - 1; i++, dim++)
+           *dim = *(dim + 1);
+         *dim = 0;
+
+         type = (struct type *)
+                   obstack_alloc (symbol_obstack, sizeof (struct type));
+         bzero (type, sizeof (struct type));
+
+         base_type = decode_type (cs, new_c_type, aux);
+
+         TYPE_CODE (type) = TYPE_CODE_ARRAY;
+         TYPE_TARGET_TYPE (type) = base_type;
+         TYPE_LENGTH (type) = n * TYPE_LENGTH (base_type);
+       }
+      return type;
+    }
+
+  /* Reference to existing type */
+  if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx != 0)
+    {
+      type = coff_alloc_type (aux->x_sym.x_tagndx);
+      return type;
+    }
+
+  return decode_base_type (cs, BTYPE (c_type), aux);
+}
+
+/* Decode a coff type specifier for function definition;
+   return the type that the function returns.  */
+
+static
+struct type *
+decode_function_type (cs, c_type, aux)
+     register struct coff_symbol *cs;
+     unsigned int c_type;
+     register AUXENT *aux;
+{
+  if (aux->x_sym.x_tagndx == 0)
+    cs->c_nsyms = 1;   /* auxent refers to function, not base type */
+
+  return decode_type (cs, DECREF (c_type), aux);
+}
+\f
+/* basic C types */
+
+static
+struct type *
+decode_base_type (cs, c_type, aux)
+     register struct coff_symbol *cs;
+     unsigned int c_type;
+     register AUXENT *aux;
+{
+  struct type *type;
+
+  switch (c_type)
+    {
+      case T_NULL:
+        /* shows up with "void (*foo)();" structure members */
+       return builtin_type_void;
+
+#ifdef T_ARG
+      case T_ARG:
+       /* Shows up in DGUX, I think.  Not sure where.  */
+       return builtin_type_void;       /* shouldn't show up here */
+#endif
+
+#ifdef T_VOID
+      case T_VOID:
+       /* Intel 960 COFF has this symbol and meaning.  */
+       return builtin_type_void;
+#endif
+
+      case T_CHAR:
+       return builtin_type_char;
+
+      case T_SHORT:
+       return builtin_type_short;
+
+      case T_INT:
+       return builtin_type_int;
+
+      case T_LONG:
+       return builtin_type_long;
+
+      case T_FLOAT:
+       return builtin_type_float;
+
+      case T_DOUBLE:
+       return builtin_type_double;
+
+      case T_STRUCT:
+       if (cs->c_nsyms != 2)
+         {
+           /* anonymous structure type */
+           type = coff_alloc_type (cs->c_symnum);
+           TYPE_CODE (type) = TYPE_CODE_STRUCT;
+           TYPE_NAME (type) = concat ("struct ", "<opaque>", "");
+           TYPE_LENGTH (type) = 0;
+           TYPE_FIELDS (type) = 0;
+           TYPE_NFIELDS (type) = 0;
+         }
+       else
+         {
+           type = read_struct_type (cs->c_symnum,
+                                   aux->x_sym.x_misc.x_lnsz.x_size,
+                                   aux->x_sym.x_fcnary.x_fcn.x_endndx);
+         }
+       return type;
+
+      case T_UNION:
+       if (cs->c_nsyms != 2)
+         {
+           /* anonymous union type */
+           type = coff_alloc_type (cs->c_symnum);
+           TYPE_NAME (type) = concat ("union ", "<opaque>", "");
+           TYPE_LENGTH (type) = 0;
+           TYPE_FIELDS (type) = 0;
+           TYPE_NFIELDS (type) = 0;
+         }
+       else
+         {
+           type = read_struct_type (cs->c_symnum,
+                                   aux->x_sym.x_misc.x_lnsz.x_size,
+                                   aux->x_sym.x_fcnary.x_fcn.x_endndx);
+         }
+       TYPE_CODE (type) = TYPE_CODE_UNION;
+       return type;
+
+      case T_ENUM:
+       return read_enum_type (cs->c_symnum,
+                                   aux->x_sym.x_misc.x_lnsz.x_size,
+                                   aux->x_sym.x_fcnary.x_fcn.x_endndx);
+
+      case T_MOE:
+       /* shouldn't show up here */
+       break;
+
+      case T_UCHAR:
+       return builtin_type_unsigned_char;
+
+      case T_USHORT:
+       return builtin_type_unsigned_short;
+
+      case T_UINT:
+       return builtin_type_unsigned_int;
+
+      case T_ULONG:
+       return builtin_type_unsigned_long;
+    }
+  printf ("unexpected type %d at symnum %d\n", c_type, cs->c_symnum);
+  return builtin_type_void;
+}
+\f
+/* This page contains subroutines of read_type.  */
+
+/* Read the description of a structure (or union type)
+   and return an object describing the type.  */
+
+static struct type *
+read_struct_type (index, length, lastsym)
+     int index;
+     int length;
+     int lastsym;
+{
+  struct nextfield
+    {
+      struct nextfield *next;
+      struct field field;
+    };
+
+  register struct type *type;
+  register struct nextfield *list = 0;
+  struct nextfield *new;
+  int nfields = 0;
+  register int n;
+  char *name;
+#ifdef NAMES_HAVE_UNDERSCORE
+  int offset = 1;
+#else
+  int offset = 0;
+#endif
+  struct coff_symbol member_sym;
+  register struct coff_symbol *ms = &member_sym;
+  SYMENT sub_sym;
+  AUXENT sub_aux;
+  int done = 0;
+
+  type = coff_alloc_type (index);
+  TYPE_CODE (type) = TYPE_CODE_STRUCT;
+  TYPE_LENGTH (type) = length;
+
+  while (!done && symnum < lastsym && symnum < nlist_nsyms_global)
+    {
+      read_one_sym (ms, &sub_sym, &sub_aux);
+      name = ms->c_name;
+      name = (name[0] == '_' ? name + offset : name);
+
+      switch (ms->c_sclass)
+       {
+         case C_MOS:
+         case C_MOU:
+
+           /* Get space to record the next field's data.  */
+           new = (struct nextfield *) alloca (sizeof (struct nextfield));
+           new->next = list;
+           list = new;
+
+           /* Save the data.  */
+           list->field.name = savestring (name, strlen (name));
+           list->field.type = decode_type (ms, ms->c_type, &sub_aux);
+           list->field.bitpos = 8 * ms->c_value;
+           list->field.bitsize = 0;
+           nfields++;
+           break;
+
+         case C_FIELD:
+
+           /* Get space to record the next field's data.  */
+           new = (struct nextfield *) alloca (sizeof (struct nextfield));
+           new->next = list;
+           list = new;
+
+           /* Save the data.  */
+           list->field.name = savestring (name, strlen (name));
+           list->field.type = decode_type (ms, ms->c_type, &sub_aux);
+           list->field.bitpos = ms->c_value;
+           list->field.bitsize = sub_aux.x_sym.x_misc.x_lnsz.x_size;
+           nfields++;
+           break;
+
+         case C_EOS:
+           done = 1;
+           break;
+       }
+    }
+  /* Now create the vector of fields, and record how big it is.  */
+
+  TYPE_NFIELDS (type) = nfields;
+  TYPE_FIELDS (type) = (struct field *)
+               obstack_alloc (symbol_obstack, sizeof (struct field) * nfields);
+
+  /* Copy the saved-up fields into the field vector.  */
+
+  for (n = nfields; list; list = list->next)
+    TYPE_FIELD (type, --n) = list->field;
+
+  return type;
+}
+\f
+/* Read a definition of an enumeration type,
+   and create and return a suitable type object.
+   Also defines the symbols that represent the values of the type.  */
+
+static struct type *
+read_enum_type (index, length, lastsym)
+     int index;
+     int length;
+     int lastsym;
+{
+  register struct symbol *sym;
+  register struct type *type;
+  int nsyms = 0;
+  int done = 0;
+  struct pending **symlist;
+  struct coff_symbol member_sym;
+  register struct coff_symbol *ms = &member_sym;
+  SYMENT sub_sym;
+  AUXENT sub_aux;
+  struct pending *osyms, *syms;
+  register int n;
+  char *name;
+#ifdef NAMES_HAVE_UNDERSCORE
+  int offset = 1;
+#else
+  int offset = 0;
+#endif
+
+  type = coff_alloc_type (index);
+  if (within_function)
+    symlist = &local_symbols;
+  else
+    symlist = &file_symbols;
+  osyms = *symlist;
+
+  while (!done && symnum < lastsym && symnum < nlist_nsyms_global)
+    {
+      read_one_sym (ms, &sub_sym, &sub_aux);
+      name = ms->c_name;
+      name = (name[0] == '_' ? name + offset : name);
+
+      switch (ms->c_sclass)
+       {
+         case C_MOE:
+           sym = (struct symbol *) xmalloc (sizeof (struct symbol));
+           bzero (sym, sizeof (struct symbol));
+
+           SYMBOL_NAME (sym) = savestring (name, strlen (name));
+           SYMBOL_CLASS (sym) = LOC_CONST;
+           SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+           SYMBOL_VALUE (sym) = ms->c_value;
+           add_symbol_to_list (sym, symlist);
+           nsyms++;
+           break;
+
+         case C_EOS:
+           /* Sometimes the linker (on 386/ix 2.0.2 at least) screws
+              up the count of how many symbols to read.  So stop
+              on .eos.  */
+           done = 1;
+           break;
+       }
+    }
+
+  /* Now fill in the fields of the type-structure.  */
+
+  TYPE_LENGTH (type) = sizeof (int);
+  TYPE_CODE (type) = TYPE_CODE_ENUM;
+  TYPE_NFIELDS (type) = nsyms;
+  TYPE_FIELDS (type) = (struct field *)
+               obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms);
+
+  /* Find the symbols for the values and put them into the type.
+     The symbols can be found in the symlist that we put them on
+     to cause them to be defined.  osyms contains the old value
+     of that symlist; everything up to there was defined by us.  */
+
+  for (syms = *symlist, n = nsyms; syms != osyms; syms = syms->next)
+    {
+      SYMBOL_TYPE (syms->symbol) = type;
+      TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol);
+      TYPE_FIELD_VALUE (type, n) = 0;
+      TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (syms->symbol);
+      TYPE_FIELD_BITSIZE (type, n) = 0;
+    }
+  return type;
+}
+
+/* Register our ability to parse symbols for coff BFD files */
+
+static struct sym_fns coff_sym_fns =
+{
+    "coff", 4,
+    coff_new_init, coff_symfile_init,
+    coff_symfile_read, coff_symfile_discard
+};
+
+void
+_initialize_coffread ()
+{
+  add_symtab_fns(&coff_sym_fns);
+}
diff --git a/gdb/command.c b/gdb/command.c
new file mode 100644 (file)
index 0000000..0b541a7
--- /dev/null
@@ -0,0 +1,1150 @@
+/* Library for reading command lines and decoding commands.
+   Copyright (C) 1986, 1989, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+extern char *getenv ();
+
+/* Add element named NAME to command list *LIST.
+   FUN should be the function to execute the command;
+   it will get a character string as argument, with leading
+   and trailing blanks already eliminated.
+
+   DOC is a documentation string for the command.
+   Its first line should be a complete sentence.
+   It should start with ? for a command that is an abbreviation
+   or with * for a command that most users don't need to know about.  */
+
+struct cmd_list_element *
+add_cmd (name, class, fun, doc, list)
+     char *name;
+     enum command_class class;
+     void (*fun) ();
+     char *doc;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c
+    = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+  delete_cmd (name, list);
+  c->next = *list;
+  c->name = name;
+  c->class = class;
+  c->function = fun;
+  c->doc = doc;
+  c->prefixlist = 0;
+  c->prefixname = (char *)NULL;
+  c->allow_unknown = 0;
+  c->abbrev_flag = 0;
+  c->aux = 0;
+  c->type = not_set_cmd;
+  c->completer = make_symbol_completion_list;
+  c->var = 0;
+  c->var_type = var_boolean;
+  c->user_commands = 0;
+  *list = c;
+  return c;
+}
+
+/* Same as above, except that the abbrev_flag is set. */
+
+struct cmd_list_element *
+add_abbrev_cmd (name, class, fun, doc, list)
+     char *name;
+     enum command_class class;
+     void (*fun) ();
+     char *doc;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c
+    = add_cmd (name, class, fun, doc, list);
+
+  c->abbrev_flag = 1;
+  return c;
+}
+
+struct cmd_list_element *
+add_alias_cmd (name, oldname, class, abbrev_flag, list)
+     char *name;
+     char *oldname;
+     enum command_class class;
+     int abbrev_flag;
+     struct cmd_list_element **list;
+{
+  /* Must do this since lookup_cmd tries to side-effect its first arg */
+  char *copied_name;
+  register struct cmd_list_element *old;
+  register struct cmd_list_element *c;
+  copied_name = (char *) alloca (strlen (oldname) + 1);
+  strcpy (copied_name, oldname);
+  old  = lookup_cmd (&copied_name, *list, "", 1, 1);
+
+  if (old == 0)
+    {
+      delete_cmd (name, list);
+      return 0;
+    }
+
+  c = add_cmd (name, class, old->function, old->doc, list);
+  c->prefixlist = old->prefixlist;
+  c->prefixname = old->prefixname;
+  c->allow_unknown = old->allow_unknown;
+  c->abbrev_flag = abbrev_flag;
+  c->aux = old->aux;
+  return c;
+}
+
+/* Like add_cmd but adds an element for a command prefix:
+   a name that should be followed by a subcommand to be looked up
+   in another command list.  PREFIXLIST should be the address
+   of the variable containing that list.  */
+
+struct cmd_list_element *
+add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+               allow_unknown, list)
+     char *name;
+     enum command_class class;
+     void (*fun) ();
+     char *doc;
+     struct cmd_list_element **prefixlist;
+     char *prefixname;
+     int allow_unknown;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+  c->prefixlist = prefixlist;
+  c->prefixname = prefixname;
+  c->allow_unknown = allow_unknown;
+  return c;
+}
+
+/* Like add_prefix_cmd butsets the abbrev_flag on the new command. */
+   
+struct cmd_list_element *
+add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+               allow_unknown, list)
+     char *name;
+     enum command_class class;
+     void (*fun) ();
+     char *doc;
+     struct cmd_list_element **prefixlist;
+     char *prefixname;
+     int allow_unknown;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+  c->prefixlist = prefixlist;
+  c->prefixname = prefixname;
+  c->allow_unknown = allow_unknown;
+  c->abbrev_flag = 1;
+  return c;
+}
+
+void
+not_just_help_class_command (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+}
+
+/* Add element named NAME to command list LIST (the list for set
+   or some sublist thereof).
+   CLASS is as in add_cmd.
+   VAR_TYPE is the kind of thing we are setting.
+   VAR is address of the variable being controlled by this command.
+   DOC is the documentation string.  */
+struct cmd_list_element *
+add_set_cmd (name, class, var_type, var, doc, list)
+     char *name;
+     enum command_class class;
+     var_types var_type;
+     char *var;
+     char *doc;
+     struct cmd_list_element **list;
+{
+  /* For set/show, we have to call do_setshow_command
+     differently than an ordinary function (take commandlist as
+     well as arg), so the function field isn't helpful.  However,
+     function == NULL means that it's a help class, so set the function
+     to not_just_help_class_command.  */
+  struct cmd_list_element *c
+    = add_cmd (name, class, not_just_help_class_command, doc, list);
+
+  c->type = set_cmd;
+  c->var_type = var_type;
+  c->var = var;
+  return c;
+}
+
+/* Where SETCMD has already been added, add the corresponding show
+   command to LIST and return a pointer to it.  */
+struct cmd_list_element *
+add_show_from_set (setcmd, list)
+     struct cmd_list_element *setcmd;
+     struct cmd_list_element **list;
+{
+  struct cmd_list_element *showcmd =
+    (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+  bcopy (setcmd, showcmd, sizeof (struct cmd_list_element));
+  delete_cmd (showcmd->name, list);
+  showcmd->type = show_cmd;
+  
+  /* Replace "set " at start of docstring with "show ".  */
+  if (setcmd->doc[0] == 'S' && setcmd->doc[1] == 'e'
+      && setcmd->doc[2] == 't' && setcmd->doc[3] == ' ')
+    showcmd->doc = concat ("Show ", setcmd->doc + 4, "");
+  else
+    fprintf (stderr, "GDB internal error: Bad docstring for set command\n");
+  
+  showcmd->next = *list;
+  *list = showcmd;
+  return showcmd;
+}
+
+/* Remove the command named NAME from the command list.  */
+
+void
+delete_cmd (name, list)
+     char *name;
+     struct cmd_list_element **list;
+{
+  register struct cmd_list_element *c;
+  struct cmd_list_element *p;
+
+  while (*list && !strcmp ((*list)->name, name))
+    {
+      p = (*list)->next;
+      free (*list);
+      *list = p;
+    }
+
+  if (*list)
+    for (c = *list; c->next;)
+      {
+       if (!strcmp (c->next->name, name))
+         {
+           p = c->next->next;
+           free (c->next);
+           c->next = p;
+         }
+       else
+         c = c->next;
+      }
+}
+
+void help_cmd (), help_list (), help_cmd_list ();
+
+/* This command really has to deal with two things:
+ *     1) I want documentation on *this string* (usually called by
+ * "help commandname").
+ *     2) I want documentation on *this list* (usually called by
+ * giving a command that requires subcommands.  Also called by saying
+ * just "help".)
+ *
+ *   I am going to split this into two seperate comamnds, help_cmd and
+ * help_list. 
+ */
+
+void
+help_cmd (command, stream)
+     char *command;
+     FILE *stream;
+{
+  struct cmd_list_element *c;
+  extern struct cmd_list_element *cmdlist;
+
+  if (!command)
+    {
+      help_list (cmdlist, "", all_classes, stream);
+      return;
+    }
+
+  c = lookup_cmd (&command, cmdlist, "", 0, 0);
+
+  if (c == 0)
+    return;
+
+  /* There are three cases here.
+     If c->prefixlist is nonzero, we have a prefix command.
+     Print its documentation, then list its subcommands.
+     
+     If c->function is nonzero, we really have a command.
+     Print its documentation and return.
+     
+     If c->function is zero, we have a class name.
+     Print its documentation (as if it were a command)
+     and then set class to the number of this class
+     so that the commands in the class will be listed.  */
+
+  fputs_filtered (c->doc, stream);
+  fputs_filtered ("\n", stream);
+
+  if (c->prefixlist == 0 && c->function != 0)
+    return;
+  fprintf_filtered (stream, "\n");
+
+  /* If this is a prefix command, print it's subcommands */
+  if (c->prefixlist)
+    help_list (*c->prefixlist, c->prefixname, all_commands, stream);
+
+  /* If this is a class name, print all of the commands in the class */
+  if (c->function == 0)
+    help_list (cmdlist, "", c->class, stream);
+}
+
+/*
+ * Get a specific kind of help on a command list.
+ *
+ * LIST is the list.
+ * CMDTYPE is the prefix to use in the title string.
+ * CLASS is the class with which to list the nodes of this list (see
+ * documentation for help_cmd_list below),  As usual, ALL_COMMANDS for
+ * everything, ALL_CLASSES for just classes, and non-negative for only things
+ * in a specific class.
+ * and STREAM is the output stream on which to print things.
+ * If you call this routine with a class >= 0, it recurses.
+ */
+void
+help_list (list, cmdtype, class, stream)
+     struct cmd_list_element *list;
+     char *cmdtype;
+     enum command_class class;
+     FILE *stream;
+{
+  int len;
+  char *cmdtype1, *cmdtype2;
+  
+  /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub"  */
+  len = strlen (cmdtype);
+  cmdtype1 = (char *) alloca (len + 1);
+  cmdtype1[0] = 0;
+  cmdtype2 = (char *) alloca (len + 4);
+  cmdtype2[0] = 0;
+  if (len)
+    {
+      cmdtype1[0] = ' ';
+      strncpy (cmdtype1 + 1, cmdtype, len - 1);
+      cmdtype1[len] = 0;
+      strncpy (cmdtype2, cmdtype, len - 1);
+      strcpy (cmdtype2 + len - 1, " sub");
+    }
+
+  if (class == all_classes)
+    fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
+  else
+    fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
+
+  help_cmd_list (list, class, cmdtype, (int)class >= 0, stream);
+
+  if (class == all_classes)
+    fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by a class name for a list of commands in that class.",
+            cmdtype1);
+
+  fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by %scommand name for full documentation.\n\
+Command name abbreviations are allowed if unambiguous.\n",
+          cmdtype1, cmdtype2);
+}
+     
+/* Print only the first line of STR on STREAM.  */
+static void
+print_doc_line (stream, str)
+     FILE *stream;
+     char *str;
+{
+  static char *line_buffer = 0;
+  static int line_size;
+  register char *p;
+
+  if (!line_buffer)
+    {
+      line_size = 80;
+      line_buffer = (char *) xmalloc (line_size);
+    }
+
+  p = str;
+  while (*p && *p != '\n' && *p != '.' && *p != ',')
+    p++;
+  if (p - str > line_size - 1)
+    {
+      line_size = p - str + 1;
+      free (line_buffer);
+      line_buffer = (char *) xmalloc (line_size);
+    }
+  strncpy (line_buffer, str, p - str);
+  line_buffer[p - str] = '\0';
+  if (islower (line_buffer[0]))
+    line_buffer[0] = toupper (line_buffer[0]);
+  fputs_filtered (line_buffer, stream);
+}
+
+/*
+ * Implement a help command on command list LIST.
+ * RECURSE should be non-zero if this should be done recursively on
+ * all sublists of LIST.
+ * PREFIX is the prefix to print before each command name.
+ * STREAM is the stream upon which the output should be written.
+ * CLASS should be:
+ *     A non-negative class number to list only commands in that
+ * class.
+ *     ALL_COMMANDS to list all commands in list.
+ *     ALL_CLASSES  to list all classes in list.
+ *
+ *   Note that RECURSE will be active on *all* sublists, not just the
+ * ones seclected by the criteria above (ie. the selection mechanism
+ * is at the low level, not the high-level).
+ */
+void
+help_cmd_list (list, class, prefix, recurse, stream)
+     struct cmd_list_element *list;
+     enum command_class class;
+     char *prefix;
+     int recurse;
+     FILE *stream;
+{
+  register struct cmd_list_element *c;
+
+  for (c = list; c; c = c->next)
+    {
+      if (c->abbrev_flag == 0 &&
+         (class == all_commands
+         || (class == all_classes && c->function == 0)
+         || (class == c->class && c->function != 0)))
+       {
+         fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+         print_doc_line (stream, c->doc);
+         fputs_filtered ("\n", stream);
+       }
+      if (recurse
+         && c->prefixlist != 0
+         && c->abbrev_flag == 0)
+       help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
+    }
+}
+\f
+/* This routine takes a line of TEXT and a CLIST in which to
+   start the lookup.  When it returns it will have incremented the text
+   pointer past the section of text it matched, set *RESULT_LIST to
+   the list in which the last word was matched, and will return the
+   cmd list element which the text matches.  It will return 0 if no
+   match at all was possible.  It will return -1 if ambigous matches are
+   possible; in this case *RESULT_LIST will be set to the list in which
+   there are ambiguous choices (and text will be set to the ambiguous
+   text string).
+
+   It does no error reporting whatsoever; control will always return
+   to the superior routine.
+
+   In the case of an ambiguous return (-1), *RESULT_LIST will be set to
+   point at the prefix_command (ie. the best match) *or* (special
+   case) will be 0 if no prefix command was ever found.  For example,
+   in the case of "info a", "info" matches without ambiguity, but "a"
+   could be "args" or "address", so *RESULT_LIST is set to
+   the cmd_list_element for "info".  So in this case
+   result list should not be interpeted as a pointer to the beginning
+   of a list; it simply points to a specific command.
+
+   If RESULT_LIST is NULL, don't set *RESULT_LIST (but don't otherwise
+   affect the operation).
+
+   This routine does *not* modify the text pointed to by TEXT.
+   
+   If IGNORE_HELP_CLASSES is nonzero, ignore any command list
+   elements which are actually help classes rather than commands (i.e.
+   the function field of the struct cmd_list_element is 0).  */
+
+struct cmd_list_element *
+lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
+     char **text;
+     struct cmd_list_element *clist, **result_list;
+     int ignore_help_classes;
+{
+  char *p, *command;
+  int len, tmp, nfound;
+  struct cmd_list_element *found, *c;
+
+  while (**text == ' ' || **text == '\t')
+    (*text)++;
+
+  /* Treating underscores as part of command words is important
+     so that "set args_foo()" doesn't get interpreted as
+     "set args _foo()".  */
+  for (p = *text;
+       *p && (isalnum(*p) || *p == '-' || *p == '_');
+       p++)
+    ;
+
+  /* If nothing but whitespace, return 0.  */
+  if (p == *text)
+    return 0;
+  
+  len = p - *text;
+
+  /* *text and p now bracket the first command word to lookup (and
+     it's length is len).  We copy this into a local temporary,
+     converting to lower case as we go.  */
+
+  command = (char *) alloca (len + 1);
+  for (tmp = 0; tmp < len; tmp++)
+    {
+      char x = (*text)[tmp];
+      command[tmp] = (x >= 'A' && x <= 'Z') ? x - 'A' + 'a' : x;
+    }
+  command[len] = '\0';
+
+  /* Look it up.  */
+  found = 0;
+  nfound = 0;
+  for (c = clist; c; c = c->next)
+    if (!strncmp (command, c->name, len)
+       && (!ignore_help_classes || c->function))
+      {
+       found = c;
+       nfound++;
+       if (c->name[len] == '\0')
+         {
+           nfound = 1;
+           break;
+         }
+      }
+
+  /* If nothing matches, we have a simple failure.  */
+  if (nfound == 0)
+    return 0;
+
+  if (nfound > 1)
+    {
+      if (result_list != NULL)
+       /* Will be modified in calling routine
+          if we know what the prefix command is.  */
+       *result_list = 0;               
+      return (struct cmd_list_element *) -1; /* Ambiguous.  */
+    }
+
+  /* We've matched something on this list.  Move text pointer forward. */
+
+  *text = p;
+  if (found->prefixlist)
+    {
+      c = lookup_cmd_1 (text, *found->prefixlist, result_list,
+                       ignore_help_classes);
+      if (!c)
+       {
+         /* Didn't find anything; this is as far as we got.  */
+         if (result_list != NULL)
+           *result_list = clist;
+         return found;
+       }
+      else if (c == (struct cmd_list_element *) -1)
+       {
+         /* We've gotten this far properley, but the next step
+            is ambiguous.  We need to set the result list to the best
+            we've found (if an inferior hasn't already set it).  */
+         if (result_list != NULL)
+           if (!*result_list)
+             /* This used to say *result_list = *found->prefixlist
+                If that was correct, need to modify the documentation
+                at the top of this function to clarify what is supposed
+                to be going on.  */
+             *result_list = found;
+         return c;
+       }
+      else
+       {
+         /* We matched!  */
+         return c;
+       }
+    }
+  else
+    {
+      if (result_list != NULL)
+       *result_list = clist;
+      return found;
+    }
+}
+
+/* Look up the contents of *LINE as a command in the command list LIST.
+   LIST is a chain of struct cmd_list_element's.
+   If it is found, return the struct cmd_list_element for that command
+   and update *LINE to point after the command name, at the first argument.
+   If not found, call error if ALLOW_UNKNOWN is zero
+   otherwise (or if error returns) return zero.
+   Call error if specified command is ambiguous,
+   unless ALLOW_UNKNOWN is negative.
+   CMDTYPE precedes the word "command" in the error message.
+
+   If INGNORE_HELP_CLASSES is nonzero, ignore any command list
+   elements which are actually help classes rather than commands (i.e.
+   the function field of the struct cmd_list_element is 0).  */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
+     char **line;
+     struct cmd_list_element *list;
+     char *cmdtype;
+     int allow_unknown;
+     int ignore_help_classes;
+{
+  struct cmd_list_element *last_list = 0;
+  struct cmd_list_element *c =
+    lookup_cmd_1 (line, list, &last_list, ignore_help_classes);
+  char *ptr = (*line) + strlen (*line) - 1;
+
+  /* Clear off trailing whitespace.  */
+  while (ptr >= *line && (*ptr == ' ' || *ptr == '\t'))
+    ptr--;
+  *(ptr + 1) = '\0';
+  
+  if (!c)
+    {
+      if (!allow_unknown)
+       {
+         if (!*line)
+           error ("Lack of needed %scommand", cmdtype);
+         else
+           {
+             char *p = *line, *q;
+
+             while (isalnum(*p) || *p == '-')
+               p++;
+
+             q = (char *) alloca (p - *line + 1);
+             strncpy (q, *line, p - *line);
+             q[p-*line] = '\0';
+             
+             error ("Undefined %scommand: \"%s\".", cmdtype, q);
+           }
+       }
+      else
+       return 0;
+    }
+  else if (c == (struct cmd_list_element *) -1)
+    {
+      /* Ambigous.  Local values should be off prefixlist or called
+        values.  */
+      int local_allow_unknown = (last_list ? last_list->allow_unknown :
+                                allow_unknown);
+      char *local_cmdtype = last_list ? last_list->prefixname : cmdtype;
+      struct cmd_list_element *local_list =
+       (last_list ? *(last_list->prefixlist) : list);
+      
+      if (local_allow_unknown < 0)
+       {
+         if (last_list)
+           return last_list;   /* Found something.  */
+         else
+           return 0;           /* Found nothing.  */
+       }
+      else
+       {
+         /* Report as error.  */
+         int amb_len;
+         char ambbuf[100];
+
+         for (amb_len = 0;
+              ((*line)[amb_len] && (*line)[amb_len] != ' '
+               && (*line)[amb_len] != '\t');
+              amb_len++)
+           ;
+         
+         ambbuf[0] = 0;
+         for (c = local_list; c; c = c->next)
+           if (!strncmp (*line, c->name, amb_len))
+             {
+               if (strlen (ambbuf) + strlen (c->name) + 6 < (int)sizeof ambbuf)
+                 {
+                   if (strlen (ambbuf))
+                     strcat (ambbuf, ", ");
+                   strcat (ambbuf, c->name);
+                 }
+               else
+                 {
+                   strcat (ambbuf, "..");
+                   break;
+                 }
+             }
+         error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
+                *line, ambbuf);
+         return 0;             /* lint */
+       }
+    }
+  else
+    {
+      /* We've got something.  It may still not be what the caller
+         wants (if this command *needs* a subcommand).  */
+      while (**line == ' ' || **line == '\t')
+       (*line)++;
+
+      if (c->prefixlist && **line && !c->allow_unknown)
+       error ("Undefined %scommand: \"%s\".", c->prefixname, *line);
+
+      /* Seems to be what he wants.  Return it.  */
+      return c;
+    }
+  return 0;
+}
+       
+#if 0
+/* Look up the contents of *LINE as a command in the command list LIST.
+   LIST is a chain of struct cmd_list_element's.
+   If it is found, return the struct cmd_list_element for that command
+   and update *LINE to point after the command name, at the first argument.
+   If not found, call error if ALLOW_UNKNOWN is zero
+   otherwise (or if error returns) return zero.
+   Call error if specified command is ambiguous,
+   unless ALLOW_UNKNOWN is negative.
+   CMDTYPE precedes the word "command" in the error message.  */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown)
+     char **line;
+     struct cmd_list_element *list;
+     char *cmdtype;
+     int allow_unknown;
+{
+  register char *p;
+  register struct cmd_list_element *c, *found;
+  int nfound;
+  char ambbuf[100];
+  char *processed_cmd;
+  int i, cmd_len;
+
+  /* Skip leading whitespace.  */
+
+  while (**line == ' ' || **line == '\t')
+    (*line)++;
+
+  /* Clear out trailing whitespace.  */
+
+  p = *line + strlen (*line);
+  while (p != *line && (p[-1] == ' ' || p[-1] == '\t'))
+    p--;
+  *p = 0;
+
+  /* Find end of command name.  */
+
+  p = *line;
+  while (*p == '-'
+        || (*p >= 'a' && *p <= 'z')
+        || (*p >= 'A' && *p <= 'Z')
+        || (*p >= '0' && *p <= '9'))
+    p++;
+
+  /* Look up the command name.
+     If exact match, keep that.
+     Otherwise, take command abbreviated, if unique.  Note that (in my
+     opinion) a null string does *not* indicate ambiguity; simply the
+     end of the argument.  */
+
+  if (p == *line)
+    {
+      if (!allow_unknown)
+       error ("Lack of needed %scommand", cmdtype);
+      return 0;
+    }
+  
+  /* Copy over to a local buffer, converting to lowercase on the way.
+     This is in case the command being parsed is a subcommand which
+     doesn't match anything, and that's ok.  We want the original
+     untouched for the routine of the original command.  */
+  
+  processed_cmd = (char *) alloca (p - *line + 1);
+  for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
+    {
+      char x = (*line)[cmd_len];
+      if (x >= 'A' && x <= 'Z')
+       processed_cmd[cmd_len] = x - 'A' + 'a';
+      else
+       processed_cmd[cmd_len] = x;
+    }
+  processed_cmd[cmd_len] = '\0';
+
+  /* Check all possibilities in the current command list.  */
+  found = 0;
+  nfound = 0;
+  for (c = list; c; c = c->next)
+    {
+      if (!strncmp (processed_cmd, c->name, cmd_len))
+       {
+         found = c;
+         nfound++;
+         if (c->name[cmd_len] == 0)
+           {
+             nfound = 1;
+             break;
+           }
+       }
+    }
+
+  /* Report error for undefined command name.  */
+
+  if (nfound != 1)
+    {
+      if (nfound > 1 && allow_unknown >= 0)
+       {
+         ambbuf[0] = 0;
+         for (c = list; c; c = c->next)
+           if (!strncmp (processed_cmd, c->name, cmd_len))
+             {
+               if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+                 {
+                   if (strlen (ambbuf))
+                     strcat (ambbuf, ", ");
+                   strcat (ambbuf, c->name);
+                 }
+               else
+                 {
+                   strcat (ambbuf, "..");
+                   break;
+                 }
+             }
+         error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
+                processed_cmd, ambbuf);
+       }
+      else if (!allow_unknown)
+       error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
+      return 0;
+    }
+
+  /* Skip whitespace before the argument.  */
+
+  while (*p == ' ' || *p == '\t') p++;
+  *line = p;
+
+  if (found->prefixlist && *p)
+    {
+      c = lookup_cmd (line, *found->prefixlist, found->prefixname,
+                     found->allow_unknown);
+      if (c)
+       return c;
+    }
+
+  return found;
+}
+#endif
+
+/* Helper function for SYMBOL_COMPLETION_FUNCTION.  */
+
+/* Return a vector of char pointers which point to the different
+   possible completions in LIST of TEXT.  */
+
+char **
+complete_on_cmdlist (list, text)
+     struct cmd_list_element *list;
+     char *text;
+{
+  struct cmd_list_element *ptr;
+  char **matchlist;
+  int sizeof_matchlist;
+  int matches;
+  int textlen = strlen (text);
+
+  sizeof_matchlist = 10;
+  matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
+  matches = 0;
+
+  for (ptr = list; ptr; ptr = ptr->next)
+    if (!strncmp (ptr->name, text, textlen)
+       && !ptr->abbrev_flag
+       && (ptr->function
+           || ptr->prefixlist))
+      {
+       if (matches == sizeof_matchlist)
+         {
+           sizeof_matchlist *= 2;
+           matchlist = (char **) xrealloc ((char *)matchlist,
+                                           (sizeof_matchlist
+                                            * sizeof (char *)));
+         }
+
+       matchlist[matches] = (char *) 
+         xmalloc (strlen (ptr->name) + 1);
+       strcpy (matchlist[matches++], ptr->name);
+      }
+
+  if (matches == 0)
+    {
+      free (matchlist);
+      matchlist = 0;
+    }
+  else
+    {
+      matchlist = (char **) xrealloc ((char *)matchlist, ((matches + 1)
+                                               * sizeof (char *)));
+      matchlist[matches] = (char *) 0;
+    }
+
+  return matchlist;
+}
+
+static int
+parse_binary_operation (arg)
+     char *arg;
+{
+  int length;
+
+  if (!arg || !*arg)
+    return 1;
+
+  length = strlen (arg);
+
+  while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
+    length--;
+
+  if (!strncmp (arg, "on", length)
+      || !strncmp (arg, "1", length)
+      || !strncmp (arg, "yes", length))
+    return 1;
+  else
+    if (!strncmp (arg, "off", length)
+       || !strncmp (arg, "0", length)
+       || !strncmp (arg, "no", length))
+      return 0;
+    else 
+      {
+       error ("\"on\" or \"off\" expected.");
+       return 0;
+      }
+}
+
+/* Do a "set" or "show" command.  ARG is NULL if no argument, or the text
+   of the argument, and FROM_TTY is nonzero if this command is being entered
+   directly by the user (i.e. these are just like any other
+   command).  C is the command list element for the command.  */
+void
+do_setshow_command (arg, from_tty, c)
+     char *arg;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  if (c->type == set_cmd)
+    {
+      switch (c->var_type)
+       {
+       case var_string:
+         {
+           char *new;
+           char *p;
+           char *q;
+           int ch;
+           
+           if (arg == NULL)
+             arg = "";
+           new = (char *) xmalloc (strlen (arg) + 2);
+           p = arg; q = new;
+           while (ch = *p++)
+             {
+               if (ch == '\\')
+                 {
+                   /* \ at end of argument is used after spaces
+                      so they won't be lost.  */
+                   if (*p == 0)
+                     break;
+                   ch = parse_escape (&p);
+                   if (ch == 0)
+                     break; /* C loses */
+                   else if (ch > 0)
+                     *q++ = ch;
+                 }
+               else
+                 *q++ = ch;
+             }
+           if (*(p - 1) != '\\')
+             *q++ = ' ';
+           *q++ = '\0';
+           new = (char *) xrealloc (new, q - new);
+           if (*(char **)c->var != NULL)
+             free (*(char **)c->var);
+           *(char **) c->var = new;
+         }
+         break;
+       case var_string_noescape:
+         if (arg == NULL)
+           arg = "";
+         if (*(char **)c->var != NULL)
+           free (*(char **)c->var);
+         *(char **) c->var = savestring (arg, strlen (arg));
+         break;
+       case var_filename:
+         if (arg == NULL)
+           error_no_arg ("filename to set it to.");
+         if (*(char **)c->var != NULL)
+           free (*(char **)c->var);
+         *(char **)c->var = tilde_expand (arg);
+         break;
+       case var_boolean:
+         *(int *) c->var = parse_binary_operation (arg);
+         break;
+       case var_uinteger:
+         if (arg == NULL)
+           error_no_arg ("integer to set it to.");
+         *(int *) c->var = parse_and_eval_address (arg);
+         if (*(int *) c->var == 0)
+           *(int *) c->var = UINT_MAX;
+         break;
+       case var_zinteger:
+         if (arg == NULL)
+           error_no_arg ("integer to set it to.");
+         *(int *) c->var = parse_and_eval_address (arg);
+         break;
+       default:
+         error ("gdb internal error: bad var_type in do_setshow_command");
+       }
+    }
+  else if (c->type == show_cmd)
+    {
+      /* Print doc minus "show" at start.  */
+      print_doc_line (stdout, c->doc + 5);
+      
+      fputs_filtered (" is ", stdout);
+      wrap_here ("    ");
+      switch (c->var_type)
+       {
+      case var_string:
+       {
+         unsigned char *p;
+         fputs_filtered ("\"", stdout);
+         for (p = *(unsigned char **) c->var; *p != '\0'; p++)
+           printchar (*p, stdout, '"');
+         fputs_filtered ("\"", stdout);
+       }
+       break;
+      case var_string_noescape:
+      case var_filename:
+       fputs_filtered ("\"", stdout);
+       fputs_filtered (*(char **) c->var, stdout);
+       fputs_filtered ("\"", stdout);
+       break;
+      case var_boolean:
+       fputs_filtered (*(int *) c->var ? "on" : "off", stdout);
+       break;
+      case var_uinteger:
+       if (*(unsigned int *) c->var == UINT_MAX) {
+         fputs_filtered ("unlimited", stdout);
+         break;
+       }
+       /* else fall through */
+      case var_zinteger:
+       fprintf_filtered (stdout, "%d", *(unsigned int *) c->var);
+       break;
+      default:
+       error ("gdb internal error: bad var_type in do_setshow_command");
+      }
+      fputs_filtered (".\n", stdout);
+    }
+  else
+    error ("gdb internal error: bad cmd_type in do_setshow_command");
+  (*c->function) (NULL, from_tty, c);
+}
+
+/* Show all the settings in a list of show commands.  */
+
+void
+cmd_show_list (list, from_tty, prefix)
+     struct cmd_list_element *list;
+     int from_tty;
+     char *prefix;
+{
+  for (; list != NULL; list = list->next) {
+    /* If we find a prefix, run its list, prefixing our output by its
+       prefix (with "show " skipped).  */
+    if (list->prefixlist && !list->abbrev_flag)
+      cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
+    if (list->type == show_cmd)
+      {
+       fputs_filtered (prefix, stdout);
+       fputs_filtered (list->name, stdout);
+       fputs_filtered (":  ", stdout);
+       do_setshow_command ((char *)NULL, from_tty, list);
+      }
+  }
+}
+
+static void
+shell_escape (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  int rc, status, pid;
+  char *p, *user_shell;
+  extern char *rindex ();
+
+  if ((user_shell = (char *) getenv ("SHELL")) == NULL)
+    user_shell = "/bin/sh";
+
+  /* Get the name of the shell for arg0 */
+  if ((p = rindex (user_shell, '/')) == NULL)
+    p = user_shell;
+  else
+    p++;                       /* Get past '/' */
+
+  if ((pid = fork()) == 0)
+    {
+      if (!arg)
+       execl (user_shell, p, 0);
+      else
+       execl (user_shell, p, "-c", arg, 0);
+
+      fprintf (stderr, "Exec of shell failed\n");
+      exit (0);
+    }
+
+  if (pid != -1)
+    while ((rc = wait (&status)) != pid && rc != -1)
+      ;
+  else
+    error ("Fork failed");
+}
+
+static void
+make_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  char *p;
+
+  if (arg == 0)
+    p = "make";
+  else
+    {
+      p = xmalloc (sizeof("make ") + strlen(arg));
+      strcpy (p, "make ");
+      strcpy (p + sizeof("make ")-1, arg);
+    }
+  
+  shell_escape (p, from_tty);
+}
+
+void
+_initialize_command ()
+{
+  add_com ("shell", class_support, shell_escape,
+          "Execute the rest of the line as a shell command.  \n\
+With no arguments, run an inferior shell.");
+
+  add_com ("make", class_support, make_command,
+          "Run the ``make'' program using the rest of the line as arguments.");
+}
diff --git a/gdb/command.h b/gdb/command.h
new file mode 100644 (file)
index 0000000..aa907fd
--- /dev/null
@@ -0,0 +1,151 @@
+/* Header file for command-reading library command.c.
+   Copyright (C) 1986, 1989, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _COMMAND_H_INCLUDED
+#define _COMMAND_H_INCLUDED
+
+/* Not a set/show command.  Note that some commands which begin with
+   "set" or "show" might be in this category, if their syntax does
+   not fall into one of the following categories.  */
+typedef enum cmd_types {
+  not_set_cmd,
+  set_cmd,
+  show_cmd,
+} cmd_types;
+
+/* Types of "set" or "show" command.  */
+typedef enum var_types {
+  /* "on" or "off".  *VAR is an integer which is nonzero for on,
+     zero for off.  */
+  var_boolean,
+  /* Unsigned Integer.  *VAR is an unsigned int.  The user can type 0
+     to mean "unlimited", which is stored in *VAR as UINT_MAX.  */
+  var_uinteger,
+  /* String which the user enters with escapes (e.g. the user types \n and
+     it is a real newline in the stored string).
+     *VAR is a malloc'd string, or NULL if the string is empty.  */
+  var_string,
+  /* String which stores what the user types verbatim.
+     *VAR is a malloc'd string, or NULL if the string is empty.  */
+  var_string_noescape,
+  /* String which stores a filename.
+     *VAR is a malloc'd string, or NULL if the string is empty.  */
+  var_filename,
+  /* ZeroableInteger.  *VAR is an int.  Like Unsigned Integer except
+     that zero really means zero.  */
+  var_zinteger,
+} var_types;
+
+/* This structure records one command'd definition.  */
+
+struct cmd_list_element
+  {
+    /* Points to next command in this list.  */
+    struct cmd_list_element *next;
+
+    /* Name of this command.  */
+    char *name;
+
+    /* Command class; class values are chosen by application program.  */
+    enum command_class class;
+
+    /* Function definition of this command.
+       Zero for command class names and for help topics that
+       are not really commands.  */
+    void (*function) ();
+#   define NO_FUNCTION ((void (*)()) 0 )
+
+    /* Documentation of this command (or help topic).
+       First line is brief documentation; remaining lines form, with it,
+       the full documentation.  First line should end with a period.
+       Entire string should also end with a period, not a newline.  */
+    char *doc;
+
+    /* Auxiliary information.
+       It is up to the calling program to decide what this means.  */
+    char *aux;
+
+    /* Nonzero identifies a prefix command.  For them, the address
+       of the variable containing the list of subcommands.  */
+    struct cmd_list_element **prefixlist;
+
+    /* For prefix commands only:
+       String containing prefix commands to get here: this one
+       plus any others needed to get to it.  Should end in a space.
+       It is used before the word "command" in describing the
+       commands reached through this prefix.  */
+    char *prefixname;
+
+    /* For prefix commands only:
+       nonzero means do not get an error if subcommand is not
+       recognized; call the prefix's own function in that case.  */
+    char allow_unknown;
+
+    /* Nonzero says this is an abbreviation, and should not
+       be mentioned in lists of commands.
+       This allows "br<tab>" to complete to "break", which it
+       otherwise wouldn't.  */
+    char abbrev_flag;
+
+    /* Completion routine for this command.  */
+    char **(*completer)();
+
+    /* Type of "set" or "show" command (or SET_NOT_SET if not "set"
+       or "show").  */
+    cmd_types type;
+
+    /* Pointer to variable affected by "set" and "show".  Doesn't matter
+       if type is not_set.  */
+    char *var;
+
+    /* What kind of variable is *VAR?  */
+    var_types var_type;
+
+    /* Pointer to command strings of user-defined commands */
+    struct command_line *user_commands;
+  };
+
+/* Forward-declarations of the entry-points of command.c.  */
+
+extern struct cmd_list_element *add_cmd ();
+extern struct cmd_list_element *add_alias_cmd ();
+extern struct cmd_list_element *add_prefix_cmd ();
+extern struct cmd_list_element *add_abbrev_prefix_cmd ();
+extern struct cmd_list_element *lookup_cmd (), *lookup_cmd_1 ();
+extern void add_com ();
+extern void add_com_alias ();
+extern void add_info ();
+extern void add_info_alias ();
+extern char **complete_on_cmdlist ();
+extern void delete_cmd ();
+extern void help_cmd ();
+extern struct cmd_list_element *add_set_cmd ();
+extern struct cmd_list_element *add_show_from_set ();
+
+/* Do a "set" or "show" command.  ARG is NULL if no argument, or the text
+   of the argument, and FROM_TTY is nonzero if this command is being entered
+   directly by the user (i.e. these are just like any other
+   command).  C is the command list element for the command.  */
+extern void do_setshow_command ();
+
+/* Do a "show" command for each thing on a command list.  */
+extern void cmd_show_list ();
+
+extern void error_no_arg ();           /* Print error for missing argument */
+extern void dont_repeat ();            /* Avoid auto-repeat of command */
+
+#endif /* _COMMAND_H_INCLUDED */
diff --git a/gdb/config.gdb b/gdb/config.gdb
new file mode 100755 (executable)
index 0000000..917d94e
--- /dev/null
@@ -0,0 +1,185 @@
+#!/bin/sh
+
+# Shell script to do machine-dependent things in
+# preparation for compiling gdb.
+#
+# Usage: config.gdb machine
+#
+# If config.gdb succeeds, it leaves its status in config.status.
+# If config.gdb fails after disturbing the status quo, 
+#      config.status is removed.
+
+progname=$0
+host=
+target=
+list_hosts=
+list_targets=
+srcdir=
+
+for arg in $*; do
+  case $arg in
+    -srcdir=*|+srcdir=*)
+      srcdir=`echo $arg | sed 's/[+-]srcdir=//'`
+      ;;
+    -host|+host)
+      list_hosts=true
+      ;;
+    -target|+target)
+      list_targets=true
+      ;;
+    -host=*|+host=*)
+      if [ "$host" = "" ]; then
+        host=`echo $arg | sed 's/[+-]host=//'`
+      else
+        echo Error: Attempt to specify host machine twice
+        bad=true
+      fi
+      ;;
+    -target=*|+target=*)
+      if [ "$target" = "" ]; then
+        target=`echo $arg | sed 's/[+-]target=//'`
+      else
+        echo Error: Attempt to specify target machine twice
+        bad=true
+      fi
+      ;;
+    *)
+      if [ "$host" = "" ]; then
+       host=$arg
+      else
+        if [ "$target" = "" ]; then
+          target=$arg
+        else
+          echo Error: More arguments than host and target machine names
+         bad=true
+        fi
+      fi
+      ;;
+  esac
+done
+
+if [ "$target" = "" ]; then target=$host; fi
+if [ "$host" = "" ]; then bad=true; fi
+
+# Find the source files, if location was not specified
+if [ "$srcdir" = "" ]; then
+  srcdirdefaulted=true
+  srcdir=.
+  if [ ! -r main.c ]; then
+    srcdir=..
+  fi
+fi
+if [ ! -r ${srcdir}/main.c ]; then
+  if [ "$srcdirdefaulted" != "true" ]; then
+    echo "$progname: Can't find debugger sources in \`${srcdir}'." 1>&2
+  else
+    echo "$progname: Can't find debugger sources in \`.' or \`..'." 1>&2
+  fi
+  exit 1
+fi
+
+if [ "$list_hosts" = "true" ]; then
+  cd $srcdir/xconfig
+  for i in * ; do
+# The {} in ${i} are required or else /bin/sh in sony newsos 3.2 removes
+# the quote after it.
+  awk <$i "NR == 1 { lastchar = substr(\"${i}\", length(\"${i}\"), 1)
+if (lastchar != \"~\" && lastchar != \"#\") \
+printf \"%-12s %s\n\", \"${i}\", substr(\$0,2) }"
+  done
+fi
+
+if [ "$list_targets" = "true" ]; then
+  cd $srcdir/tconfig
+  for i in * ; do
+  awk <$i "NR == 1 { lastchar = substr(\"${i}\", length(\"${i}\"), 1)
+if (lastchar != \"~\" && lastchar != \"#\") \
+printf \"%-12s %s\n\", \"${i}\", substr(\$0,2) }"
+  done
+fi
+
+if [ "$list_hosts" = "true" -o "$list_targets" = "true" ]; then
+  exit 0
+fi
+
+if [ "$host" != "" -a ! -f $srcdir/xconfig/$host ]; then
+  echo "No such host $host"
+  bad=true
+fi
+
+if [ "$target" != "" -a ! -f $srcdir/tconfig/$target ]; then
+  echo "No such target $target"
+  bad=true
+fi
+
+if [ "$bad" = "true" ] ; then
+  echo "Usage: "
+  echo "  $progname [+srcdir=\`dir'] machine"
+  echo "    For normal usage"
+  echo "  $progname [+srcdir=\`dir'] \`host' \`target'"
+  echo "  $progname [+srcdir=\`dir'] +host=\`host' +target=\`target'"
+  echo "    If you are doing remote debugging between machines of two"
+  echo "    different types (cross-debugging).  \`host' is the type of"
+  echo "    machine on which GDB will be running.  \`target' is the"
+  echo "    machine that the program you are debugging will be"
+  echo "    running on."
+  echo "  $progname +host"
+  echo "    Print a list of valid host machine types."
+  echo "  $progname +target"
+  echo "    Print a list of valid target machine types."
+  echo
+  echo "  +srcdir=\`dir' means that the sources are in \`dir'.  For"
+  echo "    example, \`cd /obj/hp300; config.gdb +srcdir=/src/gdb hp300'"
+  echo "    If +srcdir is not specified, sources can either be in \`.'"
+  echo "    or \`..'."
+  echo
+
+  if [ -r config.status ]
+  then
+    cat config.status
+  fi
+  exit 1
+fi
+
+rm -f tm.h xm.h
+
+cat $srcdir/xconfig/$host $srcdir/tconfig/$target | awk '$1 == "#msg" {
+  print substr($0,6)}'
+paramfile=${srcdir}/`awk '
+  $1 == "TM_FILE=" { print $2 }' <$srcdir/tconfig/$target`
+if [ "$paramfile" != "${srcdir}/" ] ; then
+  # Make a symlink if possible, otherwise try a hard link
+  ln -s $paramfile tm.h 2>/dev/null || ln $paramfile tm.h
+fi
+
+paramfile=${srcdir}/`awk '
+  $1 == "XM_FILE=" { print $2 }' <$srcdir/xconfig/$host`
+if [ "$paramfile" != "${srcdir}/" ] ; then
+  # Make a symlink if possible, otherwise try a hard link
+  ln -s $paramfile xm.h 2>/dev/null || ln $paramfile xm.h
+fi
+
+rm -f config.status
+
+case ${srcdir} in
+  .)
+    ;;
+  *)
+    echo "srcdir=${srcdir}" >./Makefile.srcdir
+    grep -s "source ${srcdir}/.gdbinit" .gdbinit 2>/dev/null || \
+      echo "source ${srcdir}/.gdbinit" >> .gdbinit
+    if [ ! -d readline ]; then
+      mkdir readline
+      # This could be a symlink, but getting the name right (because
+      # srcdir can be either relative or absolute) would be hairy.
+      cp ${srcdir}/readline/Makefile readline
+    fi
+esac
+
+make "srcdir=${srcdir}" \
+  "M_MAKEFILE=$srcdir/tconfig/$target $srcdir/xconfig/$host" \
+  -f $srcdir/Makefile.dist Makefile
+
+echo "GDB is now set up for host machine $host and target machine $target." \
+       | tee config.status
+exit 0
diff --git a/gdb/config.status b/gdb/config.status
new file mode 100755 (executable)
index 0000000..ec87176
--- /dev/null
@@ -0,0 +1 @@
+GDB is now set up for host machine none and target machine none.
diff --git a/gdb/config/3b1.mh b/gdb/config/3b1.mh
new file mode 100644 (file)
index 0000000..76fc51d
--- /dev/null
@@ -0,0 +1,27 @@
+# AT&T 3b1/Unix pc
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# I don't think cc has been tried.  -traditional for <sys/ioctl.h>
+# (not sure whether necessary).
+CC= gcc -traditional
+# GCC runs out of virtual memory.
+PINSN_CC= cc
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-3b1.h
diff --git a/gdb/config/3b1.mt b/gdb/config/3b1.mt
new file mode 100644 (file)
index 0000000..8a73b46
--- /dev/null
@@ -0,0 +1,21 @@
+# AT&T 3b1/Unix pc
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-3b1.h
diff --git a/gdb/config/altos.mh b/gdb/config/altos.mh
new file mode 100644 (file)
index 0000000..03f93bf
--- /dev/null
@@ -0,0 +1,24 @@
+# Altos 3068 (68k, System V release 2)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o altos-xdep.o
+XM_FILE= xm-altos.h
+REGEX=regex.o
+REGEX1=regex.o
+SYSV_DEFINE=-DSYSV
diff --git a/gdb/config/altos.mt b/gdb/config/altos.mt
new file mode 100644 (file)
index 0000000..5d43893
--- /dev/null
@@ -0,0 +1,21 @@
+# Altos 3068 (68k, System V release 2)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-altos.h
diff --git a/gdb/config/altosgas.mh b/gdb/config/altosgas.mh
new file mode 100644 (file)
index 0000000..2ade447
--- /dev/null
@@ -0,0 +1,27 @@
+# Altos 3068 (68k, System V release 2), using COFF encapsulation
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the coff encapsulation features require the GNU binutils utilities
+#msg To be ahead of their System V counterparts in your path.
+
+XDEPFILES= infptrace.o altos-xdep.o
+XM_FILE= xm-altos.h
+REGEX=regex.o
+REGEX1=regex.o
+SYSV_DEFINE=-DSYSV
diff --git a/gdb/config/altosgas.mt b/gdb/config/altosgas.mt
new file mode 100644 (file)
index 0000000..3c502fc
--- /dev/null
@@ -0,0 +1,24 @@
+# Altos 3068 (68k, System V release 2), using COFF encapsulation
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the coff encapsulation features require the GNU binutils utilities
+#msg To be ahead of their System V counterparts in your path.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-altosgas.h
diff --git a/gdb/config/am29k b/gdb/config/am29k
new file mode 100755 (executable)
index 0000000..8a9b475
--- /dev/null
@@ -0,0 +1,23 @@
+# AMD 29000 on EB29K board over a serial line.
+# Copyright (C) 1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o am29k-pinsn.o remote-eb.o am29k-tdep.o
+TM_FILE= tm-29k.h
+# The following is for ../include/a.out.encap.h
+TM_CFLAGS = -DCOFF_ENCAPSULATE -DTARGET=TARGET_AM29K
diff --git a/gdb/config/arm.mh b/gdb/config/arm.mh
new file mode 100644 (file)
index 0000000..8dc057a
--- /dev/null
@@ -0,0 +1,21 @@
+# Acorn RISC machine running RISCiX (4.3bsd)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o arm-xdep.o arm-convert.o
+XM_FILE= xm-arm.h
diff --git a/gdb/config/arm.mt b/gdb/config/arm.mt
new file mode 100644 (file)
index 0000000..d26c862
--- /dev/null
@@ -0,0 +1,21 @@
+# Acorn RISC machine running RISCiX (4.3bsd)
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= arm-tdep.o arm-pinsn.o
+TM_FILE= tm-arm.h
diff --git a/gdb/config/bigmips.mh b/gdb/config/bigmips.mh
new file mode 100644 (file)
index 0000000..1b1cd48
--- /dev/null
@@ -0,0 +1,21 @@
+# Big-endian MIPS machine such as Sony News
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o mips-xdep.o coredep.o
+XM_FILE= xm-bigmips.h
diff --git a/gdb/config/bigmips.mt b/gdb/config/bigmips.mt
new file mode 100644 (file)
index 0000000..0e594d8
--- /dev/null
@@ -0,0 +1,21 @@
+# Big-endian MIPS machine such as Sony News
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= mips-pinsn.o mips-tdep.o mipsread.o exec.o
+TM_FILE= tm-bigmips.h
diff --git a/gdb/config/convex.mh b/gdb/config/convex.mh
new file mode 100644 (file)
index 0000000..b681f28
--- /dev/null
@@ -0,0 +1,21 @@
+# Convex Unix (4bsd)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= convex-xdep.o
+XM_FILE= xm-convex.h
diff --git a/gdb/config/convex.mt b/gdb/config/convex.mt
new file mode 100644 (file)
index 0000000..f7938a2
--- /dev/null
@@ -0,0 +1,21 @@
+# Convex Unix (4bsd)
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= convex-tdep.o convex-pinsn.o
+TM_FILE= tm-convex.h
diff --git a/gdb/config/hp300bsd.mh b/gdb/config/hp300bsd.mh
new file mode 100644 (file)
index 0000000..ae3bb82
--- /dev/null
@@ -0,0 +1,21 @@
+# Hewlett-Packard 9000 series 300, running BSD
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-hp300bsd.h
diff --git a/gdb/config/hp300bsd.mt b/gdb/config/hp300bsd.mt
new file mode 100644 (file)
index 0000000..ea03374
--- /dev/null
@@ -0,0 +1,21 @@
+# Hewlett-Packard 9000 series 300, running BSD
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-hp300bsd.h
diff --git a/gdb/config/hp300hpux.mh b/gdb/config/hp300hpux.mh
new file mode 100644 (file)
index 0000000..3488ef0
--- /dev/null
@@ -0,0 +1,33 @@
+# Hewlett-Packard 9000 series 300, running HPUX
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The following is true because gcc uses a different .o file format
+# than the native HPUX compiler
+#msg If you compile GDB with GCC on HPUX, you must make sure
+#msg that the `nm' used in `munch' is GNU nm
+#msg
+
+# The headers in the directory hp-include override system headers
+# and tell GDB to use BSD executable file format (hence -Ihp-include)
+XDEPFILES= infptrace.o hp300hpux-xdep.o
+XM_FILE= xm-hp300hpux.h
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
+ALLOCA=alloca.o
diff --git a/gdb/config/hp300hpux.mt b/gdb/config/hp300hpux.mt
new file mode 100644 (file)
index 0000000..cee6ba7
--- /dev/null
@@ -0,0 +1,28 @@
+# Hewlett-Packard 9000 series 300, running HPUX
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Note that GDB only can read symbols from programs that were
+#msg compiled with GCC
+#msg
+
+# The headers in the directory hp-include override system headers
+# and tell GDB to use BSD executable file format (hence -Ihp-include)
+TM_CFLAGS=-Ihp-include
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-hp300hpux.h
diff --git a/gdb/config/i386v-g.mh b/gdb/config/i386v-g.mh
new file mode 100644 (file)
index 0000000..a14a85e
--- /dev/null
@@ -0,0 +1,25 @@
+# Intel 386 running System V, using COFF encapsulation
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
diff --git a/gdb/config/i386v-g.mt b/gdb/config/i386v-g.mt
new file mode 100644 (file)
index 0000000..b93b9ce
--- /dev/null
@@ -0,0 +1,25 @@
+# Intel 386 running System V, using COFF encapsulation
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the COFF encapsulation features requires the GNU binary utilities
+#msg to be ahead of their System V counterparts in your path.
+#msg
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v-g.h
diff --git a/gdb/config/i386v.mh b/gdb/config/i386v.mh
new file mode 100644 (file)
index 0000000..c65cd37
--- /dev/null
@@ -0,0 +1,25 @@
+# Intel 386 running System V
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
diff --git a/gdb/config/i386v.mt b/gdb/config/i386v.mt
new file mode 100644 (file)
index 0000000..14d9b59
--- /dev/null
@@ -0,0 +1,21 @@
+# Intel 386 running System V
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v.h
diff --git a/gdb/config/i386v32-g.mh b/gdb/config/i386v32-g.mh
new file mode 100644 (file)
index 0000000..4dfb1a4
--- /dev/null
@@ -0,0 +1,25 @@
+# Intel 386 running System V release 2, using COFF encapsulation
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v32.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
diff --git a/gdb/config/i386v32-g.mt b/gdb/config/i386v32-g.mt
new file mode 100644 (file)
index 0000000..2432551
--- /dev/null
@@ -0,0 +1,24 @@
+# Intel 386 running System V release 2, using COFF encapsulation
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the COFF encapsulation features requires the GNU binary utilities
+#msg to be ahead of their System V counterparts in your path.
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v-g.h
diff --git a/gdb/config/i386v32.mh b/gdb/config/i386v32.mh
new file mode 100644 (file)
index 0000000..c184745
--- /dev/null
@@ -0,0 +1,25 @@
+# Intel 386 running System V release 2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v32.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
diff --git a/gdb/config/i386v32.mt b/gdb/config/i386v32.mt
new file mode 100644 (file)
index 0000000..5cca19d
--- /dev/null
@@ -0,0 +1,21 @@
+# Intel 386 running System V release 2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v.h
diff --git a/gdb/config/i960.mt b/gdb/config/i960.mt
new file mode 100644 (file)
index 0000000..d92b73e
--- /dev/null
@@ -0,0 +1,23 @@
+# Intel 80960, under NINDY or under VxWorks, selected at runtime.
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg
+#msg You must specify either "nindy960" or "vxworks960"; there is no
+#msg generic i960 target any more.
+#msg
diff --git a/gdb/config/isi.mh b/gdb/config/isi.mh
new file mode 100644 (file)
index 0000000..1ae1c7a
--- /dev/null
@@ -0,0 +1,21 @@
+# ISI Optimum V (3.05) under 4.3bsd.
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-isi.h
diff --git a/gdb/config/isi.mt b/gdb/config/isi.mt
new file mode 100644 (file)
index 0000000..aab33e1
--- /dev/null
@@ -0,0 +1,21 @@
+# ISI Optimum V (3.05) under 4.3bsd.
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-isi.h
diff --git a/gdb/config/littlemips.mh b/gdb/config/littlemips.mh
new file mode 100644 (file)
index 0000000..2d4298c
--- /dev/null
@@ -0,0 +1,21 @@
+# Little-endian MIPS machine such as DECstation.
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o mips-xdep.o coredep.o
+XM_FILE= xm-mips.h
diff --git a/gdb/config/littlemips.mt b/gdb/config/littlemips.mt
new file mode 100644 (file)
index 0000000..709bc57
--- /dev/null
@@ -0,0 +1,21 @@
+# Little-endian MIPS machine such as DECstation.
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= mips-pinsn.o mips-tdep.o mipsread.o exec.o
+TM_FILE= tm-mips.h
diff --git a/gdb/config/m88k.mh b/gdb/config/m88k.mh
new file mode 100644 (file)
index 0000000..a703d1a
--- /dev/null
@@ -0,0 +1,21 @@
+# Motorola 88000 running DGUX
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= 
+XM_FILE= xm-88k.h
diff --git a/gdb/config/m88k.mt b/gdb/config/m88k.mt
new file mode 100644 (file)
index 0000000..f3b67dc
--- /dev/null
@@ -0,0 +1,23 @@
+# Motorola 88000 running DGUX
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= tdesc.o
+TM_CLIBS= tdesc/libdc.o
+TM_CDEPS= tdesc/libdc.o
+TM_FILE= tm-88k.h
diff --git a/gdb/config/merlin.mh b/gdb/config/merlin.mh
new file mode 100644 (file)
index 0000000..ecb8cf9
--- /dev/null
@@ -0,0 +1,24 @@
+# Merlin running utek 2.1
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-merlin.h
+# See SHELL_FILE in m-merlin.h for a explanation of this.
+M_INSTALL=cp /bin/sh /usr/local/lib/gdb-sh; \
+chmod ogu+rw /usr/local/lib/gdb-sh
diff --git a/gdb/config/merlin.mt b/gdb/config/merlin.mt
new file mode 100644 (file)
index 0000000..1ed8caa
--- /dev/null
@@ -0,0 +1,21 @@
+# Merlin running utek 2.1
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o ns32k-pinsn.o
+TM_FILE= tm-merlin.h
diff --git a/gdb/config/mh-vax b/gdb/config/mh-vax
new file mode 100755 (executable)
index 0000000..8dbb707
--- /dev/null
@@ -0,0 +1,28 @@
+# DEC VAX running BSD or Ultrix
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The following types of /bin/cc failures have been observed:
+# 1.  Something in readline.c which I have never seen
+# 2.  ``"values.c", line 816: compiler error: schain botch''
+#msg /bin/cc has been known to fail on VAXen running BSD4.3
+#msg If this occurs, use gcc
+#msg  (but see comments in Makefile.dist about compiling with gcc).
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-vax.h
diff --git a/gdb/config/news.mh b/gdb/config/news.mh
new file mode 100644 (file)
index 0000000..1bb7765
--- /dev/null
@@ -0,0 +1,21 @@
+# Sony news series 700/800/900 (68020) running NewsOS version 3.
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o news-xdep.o
+XM_FILE= xm-news.h
diff --git a/gdb/config/news.mt b/gdb/config/news.mt
new file mode 100644 (file)
index 0000000..c26465a
--- /dev/null
@@ -0,0 +1,21 @@
+# Sony news series 700/800/900 (68020) running NewsOS version 3.
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-news.h
diff --git a/gdb/config/news1000.mh b/gdb/config/news1000.mh
new file mode 100644 (file)
index 0000000..940aaee
--- /dev/null
@@ -0,0 +1,21 @@
+# Sony news series 1000 (68030) running NewsOS version 3.
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o news-xdep.o
+XM_FILE= xm-news1000.h
diff --git a/gdb/config/news1000.mt b/gdb/config/news1000.mt
new file mode 100644 (file)
index 0000000..d390504
--- /dev/null
@@ -0,0 +1,21 @@
+# Sony news series 1000 (68030) running NewsOS version 3.
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-news.h
diff --git a/gdb/config/nindy960.mt b/gdb/config/nindy960.mt
new file mode 100644 (file)
index 0000000..f7dc6f7
--- /dev/null
@@ -0,0 +1,22 @@
+# Intel 80960, in an embedded system under the NINDY monitor
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i960-pinsn.o i960-tdep.o nindy-tdep.o remote-nindy.o nindy.o Onindy.o ttybreak.o ttyflush.o
+TM_FILE= tm-nindy960.h
+TM_CFLAGS=
diff --git a/gdb/config/none.mh b/gdb/config/none.mh
new file mode 100644 (file)
index 0000000..74e7048
--- /dev/null
@@ -0,0 +1,21 @@
+# Target config file for "no target".  This can be used to build you
+# a Makefile that only runs administrative commands like 'clean',
+# 'gdb.tar.Z', etc.
+#
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
diff --git a/gdb/config/none.mt b/gdb/config/none.mt
new file mode 100644 (file)
index 0000000..c6b5db9
--- /dev/null
@@ -0,0 +1,3 @@
+# "no target".
+# This can be used to build you a Makefile that only runs administrative
+# commands like 'clean', 'gdb.tar.Z', etc.
diff --git a/gdb/config/np1.mh b/gdb/config/np1.mh
new file mode 100644 (file)
index 0000000..fcf88f2
--- /dev/null
@@ -0,0 +1,21 @@
+# Gould NP1
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o gould-xdep.o
+XM_FILE= xm-np1.h
diff --git a/gdb/config/np1.mt b/gdb/config/np1.mt
new file mode 100644 (file)
index 0000000..4fafd7b
--- /dev/null
@@ -0,0 +1,21 @@
+# Gould NP1
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o gould-pinsn.o
+TM_FILE= tm-np1.h
diff --git a/gdb/config/pn.mh b/gdb/config/pn.mh
new file mode 100644 (file)
index 0000000..7e8f807
--- /dev/null
@@ -0,0 +1,21 @@
+# Gould Powernode
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-pn.h
diff --git a/gdb/config/pn.mt b/gdb/config/pn.mt
new file mode 100644 (file)
index 0000000..ad26b9c
--- /dev/null
@@ -0,0 +1,21 @@
+# Gould Powernode
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o gould-pinsn.o
+TM_FILE= tm-pn.h
diff --git a/gdb/config/pyramid.mh b/gdb/config/pyramid.mh
new file mode 100644 (file)
index 0000000..59561ec
--- /dev/null
@@ -0,0 +1,25 @@
+# Pyramidax under OSx 4.0 (4.2bsd).
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg If you don't compile GDB with GCC, you'll need to add
+#msg ALLOCA=alloca.o and ALLOCA1=alloca.o to the Makefile.
+#msg 
+
+XDEPFILES= pyr-xdep.o infptrace.o
+XM_FILE= xm-pyr.h
diff --git a/gdb/config/pyramid.mt b/gdb/config/pyramid.mt
new file mode 100644 (file)
index 0000000..d62e88e
--- /dev/null
@@ -0,0 +1,25 @@
+# Pyramid under OSx 4.0 (4.2bsd).
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Note that GDB on Pyramids only works with GCC,
+#msg at least for some programs.
+#msg
+
+TDEPFILES= pyr-pinsn.o pyr-tdep.o exec.o
+TM_FILE= tm-pyr.h
diff --git a/gdb/config/sun2os3.mh b/gdb/config/sun2os3.mh
new file mode 100644 (file)
index 0000000..87f8130
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 2, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun2.h
diff --git a/gdb/config/sun2os3.mt b/gdb/config/sun2os3.mt
new file mode 100644 (file)
index 0000000..99dc7f7
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 2, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o m68k-pinsn.o m68k-tdep.o
+TM_FILE= tm-sun2.h
diff --git a/gdb/config/sun2os4.mh b/gdb/config/sun2os4.mh
new file mode 100644 (file)
index 0000000..f525cf6
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 2, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun2.h
diff --git a/gdb/config/sun2os4.mt b/gdb/config/sun2os4.mt
new file mode 100644 (file)
index 0000000..d70dd81
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 2, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o m68k-pinsn.o solib.o m68k-tdep.o
+TM_FILE= tm-sun2os4.h
diff --git a/gdb/config/sun3.mh b/gdb/config/sun3.mh
new file mode 100644 (file)
index 0000000..6a91b49
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 3, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun3os4.h
diff --git a/gdb/config/sun3.mt b/gdb/config/sun3.mt
new file mode 100644 (file)
index 0000000..ae6e351
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 3, running SunOS 4, as a target system
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o solib.o m68k-tdep.o
+TM_FILE= tm-sun3os4.h
diff --git a/gdb/config/sun386.mh b/gdb/config/sun386.mh
new file mode 100644 (file)
index 0000000..a2cb431
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 386i
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun386-xdep.o
+XM_FILE= xm-sun386.h
diff --git a/gdb/config/sun386.mt b/gdb/config/sun386.mt
new file mode 100644 (file)
index 0000000..1a0bca5
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 386i target configuration file.
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i386-pinsn.o solib.o
+TM_FILE= tm-sun386.h
diff --git a/gdb/config/sun3os3.mh b/gdb/config/sun3os3.mh
new file mode 100644 (file)
index 0000000..4408552
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 3, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun3.h
diff --git a/gdb/config/sun3os3.mt b/gdb/config/sun3os3.mt
new file mode 100644 (file)
index 0000000..3eea3bf
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 3, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o m68k-pinsn.o m68k-tdep.o
+TM_FILE= tm-sun3.h
diff --git a/gdb/config/sun3os4.mh b/gdb/config/sun3os4.mh
new file mode 100644 (file)
index 0000000..6a91b49
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 3, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun3os4.h
diff --git a/gdb/config/sun3os4.mt b/gdb/config/sun3os4.mt
new file mode 100644 (file)
index 0000000..ae6e351
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 3, running SunOS 4, as a target system
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o solib.o m68k-tdep.o
+TM_FILE= tm-sun3os4.h
diff --git a/gdb/config/sun4.mh b/gdb/config/sun4.mh
new file mode 100644 (file)
index 0000000..8054271
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sparc-xdep.o
+XM_FILE= xm-sun4os4.h
diff --git a/gdb/config/sun4.mt b/gdb/config/sun4.mt
new file mode 100644 (file)
index 0000000..030872d
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o sparc-tdep.o sparc-pinsn.o solib.o
+TM_FILE= tm-sun4os4.h
diff --git a/gdb/config/sun4os3.mh b/gdb/config/sun4os3.mh
new file mode 100644 (file)
index 0000000..fdb0ddd
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 4 or Sparcstation, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sparc-xdep.o
+XM_FILE= xm-sparc.h
diff --git a/gdb/config/sun4os3.mt b/gdb/config/sun4os3.mt
new file mode 100644 (file)
index 0000000..b90a65c
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 4 or Sparcstation, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o sparc-tdep.o sparc-pinsn.o
+TM_FILE= tm-sparc.h
diff --git a/gdb/config/sun4os4.mh b/gdb/config/sun4os4.mh
new file mode 100644 (file)
index 0000000..8054271
--- /dev/null
@@ -0,0 +1,21 @@
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sparc-xdep.o
+XM_FILE= xm-sun4os4.h
diff --git a/gdb/config/sun4os4.mt b/gdb/config/sun4os4.mt
new file mode 100644 (file)
index 0000000..030872d
--- /dev/null
@@ -0,0 +1,26 @@
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o sparc-tdep.o sparc-pinsn.o solib.o
+TM_FILE= tm-sun4os4.h
diff --git a/gdb/config/symmetry.mh b/gdb/config/symmetry.mh
new file mode 100644 (file)
index 0000000..514c527
--- /dev/null
@@ -0,0 +1,21 @@
+# Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o symmetry-xdep.o
+XM_FILE= xm-symmetry.h
diff --git a/gdb/config/symmetry.mt b/gdb/config/symmetry.mt
new file mode 100644 (file)
index 0000000..4f2f37b
--- /dev/null
@@ -0,0 +1,21 @@
+# Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= symmetry-tdep.o i386-pinsn.o
+TM_FILE= tm-symmetry.h
diff --git a/gdb/config/umax.mh b/gdb/config/umax.mh
new file mode 100644 (file)
index 0000000..34e74d5
--- /dev/null
@@ -0,0 +1,21 @@
+# Encore running umax 4.2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o umax-xdep.o
+XM_FILE= xm-umax.h
diff --git a/gdb/config/umax.mt b/gdb/config/umax.mt
new file mode 100644 (file)
index 0000000..994da6d
--- /dev/null
@@ -0,0 +1,21 @@
+# Encore running umax 4.2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o ns32k-pinsn.o
+TM_FILE= tm-umax.h
diff --git a/gdb/config/vax.mt b/gdb/config/vax.mt
new file mode 100644 (file)
index 0000000..a8e749a
--- /dev/null
@@ -0,0 +1,21 @@
+# DEC VAX running BSD or Ultrix
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= vax-pinsn.o exec.o
+TM_FILE= tm-vax.h
diff --git a/gdb/config/vxworks68.mt b/gdb/config/vxworks68.mt
new file mode 100644 (file)
index 0000000..1514c0e
--- /dev/null
@@ -0,0 +1,21 @@
+# VxWorks running on a 68000, as a target system
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o m68k-tdep.o remote-vx.o xdr_ld.o xdr_ptrace.o xdr_rdb.o xdr_regs.o
+TM_FILE= tm-vxworks68.h
diff --git a/gdb/config/vxworks960.mt b/gdb/config/vxworks960.mt
new file mode 100644 (file)
index 0000000..1cc95e0
--- /dev/null
@@ -0,0 +1,23 @@
+# VxWorks running on an Intel 960, as a target system
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB 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 1, or (at your option)
+# any later version.
+
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i960-pinsn.o i960-tdep.o remote-vx.o xdr_ld.o xdr_ptrace.o xdr_rdb.o xdr_regs.o
+TM_FILE= tm-vxworks960.h
+# Define this for the vx-share routines, which don't see param.h.
+TM_CFLAGS= -DI80960
diff --git a/gdb/convex-opcode.h b/gdb/convex-opcode.h
new file mode 100755 (executable)
index 0000000..523c874
--- /dev/null
@@ -0,0 +1,1677 @@
+/* Include information for instruction dissasembly on the Convex.
+   Copyright (C) 1989, Free Software Foundation.  
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define xxx 0
+#define rrr 1
+#define rr 2
+#define rxr 3
+#define r 4
+#define nops 5
+#define nr 6
+#define pcrel 7
+#define lr 8
+#define rxl 9
+#define rlr 10
+#define rrl 11
+#define iml 12
+#define imr 13
+#define a1r 14
+#define a1l 15
+#define a2r 16
+#define a2l 17
+#define a3 18
+#define a4 19
+#define a5 20
+#define V 1
+#define S 2
+#define VM 3
+#define A 4
+#define VL 5
+#define VS 6
+#define VLS 7
+#define PSW 8
+/* Prevent an error during "make depend".  */
+#if !defined (PC)
+#define PC 9
+#endif
+#define ITR 10
+#define VV 11
+#define ITSR 12
+#define TOC 13
+#define CIR 14
+#define TTR 15
+#define VMU 16
+#define VML 17
+#define ICR 18
+#define TCPU 19
+#define CPUID 20
+#define TID 21
+char *op[] = {
+  "",
+  "v0\0v1\0v2\0v3\0v4\0v5\0v6\0v7",
+  "s0\0s1\0s2\0s3\0s4\0s5\0s6\0s7",
+  "vm",
+  "sp\0a1\0a2\0a3\0a4\0a5\0ap\0fp",
+  "vl",
+  "vs",
+  "vls",
+  "psw",
+  "pc",
+  "itr",
+  "vv",
+  "itsr",
+  "toc",
+  "cir",
+  "ttr",
+  "vmu",
+  "vml",
+  "icr",
+  "tcpu",
+  "cpuid",
+  "tid",
+};
+struct formstr format0[] = {
+  {0,0,rrr,V,S,S},     /* mov */
+  {0,0,rrr,S,S,V},     /* mov */
+  {1,1,rrr,V,V,V},     /* merg.t */
+  {2,1,rrr,V,V,V},     /* mask.t */
+  {1,2,rrr,V,S,V},     /* merg.f */
+  {2,2,rrr,V,S,V},     /* mask.f */
+  {1,1,rrr,V,S,V},     /* merg.t */
+  {2,1,rrr,V,S,V},     /* mask.t */
+  {3,3,rrr,V,V,V},     /* mul.s */
+  {3,4,rrr,V,V,V},     /* mul.d */
+  {4,3,rrr,V,V,V},     /* div.s */
+  {4,4,rrr,V,V,V},     /* div.d */
+  {3,3,rrr,V,S,V},     /* mul.s */
+  {3,4,rrr,V,S,V},     /* mul.d */
+  {4,3,rrr,V,S,V},     /* div.s */
+  {4,4,rrr,V,S,V},     /* div.d */
+  {5,0,rrr,V,V,V},     /* and */
+  {6,0,rrr,V,V,V},     /* or */
+  {7,0,rrr,V,V,V},     /* xor */
+  {8,0,rrr,V,V,V},     /* shf */
+  {5,0,rrr,V,S,V},     /* and */
+  {6,0,rrr,V,S,V},     /* or */
+  {7,0,rrr,V,S,V},     /* xor */
+  {8,0,rrr,V,S,V},     /* shf */
+  {9,3,rrr,V,V,V},     /* add.s */
+  {9,4,rrr,V,V,V},     /* add.d */
+  {10,3,rrr,V,V,V},    /* sub.s */
+  {10,4,rrr,V,V,V},    /* sub.d */
+  {9,3,rrr,V,S,V},     /* add.s */
+  {9,4,rrr,V,S,V},     /* add.d */
+  {10,3,rrr,V,S,V},    /* sub.s */
+  {10,4,rrr,V,S,V},    /* sub.d */
+  {9,5,rrr,V,V,V},     /* add.b */
+  {9,6,rrr,V,V,V},     /* add.h */
+  {9,7,rrr,V,V,V},     /* add.w */
+  {9,8,rrr,V,V,V},     /* add.l */
+  {9,5,rrr,V,S,V},     /* add.b */
+  {9,6,rrr,V,S,V},     /* add.h */
+  {9,7,rrr,V,S,V},     /* add.w */
+  {9,8,rrr,V,S,V},     /* add.l */
+  {10,5,rrr,V,V,V},    /* sub.b */
+  {10,6,rrr,V,V,V},    /* sub.h */
+  {10,7,rrr,V,V,V},    /* sub.w */
+  {10,8,rrr,V,V,V},    /* sub.l */
+  {10,5,rrr,V,S,V},    /* sub.b */
+  {10,6,rrr,V,S,V},    /* sub.h */
+  {10,7,rrr,V,S,V},    /* sub.w */
+  {10,8,rrr,V,S,V},    /* sub.l */
+  {3,5,rrr,V,V,V},     /* mul.b */
+  {3,6,rrr,V,V,V},     /* mul.h */
+  {3,7,rrr,V,V,V},     /* mul.w */
+  {3,8,rrr,V,V,V},     /* mul.l */
+  {3,5,rrr,V,S,V},     /* mul.b */
+  {3,6,rrr,V,S,V},     /* mul.h */
+  {3,7,rrr,V,S,V},     /* mul.w */
+  {3,8,rrr,V,S,V},     /* mul.l */
+  {4,5,rrr,V,V,V},     /* div.b */
+  {4,6,rrr,V,V,V},     /* div.h */
+  {4,7,rrr,V,V,V},     /* div.w */
+  {4,8,rrr,V,V,V},     /* div.l */
+  {4,5,rrr,V,S,V},     /* div.b */
+  {4,6,rrr,V,S,V},     /* div.h */
+  {4,7,rrr,V,S,V},     /* div.w */
+  {4,8,rrr,V,S,V},     /* div.l */
+};
+struct formstr format1[] = {
+  {11,0,xxx,0,0,0},    /* exit */
+  {12,0,a3,0,0,0},     /* jmp */
+  {13,2,a3,0,0,0},     /* jmpi.f */
+  {13,1,a3,0,0,0},     /* jmpi.t */
+  {14,2,a3,0,0,0},     /* jmpa.f */
+  {14,1,a3,0,0,0},     /* jmpa.t */
+  {15,2,a3,0,0,0},     /* jmps.f */
+  {15,1,a3,0,0,0},     /* jmps.t */
+  {16,0,a3,0,0,0},     /* tac */
+  {17,0,a1r,A,0,0},    /* ldea */
+  {18,8,a1l,VLS,0,0},  /* ld.l */
+  {18,9,a1l,VM,0,0},   /* ld.x */
+  {19,0,a3,0,0,0},     /* tas */
+  {20,0,a3,0,0,0},     /* pshea */
+  {21,8,a2l,VLS,0,0},  /* st.l */
+  {21,9,a2l,VM,0,0},   /* st.x */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {22,0,a3,0,0,0},     /* call */
+  {23,0,a3,0,0,0},     /* calls */
+  {24,0,a3,0,0,0},     /* callq */
+  {25,0,a1r,A,0,0},    /* pfork */
+  {26,5,a2r,S,0,0},    /* ste.b */
+  {26,6,a2r,S,0,0},    /* ste.h */
+  {26,7,a2r,S,0,0},    /* ste.w */
+  {26,8,a2r,S,0,0},    /* ste.l */
+  {18,5,a1r,A,0,0},    /* ld.b */
+  {18,6,a1r,A,0,0},    /* ld.h */
+  {18,7,a1r,A,0,0},    /* ld.w */
+  {27,7,a1r,A,0,0},    /* incr.w */
+  {21,5,a2r,A,0,0},    /* st.b */
+  {21,6,a2r,A,0,0},    /* st.h */
+  {21,7,a2r,A,0,0},    /* st.w */
+  {27,8,a1r,S,0,0},    /* incr.l */
+  {18,5,a1r,S,0,0},    /* ld.b */
+  {18,6,a1r,S,0,0},    /* ld.h */
+  {18,7,a1r,S,0,0},    /* ld.w */
+  {18,8,a1r,S,0,0},    /* ld.l */
+  {21,5,a2r,S,0,0},    /* st.b */
+  {21,6,a2r,S,0,0},    /* st.h */
+  {21,7,a2r,S,0,0},    /* st.w */
+  {21,8,a2r,S,0,0},    /* st.l */
+  {18,5,a1r,V,0,0},    /* ld.b */
+  {18,6,a1r,V,0,0},    /* ld.h */
+  {18,7,a1r,V,0,0},    /* ld.w */
+  {18,8,a1r,V,0,0},    /* ld.l */
+  {21,5,a2r,V,0,0},    /* st.b */
+  {21,6,a2r,V,0,0},    /* st.h */
+  {21,7,a2r,V,0,0},    /* st.w */
+  {21,8,a2r,V,0,0},    /* st.l */
+};
+struct formstr format2[] = {
+  {28,5,rr,A,A,0},     /* cvtw.b */
+  {28,6,rr,A,A,0},     /* cvtw.h */
+  {29,7,rr,A,A,0},     /* cvtb.w */
+  {30,7,rr,A,A,0},     /* cvth.w */
+  {28,5,rr,S,S,0},     /* cvtw.b */
+  {28,6,rr,S,S,0},     /* cvtw.h */
+  {29,7,rr,S,S,0},     /* cvtb.w */
+  {30,7,rr,S,S,0},     /* cvth.w */
+  {28,3,rr,S,S,0},     /* cvtw.s */
+  {31,7,rr,S,S,0},     /* cvts.w */
+  {32,3,rr,S,S,0},     /* cvtd.s */
+  {31,4,rr,S,S,0},     /* cvts.d */
+  {31,8,rr,S,S,0},     /* cvts.l */
+  {32,8,rr,S,S,0},     /* cvtd.l */
+  {33,3,rr,S,S,0},     /* cvtl.s */
+  {33,4,rr,S,S,0},     /* cvtl.d */
+  {34,0,rr,A,A,0},     /* ldpa */
+  {8,0,nr,A,0,0},      /* shf */
+  {18,6,nr,A,0,0},     /* ld.h */
+  {18,7,nr,A,0,0},     /* ld.w */
+  {33,7,rr,S,S,0},     /* cvtl.w */
+  {28,8,rr,S,S,0},     /* cvtw.l */
+  {35,1,rr,S,S,0},     /* plc.t */
+  {36,0,rr,S,S,0},     /* tzc */
+  {37,6,rr,A,A,0},     /* eq.h */
+  {37,7,rr,A,A,0},     /* eq.w */
+  {37,6,nr,A,0,0},     /* eq.h */
+  {37,7,nr,A,0,0},     /* eq.w */
+  {37,5,rr,S,S,0},     /* eq.b */
+  {37,6,rr,S,S,0},     /* eq.h */
+  {37,7,rr,S,S,0},     /* eq.w */
+  {37,8,rr,S,S,0},     /* eq.l */
+  {38,6,rr,A,A,0},     /* leu.h */
+  {38,7,rr,A,A,0},     /* leu.w */
+  {38,6,nr,A,0,0},     /* leu.h */
+  {38,7,nr,A,0,0},     /* leu.w */
+  {38,5,rr,S,S,0},     /* leu.b */
+  {38,6,rr,S,S,0},     /* leu.h */
+  {38,7,rr,S,S,0},     /* leu.w */
+  {38,8,rr,S,S,0},     /* leu.l */
+  {39,6,rr,A,A,0},     /* ltu.h */
+  {39,7,rr,A,A,0},     /* ltu.w */
+  {39,6,nr,A,0,0},     /* ltu.h */
+  {39,7,nr,A,0,0},     /* ltu.w */
+  {39,5,rr,S,S,0},     /* ltu.b */
+  {39,6,rr,S,S,0},     /* ltu.h */
+  {39,7,rr,S,S,0},     /* ltu.w */
+  {39,8,rr,S,S,0},     /* ltu.l */
+  {40,6,rr,A,A,0},     /* le.h */
+  {40,7,rr,A,A,0},     /* le.w */
+  {40,6,nr,A,0,0},     /* le.h */
+  {40,7,nr,A,0,0},     /* le.w */
+  {40,5,rr,S,S,0},     /* le.b */
+  {40,6,rr,S,S,0},     /* le.h */
+  {40,7,rr,S,S,0},     /* le.w */
+  {40,8,rr,S,S,0},     /* le.l */
+  {41,6,rr,A,A,0},     /* lt.h */
+  {41,7,rr,A,A,0},     /* lt.w */
+  {41,6,nr,A,0,0},     /* lt.h */
+  {41,7,nr,A,0,0},     /* lt.w */
+  {41,5,rr,S,S,0},     /* lt.b */
+  {41,6,rr,S,S,0},     /* lt.h */
+  {41,7,rr,S,S,0},     /* lt.w */
+  {41,8,rr,S,S,0},     /* lt.l */
+  {9,7,rr,S,A,0},      /* add.w */
+  {8,0,rr,A,A,0},      /* shf */
+  {0,0,rr,A,A,0},      /* mov */
+  {0,0,rr,S,A,0},      /* mov */
+  {0,7,rr,S,S,0},      /* mov.w */
+  {8,0,rr,S,S,0},      /* shf */
+  {0,0,rr,S,S,0},      /* mov */
+  {0,0,rr,A,S,0},      /* mov */
+  {5,0,rr,A,A,0},      /* and */
+  {6,0,rr,A,A,0},      /* or */
+  {7,0,rr,A,A,0},      /* xor */
+  {42,0,rr,A,A,0},     /* not */
+  {5,0,rr,S,S,0},      /* and */
+  {6,0,rr,S,S,0},      /* or */
+  {7,0,rr,S,S,0},      /* xor */
+  {42,0,rr,S,S,0},     /* not */
+  {40,3,rr,S,S,0},     /* le.s */
+  {40,4,rr,S,S,0},     /* le.d */
+  {41,3,rr,S,S,0},     /* lt.s */
+  {41,4,rr,S,S,0},     /* lt.d */
+  {9,3,rr,S,S,0},      /* add.s */
+  {9,4,rr,S,S,0},      /* add.d */
+  {10,3,rr,S,S,0},     /* sub.s */
+  {10,4,rr,S,S,0},     /* sub.d */
+  {37,3,rr,S,S,0},     /* eq.s */
+  {37,4,rr,S,S,0},     /* eq.d */
+  {43,6,rr,A,A,0},     /* neg.h */
+  {43,7,rr,A,A,0},     /* neg.w */
+  {3,3,rr,S,S,0},      /* mul.s */
+  {3,4,rr,S,S,0},      /* mul.d */
+  {4,3,rr,S,S,0},      /* div.s */
+  {4,4,rr,S,S,0},      /* div.d */
+  {9,6,rr,A,A,0},      /* add.h */
+  {9,7,rr,A,A,0},      /* add.w */
+  {9,6,nr,A,0,0},      /* add.h */
+  {9,7,nr,A,0,0},      /* add.w */
+  {9,5,rr,S,S,0},      /* add.b */
+  {9,6,rr,S,S,0},      /* add.h */
+  {9,7,rr,S,S,0},      /* add.w */
+  {9,8,rr,S,S,0},      /* add.l */
+  {10,6,rr,A,A,0},     /* sub.h */
+  {10,7,rr,A,A,0},     /* sub.w */
+  {10,6,nr,A,0,0},     /* sub.h */
+  {10,7,nr,A,0,0},     /* sub.w */
+  {10,5,rr,S,S,0},     /* sub.b */
+  {10,6,rr,S,S,0},     /* sub.h */
+  {10,7,rr,S,S,0},     /* sub.w */
+  {10,8,rr,S,S,0},     /* sub.l */
+  {3,6,rr,A,A,0},      /* mul.h */
+  {3,7,rr,A,A,0},      /* mul.w */
+  {3,6,nr,A,0,0},      /* mul.h */
+  {3,7,nr,A,0,0},      /* mul.w */
+  {3,5,rr,S,S,0},      /* mul.b */
+  {3,6,rr,S,S,0},      /* mul.h */
+  {3,7,rr,S,S,0},      /* mul.w */
+  {3,8,rr,S,S,0},      /* mul.l */
+  {4,6,rr,A,A,0},      /* div.h */
+  {4,7,rr,A,A,0},      /* div.w */
+  {4,6,nr,A,0,0},      /* div.h */
+  {4,7,nr,A,0,0},      /* div.w */
+  {4,5,rr,S,S,0},      /* div.b */
+  {4,6,rr,S,S,0},      /* div.h */
+  {4,7,rr,S,S,0},      /* div.w */
+  {4,8,rr,S,S,0},      /* div.l */
+};
+struct formstr format3[] = {
+  {32,3,rr,V,V,0},     /* cvtd.s */
+  {31,4,rr,V,V,0},     /* cvts.d */
+  {33,4,rr,V,V,0},     /* cvtl.d */
+  {32,8,rr,V,V,0},     /* cvtd.l */
+  {0,0,rrl,S,S,VM},    /* mov */
+  {0,0,rlr,S,VM,S},    /* mov */
+  {0,0,0,0,0,0},
+  {44,0,rr,S,S,0},     /* lop */
+  {36,0,rr,V,V,0},     /* tzc */
+  {44,0,rr,V,V,0},     /* lop */
+  {0,0,0,0,0,0},
+  {42,0,rr,V,V,0},     /* not */
+  {8,0,rr,S,V,0},      /* shf */
+  {35,1,rr,V,V,0},     /* plc.t */
+  {45,2,rr,V,V,0},     /* cprs.f */
+  {45,1,rr,V,V,0},     /* cprs.t */
+  {37,3,rr,V,V,0},     /* eq.s */
+  {37,4,rr,V,V,0},     /* eq.d */
+  {43,3,rr,V,V,0},     /* neg.s */
+  {43,4,rr,V,V,0},     /* neg.d */
+  {37,3,rr,S,V,0},     /* eq.s */
+  {37,4,rr,S,V,0},     /* eq.d */
+  {43,3,rr,S,S,0},     /* neg.s */
+  {43,4,rr,S,S,0},     /* neg.d */
+  {40,3,rr,V,V,0},     /* le.s */
+  {40,4,rr,V,V,0},     /* le.d */
+  {41,3,rr,V,V,0},     /* lt.s */
+  {41,4,rr,V,V,0},     /* lt.d */
+  {40,3,rr,S,V,0},     /* le.s */
+  {40,4,rr,S,V,0},     /* le.d */
+  {41,3,rr,S,V,0},     /* lt.s */
+  {41,4,rr,S,V,0},     /* lt.d */
+  {37,5,rr,V,V,0},     /* eq.b */
+  {37,6,rr,V,V,0},     /* eq.h */
+  {37,7,rr,V,V,0},     /* eq.w */
+  {37,8,rr,V,V,0},     /* eq.l */
+  {37,5,rr,S,V,0},     /* eq.b */
+  {37,6,rr,S,V,0},     /* eq.h */
+  {37,7,rr,S,V,0},     /* eq.w */
+  {37,8,rr,S,V,0},     /* eq.l */
+  {40,5,rr,V,V,0},     /* le.b */
+  {40,6,rr,V,V,0},     /* le.h */
+  {40,7,rr,V,V,0},     /* le.w */
+  {40,8,rr,V,V,0},     /* le.l */
+  {40,5,rr,S,V,0},     /* le.b */
+  {40,6,rr,S,V,0},     /* le.h */
+  {40,7,rr,S,V,0},     /* le.w */
+  {40,8,rr,S,V,0},     /* le.l */
+  {41,5,rr,V,V,0},     /* lt.b */
+  {41,6,rr,V,V,0},     /* lt.h */
+  {41,7,rr,V,V,0},     /* lt.w */
+  {41,8,rr,V,V,0},     /* lt.l */
+  {41,5,rr,S,V,0},     /* lt.b */
+  {41,6,rr,S,V,0},     /* lt.h */
+  {41,7,rr,S,V,0},     /* lt.w */
+  {41,8,rr,S,V,0},     /* lt.l */
+  {43,5,rr,V,V,0},     /* neg.b */
+  {43,6,rr,V,V,0},     /* neg.h */
+  {43,7,rr,V,V,0},     /* neg.w */
+  {43,8,rr,V,V,0},     /* neg.l */
+  {43,5,rr,S,S,0},     /* neg.b */
+  {43,6,rr,S,S,0},     /* neg.h */
+  {43,7,rr,S,S,0},     /* neg.w */
+  {43,8,rr,S,S,0},     /* neg.l */
+};
+struct formstr format4[] = {
+  {46,0,nops,0,0,0},   /* nop */
+  {47,0,pcrel,0,0,0},  /* br */
+  {48,2,pcrel,0,0,0},  /* bri.f */
+  {48,1,pcrel,0,0,0},  /* bri.t */
+  {49,2,pcrel,0,0,0},  /* bra.f */
+  {49,1,pcrel,0,0,0},  /* bra.t */
+  {50,2,pcrel,0,0,0},  /* brs.f */
+  {50,1,pcrel,0,0,0},  /* brs.t */
+};
+struct formstr format5[] = {
+  {51,5,rr,V,V,0},     /* ldvi.b */
+  {51,6,rr,V,V,0},     /* ldvi.h */
+  {51,7,rr,V,V,0},     /* ldvi.w */
+  {51,8,rr,V,V,0},     /* ldvi.l */
+  {28,3,rr,V,V,0},     /* cvtw.s */
+  {31,7,rr,V,V,0},     /* cvts.w */
+  {28,8,rr,V,V,0},     /* cvtw.l */
+  {33,7,rr,V,V,0},     /* cvtl.w */
+  {52,5,rxr,V,V,0},    /* stvi.b */
+  {52,6,rxr,V,V,0},    /* stvi.h */
+  {52,7,rxr,V,V,0},    /* stvi.w */
+  {52,8,rxr,V,V,0},    /* stvi.l */
+  {52,5,rxr,S,V,0},    /* stvi.b */
+  {52,6,rxr,S,V,0},    /* stvi.h */
+  {52,7,rxr,S,V,0},    /* stvi.w */
+  {52,8,rxr,S,V,0},    /* stvi.l */
+};
+struct formstr format6[] = {
+  {53,0,r,A,0,0},      /* ldsdr */
+  {54,0,r,A,0,0},      /* ldkdr */
+  {55,3,r,S,0,0},      /* ln.s */
+  {55,4,r,S,0,0},      /* ln.d */
+  {56,0,nops,0,0,0},   /* patu */
+  {57,0,r,A,0,0},      /* pate */
+  {58,0,nops,0,0,0},   /* pich */
+  {59,0,nops,0,0,0},   /* plch */
+  {0,0,lr,PSW,A,0},    /* mov */
+  {0,0,rxl,A,PSW,0},   /* mov */
+  {0,0,lr,PC,A,0},     /* mov */
+  {60,0,r,S,0,0},      /* idle */
+  {0,0,lr,ITR,S,0},    /* mov */
+  {0,0,rxl,S,ITR,0},   /* mov */
+  {0,0,0,0,0,0},
+  {0,0,rxl,S,ITSR,0},  /* mov */
+  {61,0,nops,0,0,0},   /* rtnq */
+  {62,0,nops,0,0,0},   /* cfork */
+  {63,0,nops,0,0,0},   /* rtn */
+  {64,0,nops,0,0,0},   /* wfork */
+  {65,0,nops,0,0,0},   /* join */
+  {66,0,nops,0,0,0},   /* rtnc */
+  {67,3,r,S,0,0},      /* exp.s */
+  {67,4,r,S,0,0},      /* exp.d */
+  {68,3,r,S,0,0},      /* sin.s */
+  {68,4,r,S,0,0},      /* sin.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {69,3,r,S,0,0},      /* cos.s */
+  {69,4,r,S,0,0},      /* cos.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {70,7,r,A,0,0},      /* psh.w */
+  {0,0,0,0,0,0},
+  {71,7,r,A,0,0},      /* pop.w */
+  {0,0,0,0,0,0},
+  {70,7,r,S,0,0},      /* psh.w */
+  {70,8,r,S,0,0},      /* psh.l */
+  {71,7,r,S,0,0},      /* pop.w */
+  {71,8,r,S,0,0},      /* pop.l */
+  {72,0,nops,0,0,0},   /* eni */
+  {73,0,nops,0,0,0},   /* dsi */
+  {74,0,nops,0,0,0},   /* bkpt */
+  {75,0,nops,0,0,0},   /* msync */
+  {76,0,r,S,0,0},      /* mski */
+  {77,0,r,S,0,0},      /* xmti */
+  {0,0,rxl,S,VV,0},    /* mov */
+  {78,0,nops,0,0,0},   /* tstvv */
+  {0,0,lr,VS,A,0},     /* mov */
+  {0,0,rxl,A,VS,0},    /* mov */
+  {0,0,lr,VL,A,0},     /* mov */
+  {0,0,rxl,A,VL,0},    /* mov */
+  {0,7,lr,VS,S,0},     /* mov.w */
+  {0,7,rxl,S,VS,0},    /* mov.w */
+  {0,7,lr,VL,S,0},     /* mov.w */
+  {0,7,rxl,S,VL,0},    /* mov.w */
+  {79,0,r,A,0,0},      /* diag */
+  {80,0,nops,0,0,0},   /* pbkpt */
+  {81,3,r,S,0,0},      /* sqrt.s */
+  {81,4,r,S,0,0},      /* sqrt.d */
+  {82,0,nops,0,0,0},   /* casr */
+  {0,0,0,0,0,0},
+  {83,3,r,S,0,0},      /* atan.s */
+  {83,4,r,S,0,0},      /* atan.d */
+};
+struct formstr format7[] = {
+  {84,5,r,V,0,0},      /* sum.b */
+  {84,6,r,V,0,0},      /* sum.h */
+  {84,7,r,V,0,0},      /* sum.w */
+  {84,8,r,V,0,0},      /* sum.l */
+  {85,0,r,V,0,0},      /* all */
+  {86,0,r,V,0,0},      /* any */
+  {87,0,r,V,0,0},      /* parity */
+  {0,0,0,0,0,0},
+  {88,5,r,V,0,0},      /* max.b */
+  {88,6,r,V,0,0},      /* max.h */
+  {88,7,r,V,0,0},      /* max.w */
+  {88,8,r,V,0,0},      /* max.l */
+  {89,5,r,V,0,0},      /* min.b */
+  {89,6,r,V,0,0},      /* min.h */
+  {89,7,r,V,0,0},      /* min.w */
+  {89,8,r,V,0,0},      /* min.l */
+  {84,3,r,V,0,0},      /* sum.s */
+  {84,4,r,V,0,0},      /* sum.d */
+  {90,3,r,V,0,0},      /* prod.s */
+  {90,4,r,V,0,0},      /* prod.d */
+  {88,3,r,V,0,0},      /* max.s */
+  {88,4,r,V,0,0},      /* max.d */
+  {89,3,r,V,0,0},      /* min.s */
+  {89,4,r,V,0,0},      /* min.d */
+  {90,5,r,V,0,0},      /* prod.b */
+  {90,6,r,V,0,0},      /* prod.h */
+  {90,7,r,V,0,0},      /* prod.w */
+  {90,8,r,V,0,0},      /* prod.l */
+  {35,2,lr,VM,S,0},    /* plc.f */
+  {35,1,lr,VM,S,0},    /* plc.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr formatx[] = {
+  {0,0,0,0,0,0},
+};
+struct formstr format1a[] = {
+  {91,0,imr,A,0,0},    /* halt */
+  {92,0,a4,0,0,0},     /* sysc */
+  {18,6,imr,A,0,0},    /* ld.h */
+  {18,7,imr,A,0,0},    /* ld.w */
+  {5,0,imr,A,0,0},     /* and */
+  {6,0,imr,A,0,0},     /* or */
+  {7,0,imr,A,0,0},     /* xor */
+  {8,0,imr,A,0,0},     /* shf */
+  {9,6,imr,A,0,0},     /* add.h */
+  {9,7,imr,A,0,0},     /* add.w */
+  {10,6,imr,A,0,0},    /* sub.h */
+  {10,7,imr,A,0,0},    /* sub.w */
+  {3,6,imr,A,0,0},     /* mul.h */
+  {3,7,imr,A,0,0},     /* mul.w */
+  {4,6,imr,A,0,0},     /* div.h */
+  {4,7,imr,A,0,0},     /* div.w */
+  {18,7,iml,VL,0,0},   /* ld.w */
+  {18,7,iml,VS,0,0},   /* ld.w */
+  {0,0,0,0,0,0},
+  {8,7,imr,S,0,0},     /* shf.w */
+  {93,0,a5,0,0,0},     /* trap */
+  {0,0,0,0,0,0},
+  {37,6,imr,A,0,0},    /* eq.h */
+  {37,7,imr,A,0,0},    /* eq.w */
+  {38,6,imr,A,0,0},    /* leu.h */
+  {38,7,imr,A,0,0},    /* leu.w */
+  {39,6,imr,A,0,0},    /* ltu.h */
+  {39,7,imr,A,0,0},    /* ltu.w */
+  {40,6,imr,A,0,0},    /* le.h */
+  {40,7,imr,A,0,0},    /* le.w */
+  {41,6,imr,A,0,0},    /* lt.h */
+  {41,7,imr,A,0,0},    /* lt.w */
+};
+struct formstr format1b[] = {
+  {18,4,imr,S,0,0},    /* ld.d */
+  {18,10,imr,S,0,0},   /* ld.u */
+  {18,8,imr,S,0,0},    /* ld.l */
+  {18,7,imr,S,0,0},    /* ld.w */
+  {5,0,imr,S,0,0},     /* and */
+  {6,0,imr,S,0,0},     /* or */
+  {7,0,imr,S,0,0},     /* xor */
+  {8,0,imr,S,0,0},     /* shf */
+  {9,6,imr,S,0,0},     /* add.h */
+  {9,7,imr,S,0,0},     /* add.w */
+  {10,6,imr,S,0,0},    /* sub.h */
+  {10,7,imr,S,0,0},    /* sub.w */
+  {3,6,imr,S,0,0},     /* mul.h */
+  {3,7,imr,S,0,0},     /* mul.w */
+  {4,6,imr,S,0,0},     /* div.h */
+  {4,7,imr,S,0,0},     /* div.w */
+  {9,3,imr,S,0,0},     /* add.s */
+  {10,3,imr,S,0,0},    /* sub.s */
+  {3,3,imr,S,0,0},     /* mul.s */
+  {4,3,imr,S,0,0},     /* div.s */
+  {40,3,imr,S,0,0},    /* le.s */
+  {41,3,imr,S,0,0},    /* lt.s */
+  {37,6,imr,S,0,0},    /* eq.h */
+  {37,7,imr,S,0,0},    /* eq.w */
+  {38,6,imr,S,0,0},    /* leu.h */
+  {38,7,imr,S,0,0},    /* leu.w */
+  {39,6,imr,S,0,0},    /* ltu.h */
+  {39,7,imr,S,0,0},    /* ltu.w */
+  {40,6,imr,S,0,0},    /* le.h */
+  {40,7,imr,S,0,0},    /* le.w */
+  {41,6,imr,S,0,0},    /* lt.h */
+  {41,7,imr,S,0,0},    /* lt.w */
+};
+struct formstr e0_format0[] = {
+  {10,3,rrr,S,V,V},    /* sub.s */
+  {10,4,rrr,S,V,V},    /* sub.d */
+  {4,3,rrr,S,V,V},     /* div.s */
+  {4,4,rrr,S,V,V},     /* div.d */
+  {10,11,rrr,S,V,V},   /* sub.s.f */
+  {10,12,rrr,S,V,V},   /* sub.d.f */
+  {4,11,rrr,S,V,V},    /* div.s.f */
+  {4,12,rrr,S,V,V},    /* div.d.f */
+  {3,11,rrr,V,V,V},    /* mul.s.f */
+  {3,12,rrr,V,V,V},    /* mul.d.f */
+  {4,11,rrr,V,V,V},    /* div.s.f */
+  {4,12,rrr,V,V,V},    /* div.d.f */
+  {3,11,rrr,V,S,V},    /* mul.s.f */
+  {3,12,rrr,V,S,V},    /* mul.d.f */
+  {4,11,rrr,V,S,V},    /* div.s.f */
+  {4,12,rrr,V,S,V},    /* div.d.f */
+  {5,2,rrr,V,V,V},     /* and.f */
+  {6,2,rrr,V,V,V},     /* or.f */
+  {7,2,rrr,V,V,V},     /* xor.f */
+  {8,2,rrr,V,V,V},     /* shf.f */
+  {5,2,rrr,V,S,V},     /* and.f */
+  {6,2,rrr,V,S,V},     /* or.f */
+  {7,2,rrr,V,S,V},     /* xor.f */
+  {8,2,rrr,V,S,V},     /* shf.f */
+  {9,11,rrr,V,V,V},    /* add.s.f */
+  {9,12,rrr,V,V,V},    /* add.d.f */
+  {10,11,rrr,V,V,V},   /* sub.s.f */
+  {10,12,rrr,V,V,V},   /* sub.d.f */
+  {9,11,rrr,V,S,V},    /* add.s.f */
+  {9,12,rrr,V,S,V},    /* add.d.f */
+  {10,11,rrr,V,S,V},   /* sub.s.f */
+  {10,12,rrr,V,S,V},   /* sub.d.f */
+  {9,13,rrr,V,V,V},    /* add.b.f */
+  {9,14,rrr,V,V,V},    /* add.h.f */
+  {9,15,rrr,V,V,V},    /* add.w.f */
+  {9,16,rrr,V,V,V},    /* add.l.f */
+  {9,13,rrr,V,S,V},    /* add.b.f */
+  {9,14,rrr,V,S,V},    /* add.h.f */
+  {9,15,rrr,V,S,V},    /* add.w.f */
+  {9,16,rrr,V,S,V},    /* add.l.f */
+  {10,13,rrr,V,V,V},   /* sub.b.f */
+  {10,14,rrr,V,V,V},   /* sub.h.f */
+  {10,15,rrr,V,V,V},   /* sub.w.f */
+  {10,16,rrr,V,V,V},   /* sub.l.f */
+  {10,13,rrr,V,S,V},   /* sub.b.f */
+  {10,14,rrr,V,S,V},   /* sub.h.f */
+  {10,15,rrr,V,S,V},   /* sub.w.f */
+  {10,16,rrr,V,S,V},   /* sub.l.f */
+  {3,13,rrr,V,V,V},    /* mul.b.f */
+  {3,14,rrr,V,V,V},    /* mul.h.f */
+  {3,15,rrr,V,V,V},    /* mul.w.f */
+  {3,16,rrr,V,V,V},    /* mul.l.f */
+  {3,13,rrr,V,S,V},    /* mul.b.f */
+  {3,14,rrr,V,S,V},    /* mul.h.f */
+  {3,15,rrr,V,S,V},    /* mul.w.f */
+  {3,16,rrr,V,S,V},    /* mul.l.f */
+  {4,13,rrr,V,V,V},    /* div.b.f */
+  {4,14,rrr,V,V,V},    /* div.h.f */
+  {4,15,rrr,V,V,V},    /* div.w.f */
+  {4,16,rrr,V,V,V},    /* div.l.f */
+  {4,13,rrr,V,S,V},    /* div.b.f */
+  {4,14,rrr,V,S,V},    /* div.h.f */
+  {4,15,rrr,V,S,V},    /* div.w.f */
+  {4,16,rrr,V,S,V},    /* div.l.f */
+};
+struct formstr e0_format1[] = {
+  {0,0,0,0,0,0},
+  {94,0,a3,0,0,0},     /* tst */
+  {95,0,a3,0,0,0},     /* lck */
+  {96,0,a3,0,0,0},     /* ulk */
+  {17,0,a1r,S,0,0},    /* ldea */
+  {97,0,a1r,A,0,0},    /* spawn */
+  {98,0,a1r,A,0,0},    /* ldcmr */
+  {99,0,a2r,A,0,0},    /* stcmr */
+  {100,0,a1r,A,0,0},   /* popr */
+  {101,0,a2r,A,0,0},   /* pshr */
+  {102,7,a1r,A,0,0},   /* rcvr.w */
+  {103,7,a2r,A,0,0},   /* matm.w */
+  {104,7,a2r,A,0,0},   /* sndr.w */
+  {104,8,a2r,S,0,0},   /* sndr.l */
+  {102,8,a1r,S,0,0},   /* rcvr.l */
+  {103,8,a2r,S,0,0},   /* matm.l */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {105,7,a2r,A,0,0},   /* putr.w */
+  {105,8,a2r,S,0,0},   /* putr.l */
+  {106,7,a1r,A,0,0},   /* getr.w */
+  {106,8,a1r,S,0,0},   /* getr.l */
+  {26,13,a2r,S,0,0},   /* ste.b.f */
+  {26,14,a2r,S,0,0},   /* ste.h.f */
+  {26,15,a2r,S,0,0},   /* ste.w.f */
+  {26,16,a2r,S,0,0},   /* ste.l.f */
+  {107,7,a2r,A,0,0},   /* matr.w */
+  {108,7,a2r,A,0,0},   /* mat.w */
+  {109,7,a1r,A,0,0},   /* get.w */
+  {110,7,a1r,A,0,0},   /* rcv.w */
+  {0,0,0,0,0,0},
+  {111,7,a1r,A,0,0},   /* inc.w */
+  {112,7,a2r,A,0,0},   /* put.w */
+  {113,7,a2r,A,0,0},   /* snd.w */
+  {107,8,a2r,S,0,0},   /* matr.l */
+  {108,8,a2r,S,0,0},   /* mat.l */
+  {109,8,a1r,S,0,0},   /* get.l */
+  {110,8,a1r,S,0,0},   /* rcv.l */
+  {0,0,0,0,0,0},
+  {111,8,a1r,S,0,0},   /* inc.l */
+  {112,8,a2r,S,0,0},   /* put.l */
+  {113,8,a2r,S,0,0},   /* snd.l */
+  {18,13,a1r,V,0,0},   /* ld.b.f */
+  {18,14,a1r,V,0,0},   /* ld.h.f */
+  {18,15,a1r,V,0,0},   /* ld.w.f */
+  {18,16,a1r,V,0,0},   /* ld.l.f */
+  {21,13,a2r,V,0,0},   /* st.b.f */
+  {21,14,a2r,V,0,0},   /* st.h.f */
+  {21,15,a2r,V,0,0},   /* st.w.f */
+  {21,16,a2r,V,0,0},   /* st.l.f */
+};
+struct formstr e0_format2[] = {
+  {28,5,rr,V,V,0},     /* cvtw.b */
+  {28,6,rr,V,V,0},     /* cvtw.h */
+  {29,7,rr,V,V,0},     /* cvtb.w */
+  {30,7,rr,V,V,0},     /* cvth.w */
+  {28,13,rr,V,V,0},    /* cvtw.b.f */
+  {28,14,rr,V,V,0},    /* cvtw.h.f */
+  {29,15,rr,V,V,0},    /* cvtb.w.f */
+  {30,15,rr,V,V,0},    /* cvth.w.f */
+  {31,8,rr,V,V,0},     /* cvts.l */
+  {32,7,rr,V,V,0},     /* cvtd.w */
+  {33,3,rr,V,V,0},     /* cvtl.s */
+  {28,4,rr,V,V,0},     /* cvtw.d */
+  {31,16,rr,V,V,0},    /* cvts.l.f */
+  {32,15,rr,V,V,0},    /* cvtd.w.f */
+  {33,11,rr,V,V,0},    /* cvtl.s.f */
+  {28,12,rr,V,V,0},    /* cvtw.d.f */
+  {114,0,rr,S,S,0},    /* enal */
+  {8,7,rr,S,S,0},      /* shf.w */
+  {115,0,rr,S,S,0},    /* enag */
+  {0,0,0,0,0,0},
+  {28,4,rr,S,S,0},     /* cvtw.d */
+  {32,7,rr,S,S,0},     /* cvtd.w */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,3,rr,S,S,0},    /* frint.s */
+  {116,4,rr,S,S,0},    /* frint.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,3,rr,V,V,0},    /* frint.s */
+  {116,4,rr,V,V,0},    /* frint.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,11,rr,V,V,0},   /* frint.s.f */
+  {116,12,rr,V,V,0},   /* frint.d.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {81,3,rr,V,V,0},     /* sqrt.s */
+  {81,4,rr,V,V,0},     /* sqrt.d */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {81,11,rr,V,V,0},    /* sqrt.s.f */
+  {81,12,rr,V,V,0},    /* sqrt.d.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format3[] = {
+  {32,11,rr,V,V,0},    /* cvtd.s.f */
+  {31,12,rr,V,V,0},    /* cvts.d.f */
+  {33,12,rr,V,V,0},    /* cvtl.d.f */
+  {32,16,rr,V,V,0},    /* cvtd.l.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {36,2,rr,V,V,0},     /* tzc.f */
+  {44,2,rr,V,V,0},     /* lop.f */
+  {117,2,rr,V,V,0},    /* xpnd.f */
+  {42,2,rr,V,V,0},     /* not.f */
+  {8,2,rr,S,V,0},      /* shf.f */
+  {35,17,rr,V,V,0},    /* plc.t.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {37,11,rr,V,V,0},    /* eq.s.f */
+  {37,12,rr,V,V,0},    /* eq.d.f */
+  {43,11,rr,V,V,0},    /* neg.s.f */
+  {43,12,rr,V,V,0},    /* neg.d.f */
+  {37,11,rr,S,V,0},    /* eq.s.f */
+  {37,12,rr,S,V,0},    /* eq.d.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {40,11,rr,V,V,0},    /* le.s.f */
+  {40,12,rr,V,V,0},    /* le.d.f */
+  {41,11,rr,V,V,0},    /* lt.s.f */
+  {41,12,rr,V,V,0},    /* lt.d.f */
+  {40,11,rr,S,V,0},    /* le.s.f */
+  {40,12,rr,S,V,0},    /* le.d.f */
+  {41,11,rr,S,V,0},    /* lt.s.f */
+  {41,12,rr,S,V,0},    /* lt.d.f */
+  {37,13,rr,V,V,0},    /* eq.b.f */
+  {37,14,rr,V,V,0},    /* eq.h.f */
+  {37,15,rr,V,V,0},    /* eq.w.f */
+  {37,16,rr,V,V,0},    /* eq.l.f */
+  {37,13,rr,S,V,0},    /* eq.b.f */
+  {37,14,rr,S,V,0},    /* eq.h.f */
+  {37,15,rr,S,V,0},    /* eq.w.f */
+  {37,16,rr,S,V,0},    /* eq.l.f */
+  {40,13,rr,V,V,0},    /* le.b.f */
+  {40,14,rr,V,V,0},    /* le.h.f */
+  {40,15,rr,V,V,0},    /* le.w.f */
+  {40,16,rr,V,V,0},    /* le.l.f */
+  {40,13,rr,S,V,0},    /* le.b.f */
+  {40,14,rr,S,V,0},    /* le.h.f */
+  {40,15,rr,S,V,0},    /* le.w.f */
+  {40,16,rr,S,V,0},    /* le.l.f */
+  {41,13,rr,V,V,0},    /* lt.b.f */
+  {41,14,rr,V,V,0},    /* lt.h.f */
+  {41,15,rr,V,V,0},    /* lt.w.f */
+  {41,16,rr,V,V,0},    /* lt.l.f */
+  {41,13,rr,S,V,0},    /* lt.b.f */
+  {41,14,rr,S,V,0},    /* lt.h.f */
+  {41,15,rr,S,V,0},    /* lt.w.f */
+  {41,16,rr,S,V,0},    /* lt.l.f */
+  {43,13,rr,V,V,0},    /* neg.b.f */
+  {43,14,rr,V,V,0},    /* neg.h.f */
+  {43,15,rr,V,V,0},    /* neg.w.f */
+  {43,16,rr,V,V,0},    /* neg.l.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format4[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format5[] = {
+  {51,13,rr,V,V,0},    /* ldvi.b.f */
+  {51,14,rr,V,V,0},    /* ldvi.h.f */
+  {51,15,rr,V,V,0},    /* ldvi.w.f */
+  {51,16,rr,V,V,0},    /* ldvi.l.f */
+  {28,11,rr,V,V,0},    /* cvtw.s.f */
+  {31,15,rr,V,V,0},    /* cvts.w.f */
+  {28,16,rr,V,V,0},    /* cvtw.l.f */
+  {33,15,rr,V,V,0},    /* cvtl.w.f */
+  {52,13,rxr,V,V,0},   /* stvi.b.f */
+  {52,14,rxr,V,V,0},   /* stvi.h.f */
+  {52,15,rxr,V,V,0},   /* stvi.w.f */
+  {52,16,rxr,V,V,0},   /* stvi.l.f */
+  {52,13,rxr,S,V,0},   /* stvi.b.f */
+  {52,14,rxr,S,V,0},   /* stvi.h.f */
+  {52,15,rxr,S,V,0},   /* stvi.w.f */
+  {52,16,rxr,S,V,0},   /* stvi.l.f */
+};
+struct formstr e0_format6[] = {
+  {0,0,rxl,S,CIR,0},   /* mov */
+  {0,0,lr,CIR,S,0},    /* mov */
+  {0,0,lr,TOC,S,0},    /* mov */
+  {0,0,lr,CPUID,S,0},  /* mov */
+  {0,0,rxl,S,TTR,0},   /* mov */
+  {0,0,lr,TTR,S,0},    /* mov */
+  {118,0,nops,0,0,0},  /* ctrsl */
+  {119,0,nops,0,0,0},  /* ctrsg */
+  {0,0,rxl,S,VMU,0},   /* mov */
+  {0,0,lr,VMU,S,0},    /* mov */
+  {0,0,rxl,S,VML,0},   /* mov */
+  {0,0,lr,VML,S,0},    /* mov */
+  {0,0,rxl,S,ICR,0},   /* mov */
+  {0,0,lr,ICR,S,0},    /* mov */
+  {0,0,rxl,S,TCPU,0},  /* mov */
+  {0,0,lr,TCPU,S,0},   /* mov */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {120,0,nops,0,0,0},  /* stop */
+  {0,0,0,0,0,0},
+  {0,0,rxl,S,TID,0},   /* mov */
+  {0,0,lr,TID,S,0},    /* mov */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e0_format7[] = {
+  {84,13,r,V,0,0},     /* sum.b.f */
+  {84,14,r,V,0,0},     /* sum.h.f */
+  {84,15,r,V,0,0},     /* sum.w.f */
+  {84,16,r,V,0,0},     /* sum.l.f */
+  {85,2,r,V,0,0},      /* all.f */
+  {86,2,r,V,0,0},      /* any.f */
+  {87,2,r,V,0,0},      /* parity.f */
+  {0,0,0,0,0,0},
+  {88,13,r,V,0,0},     /* max.b.f */
+  {88,14,r,V,0,0},     /* max.h.f */
+  {88,15,r,V,0,0},     /* max.w.f */
+  {88,16,r,V,0,0},     /* max.l.f */
+  {89,13,r,V,0,0},     /* min.b.f */
+  {89,14,r,V,0,0},     /* min.h.f */
+  {89,15,r,V,0,0},     /* min.w.f */
+  {89,16,r,V,0,0},     /* min.l.f */
+  {84,11,r,V,0,0},     /* sum.s.f */
+  {84,12,r,V,0,0},     /* sum.d.f */
+  {90,11,r,V,0,0},     /* prod.s.f */
+  {90,12,r,V,0,0},     /* prod.d.f */
+  {88,11,r,V,0,0},     /* max.s.f */
+  {88,12,r,V,0,0},     /* max.d.f */
+  {89,11,r,V,0,0},     /* min.s.f */
+  {89,12,r,V,0,0},     /* min.d.f */
+  {90,13,r,V,0,0},     /* prod.b.f */
+  {90,14,r,V,0,0},     /* prod.h.f */
+  {90,15,r,V,0,0},     /* prod.w.f */
+  {90,16,r,V,0,0},     /* prod.l.f */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format0[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {10,18,rrr,S,V,V},   /* sub.s.t */
+  {10,19,rrr,S,V,V},   /* sub.d.t */
+  {4,18,rrr,S,V,V},    /* div.s.t */
+  {4,19,rrr,S,V,V},    /* div.d.t */
+  {3,18,rrr,V,V,V},    /* mul.s.t */
+  {3,19,rrr,V,V,V},    /* mul.d.t */
+  {4,18,rrr,V,V,V},    /* div.s.t */
+  {4,19,rrr,V,V,V},    /* div.d.t */
+  {3,18,rrr,V,S,V},    /* mul.s.t */
+  {3,19,rrr,V,S,V},    /* mul.d.t */
+  {4,18,rrr,V,S,V},    /* div.s.t */
+  {4,19,rrr,V,S,V},    /* div.d.t */
+  {5,1,rrr,V,V,V},     /* and.t */
+  {6,1,rrr,V,V,V},     /* or.t */
+  {7,1,rrr,V,V,V},     /* xor.t */
+  {8,1,rrr,V,V,V},     /* shf.t */
+  {5,1,rrr,V,S,V},     /* and.t */
+  {6,1,rrr,V,S,V},     /* or.t */
+  {7,1,rrr,V,S,V},     /* xor.t */
+  {8,1,rrr,V,S,V},     /* shf.t */
+  {9,18,rrr,V,V,V},    /* add.s.t */
+  {9,19,rrr,V,V,V},    /* add.d.t */
+  {10,18,rrr,V,V,V},   /* sub.s.t */
+  {10,19,rrr,V,V,V},   /* sub.d.t */
+  {9,18,rrr,V,S,V},    /* add.s.t */
+  {9,19,rrr,V,S,V},    /* add.d.t */
+  {10,18,rrr,V,S,V},   /* sub.s.t */
+  {10,19,rrr,V,S,V},   /* sub.d.t */
+  {9,20,rrr,V,V,V},    /* add.b.t */
+  {9,21,rrr,V,V,V},    /* add.h.t */
+  {9,22,rrr,V,V,V},    /* add.w.t */
+  {9,23,rrr,V,V,V},    /* add.l.t */
+  {9,20,rrr,V,S,V},    /* add.b.t */
+  {9,21,rrr,V,S,V},    /* add.h.t */
+  {9,22,rrr,V,S,V},    /* add.w.t */
+  {9,23,rrr,V,S,V},    /* add.l.t */
+  {10,20,rrr,V,V,V},   /* sub.b.t */
+  {10,21,rrr,V,V,V},   /* sub.h.t */
+  {10,22,rrr,V,V,V},   /* sub.w.t */
+  {10,23,rrr,V,V,V},   /* sub.l.t */
+  {10,20,rrr,V,S,V},   /* sub.b.t */
+  {10,21,rrr,V,S,V},   /* sub.h.t */
+  {10,22,rrr,V,S,V},   /* sub.w.t */
+  {10,23,rrr,V,S,V},   /* sub.l.t */
+  {3,20,rrr,V,V,V},    /* mul.b.t */
+  {3,21,rrr,V,V,V},    /* mul.h.t */
+  {3,22,rrr,V,V,V},    /* mul.w.t */
+  {3,23,rrr,V,V,V},    /* mul.l.t */
+  {3,20,rrr,V,S,V},    /* mul.b.t */
+  {3,21,rrr,V,S,V},    /* mul.h.t */
+  {3,22,rrr,V,S,V},    /* mul.w.t */
+  {3,23,rrr,V,S,V},    /* mul.l.t */
+  {4,20,rrr,V,V,V},    /* div.b.t */
+  {4,21,rrr,V,V,V},    /* div.h.t */
+  {4,22,rrr,V,V,V},    /* div.w.t */
+  {4,23,rrr,V,V,V},    /* div.l.t */
+  {4,20,rrr,V,S,V},    /* div.b.t */
+  {4,21,rrr,V,S,V},    /* div.h.t */
+  {4,22,rrr,V,S,V},    /* div.w.t */
+  {4,23,rrr,V,S,V},    /* div.l.t */
+};
+struct formstr e1_format1[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {26,20,a2r,S,0,0},   /* ste.b.t */
+  {26,21,a2r,S,0,0},   /* ste.h.t */
+  {26,22,a2r,S,0,0},   /* ste.w.t */
+  {26,23,a2r,S,0,0},   /* ste.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {18,20,a1r,V,0,0},   /* ld.b.t */
+  {18,21,a1r,V,0,0},   /* ld.h.t */
+  {18,22,a1r,V,0,0},   /* ld.w.t */
+  {18,23,a1r,V,0,0},   /* ld.l.t */
+  {21,20,a2r,V,0,0},   /* st.b.t */
+  {21,21,a2r,V,0,0},   /* st.h.t */
+  {21,22,a2r,V,0,0},   /* st.w.t */
+  {21,23,a2r,V,0,0},   /* st.l.t */
+};
+struct formstr e1_format2[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {28,20,rr,V,V,0},    /* cvtw.b.t */
+  {28,21,rr,V,V,0},    /* cvtw.h.t */
+  {29,22,rr,V,V,0},    /* cvtb.w.t */
+  {30,22,rr,V,V,0},    /* cvth.w.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {31,23,rr,V,V,0},    /* cvts.l.t */
+  {32,22,rr,V,V,0},    /* cvtd.w.t */
+  {33,18,rr,V,V,0},    /* cvtl.s.t */
+  {28,19,rr,V,V,0},    /* cvtw.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {116,18,rr,V,V,0},   /* frint.s.t */
+  {116,19,rr,V,V,0},   /* frint.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {81,18,rr,V,V,0},    /* sqrt.s.t */
+  {81,19,rr,V,V,0},    /* sqrt.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format3[] = {
+  {32,18,rr,V,V,0},    /* cvtd.s.t */
+  {31,19,rr,V,V,0},    /* cvts.d.t */
+  {33,19,rr,V,V,0},    /* cvtl.d.t */
+  {32,23,rr,V,V,0},    /* cvtd.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {36,1,rr,V,V,0},     /* tzc.t */
+  {44,1,rr,V,V,0},     /* lop.t */
+  {117,1,rr,V,V,0},    /* xpnd.t */
+  {42,1,rr,V,V,0},     /* not.t */
+  {8,1,rr,S,V,0},      /* shf.t */
+  {35,24,rr,V,V,0},    /* plc.t.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {37,18,rr,V,V,0},    /* eq.s.t */
+  {37,19,rr,V,V,0},    /* eq.d.t */
+  {43,18,rr,V,V,0},    /* neg.s.t */
+  {43,19,rr,V,V,0},    /* neg.d.t */
+  {37,18,rr,S,V,0},    /* eq.s.t */
+  {37,19,rr,S,V,0},    /* eq.d.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {40,18,rr,V,V,0},    /* le.s.t */
+  {40,19,rr,V,V,0},    /* le.d.t */
+  {41,18,rr,V,V,0},    /* lt.s.t */
+  {41,19,rr,V,V,0},    /* lt.d.t */
+  {40,18,rr,S,V,0},    /* le.s.t */
+  {40,19,rr,S,V,0},    /* le.d.t */
+  {41,18,rr,S,V,0},    /* lt.s.t */
+  {41,19,rr,S,V,0},    /* lt.d.t */
+  {37,20,rr,V,V,0},    /* eq.b.t */
+  {37,21,rr,V,V,0},    /* eq.h.t */
+  {37,22,rr,V,V,0},    /* eq.w.t */
+  {37,23,rr,V,V,0},    /* eq.l.t */
+  {37,20,rr,S,V,0},    /* eq.b.t */
+  {37,21,rr,S,V,0},    /* eq.h.t */
+  {37,22,rr,S,V,0},    /* eq.w.t */
+  {37,23,rr,S,V,0},    /* eq.l.t */
+  {40,20,rr,V,V,0},    /* le.b.t */
+  {40,21,rr,V,V,0},    /* le.h.t */
+  {40,22,rr,V,V,0},    /* le.w.t */
+  {40,23,rr,V,V,0},    /* le.l.t */
+  {40,20,rr,S,V,0},    /* le.b.t */
+  {40,21,rr,S,V,0},    /* le.h.t */
+  {40,22,rr,S,V,0},    /* le.w.t */
+  {40,23,rr,S,V,0},    /* le.l.t */
+  {41,20,rr,V,V,0},    /* lt.b.t */
+  {41,21,rr,V,V,0},    /* lt.h.t */
+  {41,22,rr,V,V,0},    /* lt.w.t */
+  {41,23,rr,V,V,0},    /* lt.l.t */
+  {41,20,rr,S,V,0},    /* lt.b.t */
+  {41,21,rr,S,V,0},    /* lt.h.t */
+  {41,22,rr,S,V,0},    /* lt.w.t */
+  {41,23,rr,S,V,0},    /* lt.l.t */
+  {43,20,rr,V,V,0},    /* neg.b.t */
+  {43,21,rr,V,V,0},    /* neg.h.t */
+  {43,22,rr,V,V,0},    /* neg.w.t */
+  {43,23,rr,V,V,0},    /* neg.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format4[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format5[] = {
+  {51,20,rr,V,V,0},    /* ldvi.b.t */
+  {51,21,rr,V,V,0},    /* ldvi.h.t */
+  {51,22,rr,V,V,0},    /* ldvi.w.t */
+  {51,23,rr,V,V,0},    /* ldvi.l.t */
+  {28,18,rr,V,V,0},    /* cvtw.s.t */
+  {31,22,rr,V,V,0},    /* cvts.w.t */
+  {28,23,rr,V,V,0},    /* cvtw.l.t */
+  {33,22,rr,V,V,0},    /* cvtl.w.t */
+  {52,20,rxr,V,V,0},   /* stvi.b.t */
+  {52,21,rxr,V,V,0},   /* stvi.h.t */
+  {52,22,rxr,V,V,0},   /* stvi.w.t */
+  {52,23,rxr,V,V,0},   /* stvi.l.t */
+  {52,20,rxr,S,V,0},   /* stvi.b.t */
+  {52,21,rxr,S,V,0},   /* stvi.h.t */
+  {52,22,rxr,S,V,0},   /* stvi.w.t */
+  {52,23,rxr,S,V,0},   /* stvi.l.t */
+};
+struct formstr e1_format6[] = {
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+struct formstr e1_format7[] = {
+  {84,20,r,V,0,0},     /* sum.b.t */
+  {84,21,r,V,0,0},     /* sum.h.t */
+  {84,22,r,V,0,0},     /* sum.w.t */
+  {84,23,r,V,0,0},     /* sum.l.t */
+  {85,1,r,V,0,0},      /* all.t */
+  {86,1,r,V,0,0},      /* any.t */
+  {87,1,r,V,0,0},      /* parity.t */
+  {0,0,0,0,0,0},
+  {88,20,r,V,0,0},     /* max.b.t */
+  {88,21,r,V,0,0},     /* max.h.t */
+  {88,22,r,V,0,0},     /* max.w.t */
+  {88,23,r,V,0,0},     /* max.l.t */
+  {89,20,r,V,0,0},     /* min.b.t */
+  {89,21,r,V,0,0},     /* min.h.t */
+  {89,22,r,V,0,0},     /* min.w.t */
+  {89,23,r,V,0,0},     /* min.l.t */
+  {84,18,r,V,0,0},     /* sum.s.t */
+  {84,19,r,V,0,0},     /* sum.d.t */
+  {90,18,r,V,0,0},     /* prod.s.t */
+  {90,19,r,V,0,0},     /* prod.d.t */
+  {88,18,r,V,0,0},     /* max.s.t */
+  {88,19,r,V,0,0},     /* max.d.t */
+  {89,18,r,V,0,0},     /* min.s.t */
+  {89,19,r,V,0,0},     /* min.d.t */
+  {90,20,r,V,0,0},     /* prod.b.t */
+  {90,21,r,V,0,0},     /* prod.h.t */
+  {90,22,r,V,0,0},     /* prod.w.t */
+  {90,23,r,V,0,0},     /* prod.l.t */
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+  {0,0,0,0,0,0},
+};
+char *lop[] = {
+  "mov",       /* 0 */
+  "merg",      /* 1 */
+  "mask",      /* 2 */
+  "mul",       /* 3 */
+  "div",       /* 4 */
+  "and",       /* 5 */
+  "or",        /* 6 */
+  "xor",       /* 7 */
+  "shf",       /* 8 */
+  "add",       /* 9 */
+  "sub",       /* 10 */
+  "exit",      /* 11 */
+  "jmp",       /* 12 */
+  "jmpi",      /* 13 */
+  "jmpa",      /* 14 */
+  "jmps",      /* 15 */
+  "tac",       /* 16 */
+  "ldea",      /* 17 */
+  "ld",        /* 18 */
+  "tas",       /* 19 */
+  "pshea",     /* 20 */
+  "st",        /* 21 */
+  "call",      /* 22 */
+  "calls",     /* 23 */
+  "callq",     /* 24 */
+  "pfork",     /* 25 */
+  "ste",       /* 26 */
+  "incr",      /* 27 */
+  "cvtw",      /* 28 */
+  "cvtb",      /* 29 */
+  "cvth",      /* 30 */
+  "cvts",      /* 31 */
+  "cvtd",      /* 32 */
+  "cvtl",      /* 33 */
+  "ldpa",      /* 34 */
+  "plc",       /* 35 */
+  "tzc",       /* 36 */
+  "eq",        /* 37 */
+  "leu",       /* 38 */
+  "ltu",       /* 39 */
+  "le",        /* 40 */
+  "lt",        /* 41 */
+  "not",       /* 42 */
+  "neg",       /* 43 */
+  "lop",       /* 44 */
+  "cprs",      /* 45 */
+  "nop",       /* 46 */
+  "br",        /* 47 */
+  "bri",       /* 48 */
+  "bra",       /* 49 */
+  "brs",       /* 50 */
+  "ldvi",      /* 51 */
+  "stvi",      /* 52 */
+  "ldsdr",     /* 53 */
+  "ldkdr",     /* 54 */
+  "ln",        /* 55 */
+  "patu",      /* 56 */
+  "pate",      /* 57 */
+  "pich",      /* 58 */
+  "plch",      /* 59 */
+  "idle",      /* 60 */
+  "rtnq",      /* 61 */
+  "cfork",     /* 62 */
+  "rtn",       /* 63 */
+  "wfork",     /* 64 */
+  "join",      /* 65 */
+  "rtnc",      /* 66 */
+  "exp",       /* 67 */
+  "sin",       /* 68 */
+  "cos",       /* 69 */
+  "psh",       /* 70 */
+  "pop",       /* 71 */
+  "eni",       /* 72 */
+  "dsi",       /* 73 */
+  "bkpt",      /* 74 */
+  "msync",     /* 75 */
+  "mski",      /* 76 */
+  "xmti",      /* 77 */
+  "tstvv",     /* 78 */
+  "diag",      /* 79 */
+  "pbkpt",     /* 80 */
+  "sqrt",      /* 81 */
+  "casr",      /* 82 */
+  "atan",      /* 83 */
+  "sum",       /* 84 */
+  "all",       /* 85 */
+  "any",       /* 86 */
+  "parity",    /* 87 */
+  "max",       /* 88 */
+  "min",       /* 89 */
+  "prod",      /* 90 */
+  "halt",      /* 91 */
+  "sysc",      /* 92 */
+  "trap",      /* 93 */
+  "tst",       /* 94 */
+  "lck",       /* 95 */
+  "ulk",       /* 96 */
+  "spawn",     /* 97 */
+  "ldcmr",     /* 98 */
+  "stcmr",     /* 99 */
+  "popr",      /* 100 */
+  "pshr",      /* 101 */
+  "rcvr",      /* 102 */
+  "matm",      /* 103 */
+  "sndr",      /* 104 */
+  "putr",      /* 105 */
+  "getr",      /* 106 */
+  "matr",      /* 107 */
+  "mat",       /* 108 */
+  "get",       /* 109 */
+  "rcv",       /* 110 */
+  "inc",       /* 111 */
+  "put",       /* 112 */
+  "snd",       /* 113 */
+  "enal",      /* 114 */
+  "enag",      /* 115 */
+  "frint",     /* 116 */
+  "xpnd",      /* 117 */
+  "ctrsl",     /* 118 */
+  "ctrsg",     /* 119 */
+  "stop",      /* 120 */
+};
+char *rop[] = {
+  "",  /* 0 */
+  ".t",        /* 1 */
+  ".f",        /* 2 */
+  ".s",        /* 3 */
+  ".d",        /* 4 */
+  ".b",        /* 5 */
+  ".h",        /* 6 */
+  ".w",        /* 7 */
+  ".l",        /* 8 */
+  ".x",        /* 9 */
+  ".u",        /* 10 */
+  ".s.f",      /* 11 */
+  ".d.f",      /* 12 */
+  ".b.f",      /* 13 */
+  ".h.f",      /* 14 */
+  ".w.f",      /* 15 */
+  ".l.f",      /* 16 */
+  ".t.f",      /* 17 */
+  ".s.t",      /* 18 */
+  ".d.t",      /* 19 */
+  ".b.t",      /* 20 */
+  ".h.t",      /* 21 */
+  ".w.t",      /* 22 */
+  ".l.t",      /* 23 */
+  ".t.t",      /* 24 */
+};
diff --git a/gdb/convex-pinsn.c b/gdb/convex-pinsn.c
new file mode 100644 (file)
index 0000000..a283d29
--- /dev/null
@@ -0,0 +1,314 @@
+/* Print Convex instructions for GDB, the GNU debugger.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+
+/* reg (fmt_field, inst_field) --
+   the {first,second,third} operand of instruction as fmt_field = [ijk]
+   gets the value of the field from the [ijk] position of the instruction */
+
+#define reg(a,b) ((char (*)[3])(op[fmt->a]))[inst.f0.b]
+
+/* lit (fmt_field) -- field [ijk] is a literal (PSW, VL, eg) */
+
+#define lit(i) op[fmt->i]
+
+/* aj[j] -- name for A register j */
+
+#define aj ((char (*)[3])(op[A]))
+\f
+union inst {
+    struct {
+       unsigned   : 7;
+       unsigned i : 3;
+       unsigned j : 3;
+       unsigned k : 3;
+       unsigned   : 16;
+       unsigned   : 32;
+    } f0;
+    struct {
+       unsigned   : 8;
+       unsigned indir : 1;
+       unsigned len : 1;
+       unsigned j : 3;
+       unsigned k : 3;
+       unsigned   : 16;
+       unsigned   : 32;
+    } f1;
+    unsigned char byte[8];
+    unsigned short half[4];
+    char signed_byte[8];
+    short signed_half[4];
+};
+
+struct opform {
+    int mask;                  /* opcode mask */
+    int shift;                 /* opcode align */
+    struct formstr *formstr[3];        /* ST, E0, E1 */
+};
+
+struct formstr {
+    unsigned lop:8, rop:5;     /* opcode */
+    unsigned fmt:5;            /* inst format */
+    unsigned i:5, j:5, k:2;    /* operand formats */
+};
+
+#include "convex-opcode.h"
+
+unsigned char formdecode [] = {
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+struct opform opdecode[] = {
+    0x7e00, 9, format0, e0_format0, e1_format0,
+    0x3f00, 8, format1, e0_format1, e1_format1,
+    0x1fc0, 6, format2, e0_format2, e1_format2,
+    0x0fc0, 6, format3, e0_format3, e1_format3,
+    0x0700, 8, format4, e0_format4, e1_format4,
+    0x03c0, 6, format5, e0_format5, e1_format5,
+    0x01f8, 3, format6, e0_format6, e1_format6,
+    0x00f8, 3, format7, e0_format7, e1_format7,
+    0x0000, 0, formatx, formatx, formatx,
+    0x0f80, 7, formatx, formatx, formatx,
+    0x0f80, 7, formatx, formatx, formatx,
+};
+\f
+/* Print the instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  union inst inst;
+  struct formstr *fmt;
+  register int format, op1, pfx;
+  int l;
+
+  read_memory (memaddr, &inst, sizeof inst);
+
+  /* Remove and note prefix, if present */
+    
+  pfx = inst.half[0];
+  if ((pfx & 0xfff0) == 0x7ef0)
+    {
+      pfx = ((pfx >> 3) & 1) + 1;
+      *(long long *) &inst = *(long long *) &inst.half[1];
+    }
+  else pfx = 0;
+
+  /* Split opcode into format.op1 and look up in appropriate table */
+
+  format = formdecode[inst.byte[0]];
+  op1 = (inst.half[0] & opdecode[format].mask) >> opdecode[format].shift;
+  if (format == 9)
+    {
+      if (pfx)
+       fmt = formatx;
+      else if (inst.f1.j == 0)
+       fmt = &format1a[op1];
+      else if (inst.f1.j == 1)
+       fmt = &format1b[op1];
+      else
+       fmt = formatx;
+    }
+  else
+    fmt = &opdecode[format].formstr[pfx][op1];
+
+  /* Print it */
+
+  if (fmt->fmt == xxx)
+    {
+      /* noninstruction */
+      fprintf (stream, "0x%04x", pfx ? pfx : inst.half[0]);
+      return 2;
+    }
+
+  if (pfx)
+    pfx = 2;
+
+  fprintf (stream, "%s%s%s", lop[fmt->lop], rop[fmt->rop],
+          &"        "[strlen(lop[fmt->lop]) + strlen(rop[fmt->rop])]);
+
+  switch (fmt->fmt)
+    {
+    case rrr:                  /* three register */
+      fprintf (stream, "%s,%s,%s", reg(i,i), reg(j,j), reg(k,k));
+      return pfx + 2;
+
+    case rr:                   /* two register */
+      fprintf (stream, "%s,%s", reg(i,j), reg(j,k));
+      return pfx + 2;
+
+    case rxr:                  /* two register, reversed i and j fields */
+      fprintf (stream, "%s,%s", reg(i,k), reg(j,j));
+      return pfx + 2;
+
+    case r:                    /* one register */
+      fprintf (stream, "%s", reg(i,k));
+      return pfx + 2;
+
+    case nops:                 /* no operands */
+      return pfx + 2;
+
+    case nr:                   /* short immediate, one register */
+      fprintf (stream, "#%d,%s", inst.f0.j, reg(i,k));
+      return pfx + 2;
+
+    case pcrel:                        /* pc relative */
+      print_address (memaddr + 2 * inst.signed_byte[1], stream);
+      return pfx + 2;
+
+    case lr:                   /* literal, one register */
+      fprintf (stream, "%s,%s", lit(i), reg(j,k));
+      return pfx + 2;
+
+    case rxl:                  /* one register, literal */
+      fprintf (stream, "%s,%s", reg(i,k), lit(j));
+      return pfx + 2;
+
+    case rlr:                  /* register, literal, register */
+      fprintf (stream, "%s,%s,%s", reg(i,j), lit(j), reg(k,k));
+      return pfx + 2;
+
+    case rrl:                  /* register, register, literal */
+      fprintf (stream, "%s,%s,%s", reg(i,j), reg(j,k), lit(k));
+      return pfx + 2;
+
+    case iml:                  /* immediate, literal */
+      if (inst.f1.len)
+       {
+         fprintf (stream, "#%#x,%s",
+                  (inst.signed_half[1] << 16) + inst.half[2], lit(i));
+         return pfx + 6;
+       }
+      else
+       {
+         fprintf (stream, "#%d,%s", inst.signed_half[1], lit(i));
+         return pfx + 4;
+       }
+
+    case imr:                  /* immediate, register */
+      if (inst.f1.len)
+       {
+         fprintf (stream, "#%#x,%s",
+                  (inst.signed_half[1] << 16) + inst.half[2], reg(i,k));
+         return pfx + 6;
+       }
+      else
+       {
+         fprintf (stream, "#%d,%s", inst.signed_half[1], reg(i,k));
+         return pfx + 4;
+       }
+
+    case a1r:                  /* memory, register */
+      l = print_effa (inst, stream);
+      fprintf (stream, ",%s", reg(i,k));
+      return pfx + l;
+
+    case a1l:                  /* memory, literal  */
+      l = print_effa (inst, stream);
+      fprintf (stream, ",%s", lit(i));
+      return pfx + l;
+
+    case a2r:                  /* register, memory */
+      fprintf (stream, "%s,", reg(i,k));
+      return pfx + print_effa (inst, stream);
+
+    case a2l:                  /* literal, memory */
+      fprintf (stream, "%s,", lit(i));
+      return pfx + print_effa (inst, stream);
+
+    case a3:                   /* memory */
+      return pfx + print_effa (inst, stream);
+
+    case a4:                   /* system call */
+      l = 29; goto a4a5;
+    case a5:                   /* trap */
+      l = 27;
+    a4a5:
+      if (inst.f1.len)
+       {
+         unsigned int m = (inst.signed_half[1] << 16) + inst.half[2];
+         fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
+         return pfx + 6;
+       }
+      else
+       {
+         unsigned int m = inst.signed_half[1];
+         fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
+         return pfx + 4;
+       }
+    }
+}
+
+
+/* print effective address @nnn(aj), return instruction length */
+
+int print_effa (inst, stream)
+     union inst inst;
+     FILE *stream;
+{
+  int n, l;
+
+  if (inst.f1.len)
+    {
+      n = (inst.signed_half[1] << 16) + inst.half[2];
+      l = 6;
+    }
+  else
+    {
+      n = inst.signed_half[1];
+      l = 4;
+    }
+       
+  if (inst.f1.indir)
+    printf ("@");
+
+  if (!inst.f1.j)
+    {
+      print_address (n, stream);
+      return l;
+    }
+
+  fprintf (stream, (n & 0xf0000000) == 0x80000000 ? "%#x(%s)" : "%d(%s)",
+          n, aj[inst.f1.j]);
+
+  return l;
+}
diff --git a/gdb/convex-tdep.c b/gdb/convex-tdep.c
new file mode 100644 (file)
index 0000000..c206e1e
--- /dev/null
@@ -0,0 +1,934 @@
+/* Convex stuff for GDB.
+   Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <signal.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/pcntl.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "gdbcmd.h"
+
+exec_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  int n;
+  struct stat st_exec;
+
+  /* Eliminate all traces of old exec file.
+     Mark text segment as empty.  */
+
+  if (execfile)
+    free (execfile);
+  execfile = 0;
+  data_start = 0;
+  data_end = 0;
+  text_start = 0;
+  text_end = 0;
+  exec_data_start = 0;
+  exec_data_end = 0;
+  if (execchan >= 0)
+    close (execchan);
+  execchan = -1;
+
+  n_exec = 0;
+
+  /* Now open and digest the file the user requested, if any.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+                       &execfile);
+      if (execchan < 0)
+       perror_with_name (filename);
+
+      if (myread (execchan, &filehdr, sizeof filehdr) < 0)
+       perror_with_name (filename);
+
+      if (! IS_SOFF_MAGIC (filehdr.h_magic))
+       error ("%s: not an executable file.", filename);
+
+      if (myread (execchan, &opthdr, filehdr.h_opthdr) <= 0)
+       perror_with_name (filename);
+
+      /* Read through the section headers.
+        For text, data, etc, record an entry in the exec file map.
+        Record text_start and text_end.  */
+
+      lseek (execchan, (long) filehdr.h_scnptr, 0);
+
+      for (n = 0; n < filehdr.h_nscns; n++)
+       {
+         if (myread (execchan, &scnhdr, sizeof scnhdr) < 0)
+           perror_with_name (filename);
+
+         if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT
+             && (scnhdr.s_flags & S_TYPMASK) <= S_COMON)
+           {
+             exec_map[n_exec].mem_addr = scnhdr.s_vaddr;
+             exec_map[n_exec].mem_end = scnhdr.s_vaddr + scnhdr.s_size;
+             exec_map[n_exec].file_addr = scnhdr.s_scnptr;
+             exec_map[n_exec].type = scnhdr.s_flags & S_TYPMASK;
+             n_exec++;
+
+             if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT)
+               {
+                 text_start = scnhdr.s_vaddr;
+                 text_end =  scnhdr.s_vaddr + scnhdr.s_size;
+               }
+           }
+       }
+
+      fstat (execchan, &st_exec);
+      exec_mtime = st_exec.st_mtime;
+      
+      validate_files ();
+    }
+  else if (from_tty)
+    printf_filtered ("No exec file now.\n");
+
+  /* Tell display code (if any) about the changed file name.  */
+  if (exec_file_display_hook)
+    (*exec_file_display_hook) (filename);
+}
+
+/* Read data from SOFF exec or core file.
+   Return 0 on success, EIO if address out of bounds. */
+
+int
+xfer_core_file (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  register int i;
+  register int n;
+  register int val;
+  int xferchan;
+  char **xferfile;
+  int fileptr;
+  int returnval = 0;
+
+  while (len > 0)
+    {
+      xferfile = 0;
+      xferchan = 0;
+
+      /* Determine which file the next bunch of addresses reside in,
+        and where in the file.  Set the file's read/write pointer
+        to point at the proper place for the desired address
+        and set xferfile and xferchan for the correct file.
+        If desired address is nonexistent, leave them zero.
+        i is set to the number of bytes that can be handled
+        along with the next address.  */
+
+      i = len;
+
+      for (n = 0; n < n_core; n++)
+       {
+         if (memaddr >= core_map[n].mem_addr && memaddr < core_map[n].mem_end
+             && (core_map[n].thread == -1
+                 || core_map[n].thread == inferior_thread))
+           {
+             i = min (len, core_map[n].mem_end - memaddr);
+             fileptr = core_map[n].file_addr + memaddr - core_map[n].mem_addr;
+             if (core_map[n].file_addr)
+               {
+                 xferfile = &corefile;
+                 xferchan = corechan;
+               }
+             break;
+           }
+         else if (core_map[n].mem_addr >= memaddr
+                  && core_map[n].mem_addr < memaddr + i)
+           i = core_map[n].mem_addr - memaddr;
+        }
+
+      if (!xferfile) 
+       for (n = 0; n < n_exec; n++)
+         {
+           if (memaddr >= exec_map[n].mem_addr
+               && memaddr < exec_map[n].mem_end)
+             {
+               i = min (len, exec_map[n].mem_end - memaddr);
+               fileptr = exec_map[n].file_addr + memaddr
+                 - exec_map[n].mem_addr;
+               if (exec_map[n].file_addr)
+                 {
+                   xferfile = &execfile;
+                   xferchan = execchan;
+                 }
+               break;
+             }
+           else if (exec_map[n].mem_addr >= memaddr
+                    && exec_map[n].mem_addr < memaddr + i)
+             i = exec_map[n].mem_addr - memaddr;
+         }
+
+      /* Now we know which file to use.
+        Set up its pointer and transfer the data.  */
+      if (xferfile)
+       {
+         if (*xferfile == 0)
+           if (xferfile == &execfile)
+             error ("No program file to examine.");
+           else
+             error ("No core dump file or running program to examine.");
+         val = lseek (xferchan, fileptr, 0);
+         if (val < 0)
+           perror_with_name (*xferfile);
+         val = myread (xferchan, myaddr, i);
+         if (val < 0)
+           perror_with_name (*xferfile);
+       }
+      /* If this address is for nonexistent memory,
+        read zeros if reading, or do nothing if writing.  */
+      else
+       {
+         bzero (myaddr, i);
+         returnval = EIO;
+       }
+
+      memaddr += i;
+      myaddr += i;
+      len -= i;
+    }
+  return returnval;
+}
+
+
+/* Here from info files command to print an address map.  */
+
+print_maps ()
+{
+  struct pmap ptrs[200];
+  int n;
+
+  /* ID strings for core and executable file sections */
+
+  static char *idstr[] =
+    {
+      "0", "text", "data", "tdata", "bss", "tbss", 
+      "common", "ttext", "ctx", "tctx", "10", "11", "12",
+    };
+
+  for (n = 0; n < n_core; n++)
+    {
+      core_map[n].which = 0;
+      ptrs[n] = core_map[n];
+    }
+  for (n = 0; n < n_exec; n++)
+    {
+      exec_map[n].which = 1;
+      ptrs[n_core+n] = exec_map[n];
+    }
+
+  qsort (ptrs, n_core + n_exec, sizeof *ptrs, ptr_cmp);
+
+  for (n = 0; n < n_core + n_exec; n++)
+    {
+      struct pmap *p = &ptrs[n];
+      if (n > 0)
+       {
+         if (p->mem_addr < ptrs[n-1].mem_end)
+           p->mem_addr = ptrs[n-1].mem_end;
+         if (p->mem_addr >= p->mem_end)
+           continue;
+       }
+      printf_filtered ("%08x .. %08x  %-6s  %s\n",
+                      p->mem_addr, p->mem_end, idstr[p->type],
+                      p->which ? execfile : corefile);
+    }
+}
+
+/* Compare routine to put file sections in order.
+   Sort into increasing order on address, and put core file sections
+   before exec file sections if both files contain the same addresses.  */
+
+static ptr_cmp (a, b)
+     struct pmap *a, *b;
+{
+  if (a->mem_addr != b->mem_addr) return a->mem_addr - b->mem_addr;
+  return a->which - b->which;
+}
+\f
+/* Trapped internal variables are used to handle special registers.
+   A trapped i.v. calls a hook here every time it is dereferenced,
+   to provide a new value for the variable, and it calls a hook here
+   when a new value is assigned, to do something with the value.
+   
+   The vector registers are $vl, $vs, $vm, $vN, $VN (N in 0..7).
+   The communication registers are $cN, $CN (N in 0..63).
+   They not handled as regular registers because it's expensive to
+   read them, and their size varies, and they have too many names.  */
+
+
+/* Return 1 if NAME is a trapped internal variable, else 0. */
+
+int
+is_trapped_internalvar (name)
+     char *name;
+{
+    if ((name[0] == 'c' || name[0] == 'C')
+       && name[1] >= '0' && name[1] <= '9'
+       && (name[2] == '\0'
+           || (name[2] >= '0' && name[2] <= '9'
+               && name[3] == '\0' && name[1] != '0'))
+       && atoi (&name[1]) < 64) return 1;
+
+  if ((name[0] == 'v' || name[0] == 'V')
+      && (((name[1] & -8) == '0' && name[2] == '\0')
+         || !strcmp (name, "vl")
+         || !strcmp (name, "vs") 
+         || !strcmp (name, "vm")))
+    return 1;
+  else return 0;
+}
+
+/* Return the value of trapped internal variable VAR */
+
+value
+value_of_trapped_internalvar (var)
+     struct internalvar *var;
+{
+  char *name = var->name;
+  value val;
+  struct type *type;
+  long len = *read_vector_register (VL_REGNUM);
+  if (len <= 0 || len > 128) len = 128;
+
+  if (!strcmp (name, "vl"))
+    {
+      val = value_from_long (builtin_type_int,
+                            (LONGEST) *read_vector_register_1 (VL_REGNUM));
+    }
+  else if (!strcmp (name, "vs"))
+    {
+      val = value_from_long (builtin_type_int,
+                            (LONGEST) *read_vector_register_1 (VS_REGNUM));
+    }
+  else if (!strcmp (name, "vm"))
+    {
+      long vm[4];
+      long i, *p;
+      bcopy (read_vector_register_1 (VM_REGNUM), vm, sizeof vm);
+      type = vector_type (builtin_type_int, len);
+      val = allocate_value (type);
+      p = (long *) VALUE_CONTENTS (val);
+      for (i = 0; i < len; i++) 
+       *p++ = !! (vm[3 - (i >> 5)] & (1 << (i & 037)));
+    }
+  else if (name[0] == 'V')
+    {
+      type = vector_type (builtin_type_long_long, len);
+      val = allocate_value (type);
+      bcopy (read_vector_register_1 (name[1] - '0'),
+            VALUE_CONTENTS (val), TYPE_LENGTH (type));
+    }
+  else if (name[0] == 'v')
+    {
+      long *p1, *p2;
+      type = vector_type (builtin_type_long, len);
+      val = allocate_value (type);
+      p1 = read_vector_register_1 (name[1] - '0');
+      p2 = (long *) VALUE_CONTENTS (val);
+      while (--len >= 0) {p1++; *p2++ = *p1++;}
+    }
+
+  else if (name[0] == 'c')
+    val = value_from_long (builtin_type_int,
+                          read_comm_register (atoi (&name[1])));
+  else if (name[0] == 'C')
+    val = value_from_long (builtin_type_long_long,
+                          read_comm_register (atoi (&name[1])));
+
+  VALUE_LVAL (val) = lval_internalvar;
+  VALUE_INTERNALVAR (val) = var;
+  return val;
+}
+
+/* Construct the type for a vector register's value --
+   array[LENGTH] of ELEMENT_TYPE.  */
+
+static struct type *
+vector_type (element_type, length)
+     struct type *element_type;
+     long length;
+{
+  struct type *type = (struct type *) xmalloc (sizeof (struct type));
+  bzero (type, sizeof type);
+  TYPE_CODE (type) = TYPE_CODE_ARRAY;
+  TYPE_TARGET_TYPE (type) = element_type;
+  TYPE_LENGTH (type) = length * TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+  return type;
+}
+
+/* Handle a new value assigned to a trapped internal variable */
+
+void
+set_trapped_internalvar (var, val, bitpos, bitsize, offset)
+     struct internalvar *var;
+     value val;
+     int bitpos, bitsize, offset;
+{ 
+  char *name = var->name;
+  long long newval = value_as_long (val);
+
+  if (!strcmp (name, "vl")) 
+    write_vector_register (VL_REGNUM, 0, newval);
+  else if (!strcmp (name, "vs"))
+    write_vector_register (VS_REGNUM, 0, newval);
+  else if (name[0] == 'c' || name[0] == 'C')
+    write_comm_register (atoi (&name[1]), newval);
+  else if (!strcmp (name, "vm"))
+    error ("can't assign to $vm");
+  else
+    {
+      offset /= bitsize / 8;
+      write_vector_register (name[1] - '0', offset, newval);
+    }
+}
+
+/* Print an integer value when no format was specified.  gdb normally
+   prints these values in decimal, but the the leading 0x80000000 of
+   pointers produces intolerable 10-digit negative numbers.
+   If it looks like an address, print it in hex instead.  */
+
+decout (stream, type, val)
+     FILE *stream;
+     struct type *type;
+     LONGEST val;
+{
+  long lv = val;
+
+  switch (output_radix)
+    {
+    case 0:
+      if ((lv == val || (unsigned) lv == val)
+         && ((lv & 0xf0000000) == 0x80000000
+             || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR)))
+       {
+         fprintf_filtered (stream, "%#x", lv);
+         return;
+       }
+
+    case 10:
+      fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val);
+      return;
+
+    case 8:
+      if (TYPE_LENGTH (type) <= sizeof lv)
+       fprintf_filtered (stream, "%#o", lv);
+      else
+       fprintf_filtered (stream, "%#llo", val);
+      return;
+
+    case 16:
+      if (TYPE_LENGTH (type) <= sizeof lv)
+       fprintf_filtered (stream, "%#x", lv);
+      else
+       fprintf_filtered (stream, "%#llx", val);
+      return;
+    }
+}
+
+/* Change the default output radix to 10 or 16, or set it to 0 (heuristic).
+   This command is mostly obsolete now that the print command allows
+   formats to apply to aggregates, but is still handy occasionally.  */
+
+static void
+set_base_command (arg)
+    char *arg;
+{
+  int new_radix;
+
+  if (!arg)
+    output_radix = 0;
+  else
+    {
+      new_radix = atoi (arg);
+      if (new_radix != 10 && new_radix != 16 && new_radix != 8) 
+       error ("base must be 8, 10 or 16, or null");
+      else output_radix = new_radix;
+    }
+}
+
+/* Turn pipelining on or off in the inferior. */
+
+static void
+set_pipelining_command (arg)
+    char *arg;
+{
+  if (!arg)
+    {
+      sequential = !sequential;
+      printf_filtered ("%s\n", sequential ? "off" : "on");
+    }
+  else if (!strcmp (arg, "on"))
+    sequential = 0;
+  else if (!strcmp (arg, "off"))
+    sequential = 1;
+  else error ("valid args are `on', to allow instructions to overlap, or\n\
+`off', to prevent it and thereby pinpoint exceptions.");
+}
+
+/* Enable, disable, or force parallel execution in the inferior.  */
+
+static void
+set_parallel_command (arg)
+     char *arg;
+{
+  struct rlimit rl;
+  int prevparallel = parallel;
+
+  if (!strncmp (arg, "fixed", strlen (arg)))
+    parallel = 2;  
+  else if (!strcmp (arg, "on"))
+    parallel = 1;
+  else if (!strcmp (arg, "off"))
+    parallel = 0;
+  else error ("valid args are `on', to allow multiple threads, or\n\
+`fixed', to force multiple threads, or\n\
+`off', to run with one thread only.");
+
+  if ((prevparallel == 0) != (parallel == 0) && inferior_pid)
+    printf_filtered ("will take effect at next run.\n");
+
+  getrlimit (RLIMIT_CONCUR, &rl);
+  rl.rlim_cur = parallel ? rl.rlim_max : 1;
+  setrlimit (RLIMIT_CONCUR, &rl);
+
+  if (inferior_pid)
+    set_fixed_scheduling (inferior_pid, parallel == 2);
+}
+
+/* Add a new name for an existing command.  */
+
+static void 
+alias_command (arg)
+    char *arg;
+{
+    static char *aliaserr = "usage is `alias NEW OLD', no args allowed";
+    char *newname = arg;
+    struct cmd_list_element *new, *old;
+
+    if (!arg)
+      error_no_arg ("newname oldname");
+       
+    new = lookup_cmd (&arg, cmdlist, "", -1);
+    if (new && !strncmp (newname, new->name, strlen (new->name)))
+      {
+       newname = new->name;
+       if (!(*arg == '-' 
+             || (*arg >= 'a' && *arg <= 'z')
+             || (*arg >= 'A' && *arg <= 'Z')
+             || (*arg >= '0' && *arg <= '9')))
+         error (aliaserr);
+      }
+    else
+      {
+       arg = newname;
+       while (*arg == '-' 
+              || (*arg >= 'a' && *arg <= 'z')
+              || (*arg >= 'A' && *arg <= 'Z')
+              || (*arg >= '0' && *arg <= '9'))
+         arg++;
+       if (*arg != ' ' && *arg != '\t')
+         error (aliaserr);
+       *arg = '\0';
+       arg++;
+      }
+
+    old = lookup_cmd (&arg, cmdlist, "", 0);
+
+    if (*arg != '\0')
+      error (aliaserr);
+
+    if (new && !strncmp (newname, new->name, strlen (new->name)))
+      {
+       char *tem;
+       if (new->class == (int) class_user || new->class == (int) class_alias)
+         tem = "Redefine command \"%s\"? ";
+       else
+         tem = "Really redefine built-in command \"%s\"? ";
+       if (!query (tem, new->name))
+         error ("Command \"%s\" not redefined.", new->name);
+      }
+
+    add_com (newname, class_alias, old->function, old->doc);
+}
+
+
+
+/* Print the current thread number, and any threads with signals in the
+   queue.  */
+
+thread_info ()
+{
+  struct threadpid *p;
+
+  if (have_inferior_p ())
+    {
+      ps.pi_buffer = (char *) &comm_registers;
+      ps.pi_nbytes = sizeof comm_registers;
+      ps.pi_offset = 0;
+      ps.pi_thread = inferior_thread;
+      ioctl (inferior_fd, PIXRDCREGS, &ps);
+    }
+
+  printf_filtered ("Current thread %d stopped with signal %d.%d (%s).\n",
+                  inferior_thread, stop_signal, stop_sigcode,
+                  subsig_name (stop_signal, stop_sigcode));
+  
+  for (p = signal_stack; p->pid; p--)
+    printf_filtered ("Thread %d stopped with signal %d.%d (%s).\n",
+                    p->thread, p->signo, p->subsig,
+                    subsig_name (p->signo, p->subsig));
+               
+  if (iscrlbit (comm_registers.crctl.lbits.cc, 64+13))
+    printf_filtered ("New thread start pc %#x\n",
+                    (long) (comm_registers.crreg.pcpsw >> 32));
+}
+
+/* Return string describing a signal.subcode number */
+
+static char *
+subsig_name (signo, subcode)
+     int signo, subcode;
+{
+  static char *subsig4[] = {
+    "error exit", "privileged instruction", "unknown",
+    "unknown", "undefined opcode",
+    0};
+  static char *subsig5[] = {0,
+    "breakpoint", "single step", "fork trap", "exec trap", "pfork trap",
+    "join trap", "idle trap", "last thread", "wfork trap",
+    "process breakpoint", "trap instruction",
+    0};
+  static char *subsig8[] = {0,
+    "int overflow", "int divide check", "float overflow",
+    "float divide check", "float underflow", "reserved operand",
+    "sqrt error", "exp error", "ln error", "sin error", "cos error",
+    0};
+  static char *subsig10[] = {0,
+    "invalid inward ring address", "invalid outward ring call",
+    "invalid inward ring return", "invalid syscall gate",
+    "invalid rtn frame length", "invalid comm reg address",
+    "invalid trap gate",
+    0};
+  static char *subsig11[] = {0,
+    "read access denied", "write access denied", "execute access denied",
+    "segment descriptor fault", "page table fault", "data reference fault",
+    "i/o access denied", "levt pte invalid",
+    0};
+
+  static char **subsig_list[] = 
+    {0, 0, 0, 0, subsig4, subsig5, 0, 0, subsig8, 0, subsig10, subsig11, 0};
+
+  int i;
+  char *p = signo < NSIG ? sys_siglist[signo] : "unknown";
+
+  if (signo >= (sizeof subsig_list / sizeof *subsig_list)
+      || !subsig_list[signo])
+    return p;
+  for (i = 1; subsig_list[signo][i]; i++)
+    if (i == subcode)
+      return subsig_list[signo][subcode];
+  return p;
+}
+
+
+/* Print a compact display of thread status, essentially x/i $pc
+   for all active threads.  */
+
+static void
+threadstat ()
+{
+  int t;
+
+  for (t = 0; t < n_threads; t++)
+    if (thread_state[t] == PI_TALIVE)
+      {
+       printf_filtered ("%d%c %08x%c %d.%d ", t,
+                        (t == inferior_thread ? '*' : ' '), thread_pc[t],
+                        (thread_is_in_kernel[t] ? '#' : ' '),
+                        thread_signal[t], thread_sigcode[t]);
+       print_insn (thread_pc[t], stdout);
+       printf_filtered ("\n");
+      }
+}
+
+/* Change the current thread to ARG.  */
+
+set_thread_command (arg)
+     char *arg;
+{
+    int thread;
+
+    if (!arg)
+      {
+       threadstat ();
+       return;
+      }
+
+    thread = parse_and_eval_address (arg);
+
+    if (thread < 0 || thread > n_threads || thread_state[thread] != PI_TALIVE)
+      error ("no such thread.");
+
+    select_thread (thread);
+
+    stop_pc = read_pc ();
+    flush_cached_frames ();
+    set_current_frame (create_new_frame (read_register (FP_REGNUM),
+                                        read_pc ()));
+    select_frame (get_current_frame (), 0);
+    print_sel_frame (1);
+}
+
+/* Here on CONT command; gdb's dispatch address is changed to come here.
+   Set global variable ALL_CONTINUE to tell resume() that it should
+   start up all threads, and that a thread switch will not blow gdb's
+   mind.  */
+
+static void
+convex_cont_command (proc_count_exp, from_tty)
+     char *proc_count_exp;
+     int from_tty;
+{
+  all_continue = 1;
+  cont_command (proc_count_exp, from_tty);
+}
+
+/* Here on 1CONT command.  Resume only the current thread.  */
+
+one_cont_command (proc_count_exp, from_tty)
+     char *proc_count_exp;
+     int from_tty;
+{
+  cont_command (proc_count_exp, from_tty);
+}
+
+/* Print the contents and lock bits of all communication registers,
+   or just register ARG if ARG is a communication register,
+   or the 3-word resource structure in memory at address ARG.  */
+
+comm_registers_info (arg)
+    char *arg;
+{
+  int i, regnum;
+
+  if (arg)
+    {
+      if (sscanf (arg, "0x%x", &regnum) == 1
+         || sscanf (arg, "%d", &regnum) == 1)
+       {
+         if (regnum > 0)
+           regnum &= ~0x8000;
+       }
+      else if (sscanf (arg, "$c%d", &regnum) == 1)
+       ;
+      else if (sscanf (arg, "$C%d", &regnum) == 1)
+       ;
+      else
+       regnum = parse_and_eval_address (arg);
+
+      if (regnum >= 64)
+       error ("%s: invalid register name.", arg);
+
+      /* if we got a (user) address, examine the resource struct there */
+
+      if (regnum < 0)
+       {
+         static int buf[3];
+         read_memory (regnum, buf, sizeof buf);
+         printf_filtered ("%08x  %08x%08x%s\n", regnum, buf[1], buf[2],
+                          buf[0] & 0xff ? " locked" : "");
+         return;
+       }
+    }
+
+  ps.pi_buffer = (char *) &comm_registers;
+  ps.pi_nbytes = sizeof comm_registers;
+  ps.pi_offset = 0;
+  ps.pi_thread = inferior_thread;
+  ioctl (inferior_fd, PIXRDCREGS, &ps);
+
+  for (i = 0; i < 64; i++)
+    if (!arg || i == regnum)
+      printf_filtered ("%2d 0x8%03x %016llx%s\n", i, i,
+                      comm_registers.crreg.r4[i],
+                      (iscrlbit (comm_registers.crctl.lbits.cc, i)
+                       ? " locked" : ""));
+}
+
+/* Print the psw */
+
+static void 
+psw_info (arg)
+    char *arg;
+{
+  struct pswbit
+    {
+      int bit;
+      int pos;
+      char *text;
+    };
+
+  static struct pswbit pswbit[] =
+    {
+      { 0x80000000, -1, "A carry" }, 
+      { 0x40000000, -1, "A integer overflow" }, 
+      { 0x20000000, -1, "A zero divide" }, 
+      { 0x10000000, -1, "Integer overflow enable" }, 
+      { 0x08000000, -1, "Trace" }, 
+      { 0x06000000, 25, "Frame length" }, 
+      { 0x01000000, -1, "Sequential" }, 
+      { 0x00800000, -1, "S carry" }, 
+      { 0x00400000, -1, "S integer overflow" }, 
+      { 0x00200000, -1, "S zero divide" }, 
+      { 0x00100000, -1, "Zero divide enable" }, 
+      { 0x00080000, -1, "Floating underflow" }, 
+      { 0x00040000, -1, "Floating overflow" }, 
+      { 0x00020000, -1, "Floating reserved operand" }, 
+      { 0x00010000, -1, "Floating zero divide" }, 
+      { 0x00008000, -1, "Floating error enable" }, 
+      { 0x00004000, -1, "Floating underflow enable" }, 
+      { 0x00002000, -1, "IEEE" }, 
+      { 0x00001000, -1, "Sequential stores" }, 
+      { 0x00000800, -1, "Intrinsic error" }, 
+      { 0x00000400, -1, "Intrinsic error enable" }, 
+      { 0x00000200, -1, "Trace thread creates" }, 
+      { 0x00000100, -1, "Thread init trap" }, 
+      { 0x000000e0,  5, "Reserved" },
+      { 0x0000001f,  0, "Intrinsic error code" },
+      {0, 0, 0},
+    };
+
+  long psw;
+  struct pswbit *p;
+
+  if (arg)
+    psw = parse_and_eval_address (arg);
+  else
+    psw = read_register (PS_REGNUM);
+
+  for (p = pswbit; p->bit; p++)
+    {
+      if (p->pos < 0)
+       printf_filtered ("%08x  %s  %s\n", p->bit,
+                        (psw & p->bit) ? "yes" : "no ", p->text);
+      else
+       printf_filtered ("%08x %3d   %s\n", p->bit,
+                        (psw & p->bit) >> p->pos, p->text);
+    }
+}
+\f
+_initialize_convex_dep ()
+{
+  add_com ("alias", class_support, alias_command,
+          "Add a new name for an existing command.");
+
+  add_cmd ("base", class_vars, set_base_command,
+          "Change the integer output radix to 8, 10 or 16\n\
+or use just `set base' with no args to return to the ad-hoc default,\n\
+which is 16 for integers that look like addresses, 10 otherwise.",
+          &setlist);
+
+  add_cmd ("pipeline", class_run, set_pipelining_command,
+          "Enable or disable overlapped execution of instructions.\n\
+With `set pipe off', exceptions are reported with\n\
+$pc pointing at the instruction after the faulting one.\n\
+The default is `set pipe on', which runs faster.",
+          &setlist);
+
+  add_cmd ("parallel", class_run, set_parallel_command,
+          "Enable or disable multi-threaded execution of parallel code.\n\
+`set parallel off' means run the program on a single CPU.\n\
+`set parallel fixed' means run the program with all CPUs assigned to it.\n\
+`set parallel on' means run the program on any CPUs that are available.",
+          &setlist);
+
+  add_com ("1cont", class_run, one_cont_command,
+          "Continue the program, activating only the current thread.\n\
+Args are the same as the `cont' command.");
+
+  add_com ("thread", class_run, set_thread_command,
+          "Change the current thread, the one under scrutiny and control.\n\
+With no arg, show the active threads, the current one marked with *.");
+
+  add_info ("threads", thread_info,
+           "List status of active threads.");
+
+  add_info ("comm-registers", comm_registers_info,
+           "List communication registers and their contents.\n\
+A communication register name as argument means describe only that register.\n\
+An address as argument means describe the resource structure at that address.\n\
+`Locked' means that the register has been sent to but not yet received from.");
+
+  add_info ("psw", psw_info, 
+           "Display $ps, the processor status word, bit by bit.\n\
+An argument means display that value's interpretation as a psw.");
+
+  add_cmd ("convex", no_class, 0, "Convex-specific commands.\n\
+32-bit registers  $pc $ps $sp $ap $fp $a1-5 $s0-7 $v0-7 $vl $vs $vm $c0-63\n\
+64-bit registers  $S0-7 $V0-7 $C0-63\n\
+\n\
+info threads       display info on stopped threads waiting to signal\n\
+thread             display list of active threads\n\
+thread N           select thread N (its registers, stack, memory, etc.)\n\
+step, next, etc     step selected thread only\n\
+1cont              continue selected thread only\n\
+cont               continue all threads\n\
+info comm-registers display contents of comm register(s) or a resource struct\n\
+info psw           display processor status word $ps\n\
+set base N         change integer radix used by `print' without a format\n\
+set pipeline off    exceptions are precise, $pc points after the faulting insn\n\
+set pipeline on     normal mode, $pc is somewhere ahead of faulting insn\n\
+set parallel off    program runs on a single CPU\n\
+set parallel fixed  all CPUs are assigned to the program\n\
+set parallel on     normal mode, parallel execution on random available CPUs\n\
+",
+          &cmdlist);
+
+}
diff --git a/gdb/convex-xdep.c b/gdb/convex-xdep.c
new file mode 100644 (file)
index 0000000..f9f44a0
--- /dev/null
@@ -0,0 +1,983 @@
+/* Convex stuff for GDB.
+   Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <signal.h>
+#include <fcntl.h>
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/pcntl.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <convex/vmparam.h>
+#include <convex/filehdr.h>
+#include <convex/opthdr.h>
+#include <convex/scnhdr.h>
+#include <convex/core.h>
+
+/* Per-thread data, read from the inferior at each stop and written
+   back at each resume.  */
+
+/* Number of active threads.
+   Tables are valid for thread numbers less than this.  */
+
+static int n_threads;
+
+#define MAXTHREADS 8
+               
+/* Thread state.  The remaining data is valid only if this is PI_TALIVE.  */
+
+static int thread_state[MAXTHREADS];
+
+/* Stop pc, signal, signal subcode */
+
+static int thread_pc[MAXTHREADS];
+static int thread_signal[MAXTHREADS];
+static int thread_sigcode[MAXTHREADS]; 
+
+/* Thread registers.
+   If thread is selected, the regs are in registers[] instead.  */
+
+static char thread_regs[MAXTHREADS][REGISTER_BYTES];
+
+/* 1 if the top frame on the thread's stack was a context frame,
+   meaning that the kernel is up to something and we should not
+   touch the thread at all except to resume it.  */
+
+static char thread_is_in_kernel[MAXTHREADS];
+
+/* The currently selected thread's number.  */
+
+static int inferior_thread;
+
+/* Inferior process's file handle and a process control block
+   to feed args to ioctl with.  */
+
+static int inferior_fd;
+static struct pcntl ps;
+
+/* SOFF file headers for exec or core file.  */
+
+static FILEHDR filehdr;
+static OPTHDR opthdr;
+static SCNHDR scnhdr;
+
+/* Address maps constructed from section headers of exec and core files.
+   Defines process address -> file address translation.  */
+
+struct pmap 
+{
+    long mem_addr;             /* process start address */
+    long mem_end;              /* process end+1 address */
+    long file_addr;            /* file start address */
+    long thread;               /* -1 shared; 0,1,... thread-local */
+    long type;                 /* S_TEXT S_DATA S_BSS S_TBSS etc */
+    long which;                        /* used to sort map for info files */
+};
+
+static int n_exec, n_core;
+static struct pmap exec_map[100];
+static struct pmap core_map[100];
+
+/* Offsets in the core file of core_context and core_tcontext blocks.  */
+
+static int context_offset;
+static int tcontext_offset[MAXTHREADS];
+
+/* Core file control blocks.  */
+
+static struct core_context_v70 c;
+static struct core_tcontext_v70 tc;
+static struct user u;
+static thread_t th;
+static proc_t pr;
+
+/* The registers of the currently selected thread.  */
+
+extern char registers[REGISTER_BYTES];
+
+/* Vector and communication registers from core dump or from inferior.
+   These are read on demand, ie, not normally valid.  */
+
+static struct vecst vector_registers;
+static struct creg_ctx comm_registers;
+
+/* Flag, set on a vanilla CONT command and cleared when the inferior
+   is continued.  */
+
+static int all_continue;
+
+/* Flag, set when the inferior is continued by a vanilla CONT command,
+   cleared if it is continued for any other purpose.  */
+
+static int thread_switch_ok;
+
+/* Stack of signals recieved from threads but not yet delivered to gdb.  */
+
+struct threadpid 
+{
+    int pid;
+    int thread;
+    int signo;
+    int subsig;
+    int pc;
+};
+
+static struct threadpid signal_stack_bot[100];
+static struct threadpid *signal_stack = signal_stack_bot;
+
+/* How to detect empty stack -- bottom frame is all zero.  */
+
+#define signal_stack_is_empty() (signal_stack->pid == 0)
+
+/* Mode controlled by SET PIPE command, controls the psw SEQ bit
+   which forces each instruction to complete before the next one starts.  */
+
+static int sequential = 0;
+
+/* Mode controlled by the SET PARALLEL command.  Values are:
+   0  concurrency limit 1 thread, dynamic scheduling
+   1  no concurrency limit, dynamic scheduling
+   2  no concurrency limit, fixed scheduling  */
+
+static int parallel = 1;
+
+/* Mode controlled by SET BASE command, output radix for unformatted
+   integer typeout, as in argument lists, aggregates, and so on.
+   Zero means guess whether it's an address (hex) or not (decimal).  */
+
+static int output_radix = 0;
+
+/* Signal subcode at last thread stop.  */
+
+static int stop_sigcode;
+
+/* Hack, see wait() below.  */
+
+static int exec_trap_timer;
+
+#include "gdbcmd.h"
+
+/* Nonzero if we are debugging an attached outside process
+   rather than an inferior.  */
+
+extern int attach_flag;
+
+
+
+static struct type *vector_type ();
+static long *read_vector_register ();
+static long *read_vector_register_1 ();
+static void write_vector_register ();
+static REGISTER_TYPE read_comm_register ();
+static void write_comm_register ();
+static void convex_cont_command ();
+static void thread_continue ();
+static void select_thread ();
+static void scan_stack ();
+static void set_fixed_scheduling ();
+static char *subsig_name ();
+static void psw_info ();
+static sig_noop ();
+static ptr_cmp ();
+
+extern char *sys_siglist[];
+\f
+/* Execute ptrace.  Convex V7 replaced ptrace with pattach.
+   Allow ptrace (0) as a no-op.  */
+
+int
+call_ptrace (request, pid, procaddr, buf)
+     int request, pid, procaddr, buf;
+{
+  if (request == 0)
+    return;
+  error ("no ptrace");
+}
+
+/* Replacement for system execle routine.
+   Convert it to an equivalent exect, which pattach insists on.  */
+
+execle (name, argv)
+     char *name, *argv;
+{
+  char ***envp = (char ***) &argv;
+  while (*envp++) ;
+
+  signal (SIGTRAP, sig_noop);
+  exect (name, &argv, *envp);
+}
+
+/* Stupid handler for stupid trace trap that otherwise causes
+   startup to stupidly hang.  */
+
+static sig_noop () 
+{}
+
+/* Read registers from inferior into registers[] array.
+   For convex, they are already there, read in when the inferior stops.  */
+
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+}
+
+/* Store our register values back into the inferior.
+   For Convex, do this only once, right before resuming inferior.  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+}
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR. 
+   On failure (cannot read from inferior, usually because address is out
+   of bounds) returns the value of errno. */
+
+int
+read_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  errno = 0;
+  while (len > 0)
+    {
+      /* little-known undocumented max request size */
+      int i = (len < 12288) ? len : 12288;
+
+      lseek (inferior_fd, memaddr, 0);
+      read (inferior_fd, myaddr, i);
+
+      memaddr += i;
+      myaddr += i;
+      len -= i;
+    }
+  if (errno) 
+    bzero (myaddr, len);
+  return errno;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+   to inferior's memory at MEMADDR.
+   Returns errno on failure (cannot write the inferior) */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  errno = 0;
+  lseek (inferior_fd, memaddr, 0);
+  write (inferior_fd, myaddr, len);
+  return errno;
+}
+
+/* Here from create_inferior when the inferior process has been created
+   and started up.  We must do a pattach to grab it for debugging.
+
+   Also, intercept the CONT command by altering its dispatch address.  */
+
+create_inferior_hook (pid)
+    int pid;
+{
+  static char cont[] = "cont";
+  static char cont1[] = "c";
+  char *linep = cont;
+  char *linep1 = cont1;
+  char **line = &linep;
+  char **line1 = &linep1;
+  struct cmd_list_element *c;
+
+  c = lookup_cmd (line, cmdlist, "", 0);
+  c->function = convex_cont_command;
+  c = lookup_cmd (line1, cmdlist, "", 0);
+  c->function = convex_cont_command;
+
+  inferior_fd = pattach (pid, O_EXCL);
+  if (inferior_fd < 0)
+    perror_with_name ("pattach");
+  inferior_thread = 0;
+  set_fixed_scheduling (pid, parallel == 2);
+}
+
+/* Attach process PID for debugging.  */
+
+attach (pid)
+    int pid;
+{
+  int fd = pattach (pid, O_EXCL);
+  if (fd < 0)
+    perror_with_name ("pattach");
+  attach_flag = 1;
+  /* wait for strange kernel reverberations to go away */
+  sleep (1);
+
+  setpgrp (pid, pid);
+
+  inferior_fd = fd;
+  inferior_thread = 0;
+  return pid;
+}
+
+/* Stop debugging the process whose number is PID
+   and continue it with signal number SIGNAL.
+   SIGNAL = 0 means just continue it.  */
+
+void
+detach (signal)
+     int signal;
+{
+  signal_stack = signal_stack_bot;
+  thread_continue (-1, 0, signal);
+  ioctl (inferior_fd, PIXDETACH, &ps);
+  close (inferior_fd);
+  inferior_fd = 0;
+  attach_flag = 0;
+}
+
+/* Kill off the inferior process.  */
+
+kill_inferior ()
+{
+  if (inferior_pid == 0)
+    return;
+  ioctl (inferior_fd, PIXTERMINATE, 0);
+  wait (0);
+  target_mourn_inferior ();
+}
+
+/* This is used when GDB is exiting.  It gives less chance of error.*/
+
+kill_inferior_fast ()
+{
+  if (inferior_pid == 0)
+    return;
+  ioctl (inferior_fd, PIXTERMINATE, 0);
+  wait (0);
+}
+
+/* Read vector register REG, and return a pointer to the value.  */
+
+static long *
+read_vector_register (reg)
+    int reg;
+{
+  if (have_inferior_p ())
+    {
+      errno = 0;
+      ps.pi_buffer = (char *) &vector_registers;
+      ps.pi_nbytes = sizeof vector_registers;
+      ps.pi_offset = 0;
+      ps.pi_thread = inferior_thread;
+      ioctl (inferior_fd, PIXRDVREGS, &ps);
+      if (errno)
+       bzero (&vector_registers, sizeof vector_registers);
+    }
+  else if (corechan >= 0)
+    {
+      lseek (corechan, tcontext_offset[inferior_thread], 0);
+      if (myread (corechan, &tc, sizeof tc) < 0)
+       perror_with_name (corefile);
+      lseek (corechan, tc.core_thread_p, 0);
+      if (myread (corechan, &th, sizeof th) < 0)
+       perror_with_name (corefile);
+      lseek (corechan, tc.core_vregs_p, 0);
+      if (myread (corechan, &vector_registers, 16*128) < 0)
+       perror_with_name (corefile);
+      vector_registers.vm[0] = th.t_vect_ctx.vc_vm[0];
+      vector_registers.vm[1] = th.t_vect_ctx.vc_vm[1];
+      vector_registers.vls = th.t_vect_ctx.vc_vls;
+    }
+
+  return read_vector_register_1 (reg);
+}
+
+/* Return a pointer to vector register REG, which must already have been
+   fetched from the inferior or core file.  */
+
+static long *
+read_vector_register_1 (reg) 
+    int reg;
+{
+  switch (reg)
+    {
+    case VM_REGNUM:
+      return (long *) vector_registers.vm;
+    case VS_REGNUM:
+      return (long *) &vector_registers.vls;
+    case VL_REGNUM:
+      return 1 + (long *) &vector_registers.vls;
+    default:
+      return (long *) &vector_registers.vr[reg];
+    }
+}
+
+/* Write vector register REG, element ELEMENT, new value VAL.
+   NB: must use read-modify-write on the entire vector state,
+   since pattach does not do offsetted writes correctly.  */
+
+static void
+write_vector_register (reg, element, val)
+    int reg, element;
+    REGISTER_TYPE val;
+{
+  if (have_inferior_p ())
+    {
+      errno = 0;
+      ps.pi_thread = inferior_thread;
+      ps.pi_offset = 0;
+      ps.pi_buffer = (char *) &vector_registers;
+      ps.pi_nbytes = sizeof vector_registers;
+
+      ioctl (inferior_fd, PIXRDVREGS, &ps);
+
+      switch (reg)
+       {
+       case VL_REGNUM:
+         vector_registers.vls =
+           (vector_registers.vls & 0xffffffff00000000LL)
+             + (unsigned long) val;
+         break;
+
+       case VS_REGNUM:
+         vector_registers.vls =
+           (val << 32) + (unsigned long) vector_registers.vls;
+         break;
+           
+       default:
+         vector_registers.vr[reg].el[element] = val;
+         break;
+       }
+
+      ioctl (inferior_fd, PIXWRVREGS, &ps);
+
+      if (errno)
+       perror_with_name ("writing vector register");
+    }
+}
+
+/* Return the contents of communication register NUM.  */ 
+
+static REGISTER_TYPE 
+read_comm_register (num)
+     int num;
+{
+  if (have_inferior_p ())
+    {
+      ps.pi_buffer = (char *) &comm_registers;
+      ps.pi_nbytes = sizeof comm_registers;
+      ps.pi_offset = 0;
+      ps.pi_thread = inferior_thread;
+      ioctl (inferior_fd, PIXRDCREGS, &ps);
+    }
+  return comm_registers.crreg.r4[num];
+}
+
+/* Store a new value VAL into communication register NUM.  
+   NB: Must use read-modify-write on the whole comm register set
+   since pattach does not do offsetted writes correctly.  */
+
+static void
+write_comm_register (num, val)
+     int num;
+     REGISTER_TYPE val;
+{
+  if (have_inferior_p ())
+    {
+      ps.pi_buffer = (char *) &comm_registers;
+      ps.pi_nbytes = sizeof comm_registers;
+      ps.pi_offset = 0;
+      ps.pi_thread = inferior_thread;
+      ioctl (inferior_fd, PIXRDCREGS, &ps);
+      comm_registers.crreg.r4[num] = val;
+      ioctl (inferior_fd, PIXWRCREGS, &ps);
+    }
+}
+
+/* Resume execution of the inferior process.
+   If STEP is nonzero, single-step it.
+   If SIGNAL is nonzero, give it that signal.  */
+
+void
+resume (step, signal)
+     int step;
+     int signal;
+{
+  errno = 0;
+  if (step || signal)
+    thread_continue (inferior_thread, step, signal);
+  else
+    thread_continue (-1, 0, 0);
+}
+
+/* Maybe resume some threads.
+   THREAD is which thread to resume, or -1 to resume them all.
+   STEP and SIGNAL are as in resume.
+
+   Global variable ALL_CONTINUE is set when we are here to do a
+   `cont' command; otherwise we may be doing `finish' or a call or
+   something else that will not tolerate an automatic thread switch.
+
+   If there are stopped threads waiting to deliver signals, and
+   ALL_CONTINUE, do not actually resume anything.  gdb will do a wait
+   and see one of the stopped threads in the queue.  */
+
+static void
+thread_continue (thread, step, signal)
+     int thread, step, signal;
+{
+  int n;
+
+  /* If we are to continue all threads, but not for the CONTINUE command,
+     pay no attention and continue only the selected thread.  */
+
+  if (thread < 0 && ! all_continue)
+    thread = inferior_thread;
+
+  /* If we are not stepping, we have now executed the continue part
+     of a CONTINUE command.  */
+
+  if (! step)
+    all_continue = 0;
+
+  /* Allow wait() to switch threads if this is an all-out continue.  */
+
+  thread_switch_ok = thread < 0;
+
+  /* If there are threads queued up, don't resume.  */
+
+  if (thread_switch_ok && ! signal_stack_is_empty ())
+    return;
+
+  /* OK, do it.  */
+
+  for (n = 0; n < n_threads; n++)
+    if (thread_state[n] == PI_TALIVE)
+      {
+       select_thread (n);
+
+       if ((thread < 0 || n == thread) && ! thread_is_in_kernel[n])
+         {
+           /* Blam the trace bits in the stack's saved psws to match 
+              the desired step mode.  This is required so that
+              single-stepping a return doesn't restore a psw with a
+              clear trace bit and fly away, and conversely,
+              proceeding through a return in a routine that was
+              stepped into doesn't cause a phantom break by restoring
+              a psw with the trace bit set. */
+           scan_stack (PSW_T_BIT, step);
+           scan_stack (PSW_S_BIT, sequential);
+         }
+
+       ps.pi_buffer = registers;
+       ps.pi_nbytes = REGISTER_BYTES;
+       ps.pi_offset = 0;
+       ps.pi_thread = n;
+       if (! thread_is_in_kernel[n])
+         if (ioctl (inferior_fd, PIXWRREGS, &ps))
+           perror_with_name ("PIXWRREGS");
+
+       if (thread < 0 || n == thread)
+         {
+           ps.pi_pc = 1;
+           ps.pi_signo = signal;
+           if (ioctl (inferior_fd, step ? PIXSTEP : PIXCONTINUE, &ps) < 0)
+             perror_with_name ("PIXCONTINUE");
+         }
+      }
+
+  if (ioctl (inferior_fd, PIXRUN, &ps) < 0)
+    perror_with_name ("PIXRUN");
+}
+
+/* Replacement for system wait routine.  
+
+   The system wait returns with one or more threads stopped by
+   signals.  Put stopped threads on a stack and return them one by
+   one, so that it appears that wait returns one thread at a time.
+
+   Global variable THREAD_SWITCH_OK is set when gdb can tolerate wait
+   returning a new thread.  If it is false, then only one thread is
+   running; we will do a real wait, the thread will do something, and
+   we will return that.  */
+
+pid_t
+wait (w)
+    union wait *w;
+{
+  int pid;
+
+  if (!w)
+    return wait3 (0, 0, 0);
+
+  /* Do a real wait if we were told to, or if there are no queued threads.  */
+
+  if (! thread_switch_ok || signal_stack_is_empty ())
+    {
+      int thread;
+
+      pid = wait3 (w, 0, 0);
+
+      if (!WIFSTOPPED (*w) || pid != inferior_pid)
+       return pid;
+
+      /* The inferior has done something and stopped.  Read in all the
+        threads' registers, and queue up any signals that happened.  */
+
+      if (ioctl (inferior_fd, PIXGETTHCOUNT, &ps) < 0)
+       perror_with_name ("PIXGETTHCOUNT");
+      
+      n_threads = ps.pi_othdcnt;
+      for (thread = 0; thread < n_threads; thread++)
+       {
+         ps.pi_thread = thread;
+         if (ioctl (inferior_fd, PIXGETSUBCODE, &ps) < 0)
+           perror_with_name ("PIXGETSUBCODE");
+         thread_state[thread] = ps.pi_otstate;
+
+         if (ps.pi_otstate == PI_TALIVE)
+           {
+             select_thread (thread);
+             ps.pi_buffer = registers;
+             ps.pi_nbytes = REGISTER_BYTES;
+             ps.pi_offset = 0;
+             ps.pi_thread = thread;
+             if (ioctl (inferior_fd, PIXRDREGS, &ps) < 0)
+               perror_with_name ("PIXRDREGS");
+
+             registers_fetched ();
+
+             thread_pc[thread] = read_pc ();
+             thread_signal[thread] = ps.pi_osigno;
+             thread_sigcode[thread] = ps.pi_osigcode;
+
+             /* If the thread's stack has a context frame
+                on top, something fucked is going on.  I do not
+                know what, but do I know this: the only thing you
+                can do with such a thread is continue it.  */
+
+             thread_is_in_kernel[thread] = 
+               ((read_register (PS_REGNUM) >> 25) & 3) == 0;
+
+             /* Signals push an extended frame and then fault
+                with a ridiculous pc.  Pop the frame.  */
+
+             if (thread_pc[thread] > STACK_END_ADDR)
+               {
+                 POP_FRAME;
+                 if (is_break_pc (thread_pc[thread]))
+                   thread_pc[thread] = read_pc () - 2;
+                 else
+                   thread_pc[thread] = read_pc ();
+                 write_register (PC_REGNUM, thread_pc[thread]);
+               }
+             
+             if (ps.pi_osigno || ps.pi_osigcode)
+               {
+                 signal_stack++;
+                 signal_stack->pid = pid;
+                 signal_stack->thread = thread;
+                 signal_stack->signo = thread_signal[thread];
+                 signal_stack->subsig = thread_sigcode[thread];
+                 signal_stack->pc = thread_pc[thread];
+               }
+
+             /* The following hackery is caused by a unix 7.1 feature:
+                the inferior's fixed scheduling mode is cleared when
+                it execs the shell (since the shell is not a parallel
+                program).  So, note the 5.4 trap we get when
+                the shell does its exec, then catch the 5.0 trap 
+                that occurs when the debuggee starts, and set fixed
+                scheduling mode properly.  */
+
+             if (ps.pi_osigno == 5 && ps.pi_osigcode == 4)
+               exec_trap_timer = 1;
+             else
+               exec_trap_timer--;
+             
+             if (ps.pi_osigno == 5 && exec_trap_timer == 0)
+               set_fixed_scheduling (pid, parallel == 2);
+           }
+       }
+
+      if (signal_stack_is_empty ())
+       error ("no active threads?!");
+    }
+
+  /* Select the thread that stopped, and return *w saying why.  */
+
+  select_thread (signal_stack->thread);
+
+  stop_signal = signal_stack->signo;
+  stop_sigcode = signal_stack->subsig;
+
+  WSETSTOP (*w, signal_stack->signo);
+  w->w_thread = signal_stack->thread;
+  return (signal_stack--)->pid;
+}
+
+/* Select thread THREAD -- its registers, stack, per-thread memory.
+   This is the only routine that may assign to inferior_thread
+   or thread_regs[].  */
+
+static void
+select_thread (thread)
+     int thread;
+{
+  if (thread == inferior_thread)
+    return;
+
+  bcopy (registers, thread_regs[inferior_thread], REGISTER_BYTES);
+  ps.pi_thread = inferior_thread = thread;
+  if (have_inferior_p ())
+    ioctl (inferior_fd, PISETRWTID, &ps);
+  bcopy (thread_regs[thread], registers, REGISTER_BYTES);
+}
+  
+/* Routine to set or clear a psw bit in the psw and also all psws
+   saved on the stack.  Quits when we get to a frame in which the
+   saved psw is correct. */
+
+static void
+scan_stack (bit, val)
+    long bit, val;
+{
+  long ps = read_register (PS_REGNUM);
+  long fp;
+  if (val ? !(ps & bit) : (ps & bit))
+    {    
+      ps ^= bit;
+      write_register (PS_REGNUM, ps);
+
+      fp = read_register (FP_REGNUM);
+      while (fp & 0x80000000)
+       {
+         ps = read_memory_integer (fp + 4, 4);
+         if (val ? (ps & bit) : !(ps & bit))
+           break;
+         ps ^= bit;
+         write_memory (fp + 4, &ps, 4);
+         fp = read_memory_integer (fp + 8, 4);
+       }
+    }
+}
+
+/* Set fixed scheduling (alliant mode) of process PID to ARG (0 or 1).  */
+
+static void
+set_fixed_scheduling (pid, arg)
+      int arg;
+{
+  struct pattributes pattr;
+  getpattr (pid, &pattr);
+  pattr.pattr_pfixed = arg;
+  setpattr (pid, &pattr);
+}
+\f
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int n;
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+  n_core = 0;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+
+      if (myread (corechan, &filehdr, sizeof filehdr) < 0)
+       perror_with_name (filename);
+
+      if (!IS_CORE_SOFF_MAGIC (filehdr.h_magic))
+       error ("%s: not a core file.\n", filename);
+
+      if (myread (corechan, &opthdr, filehdr.h_opthdr) < 0)
+       perror_with_name (filename);
+
+      /* Read through the section headers.
+        For text, data, etc, record an entry in the core file map.
+        For context and tcontext, record the file address of
+        the context blocks.  */
+
+      lseek (corechan, (long) filehdr.h_scnptr, 0);
+
+      n_threads = 0;
+      for (n = 0; n < filehdr.h_nscns; n++)
+       {
+         if (myread (corechan, &scnhdr, sizeof scnhdr) < 0)
+           perror_with_name (filename);
+         if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT
+             && (scnhdr.s_flags & S_TYPMASK) <= S_COMON)
+           {
+             core_map[n_core].mem_addr = scnhdr.s_vaddr;
+             core_map[n_core].mem_end = scnhdr.s_vaddr + scnhdr.s_size;
+             core_map[n_core].file_addr = scnhdr.s_scnptr;
+             core_map[n_core].type = scnhdr.s_flags & S_TYPMASK;
+             if (core_map[n_core].type != S_TBSS
+                 && core_map[n_core].type != S_TDATA
+                 && core_map[n_core].type != S_TTEXT)
+               core_map[n_core].thread = -1;
+             else if (n_core == 0
+                      || core_map[n_core-1].mem_addr != scnhdr.s_vaddr)
+               core_map[n_core].thread = 0;
+             else 
+               core_map[n_core].thread = core_map[n_core-1].thread + 1;
+             n_core++;
+           }
+         else if ((scnhdr.s_flags & S_TYPMASK) == S_CONTEXT)
+           context_offset = scnhdr.s_scnptr;
+         else if ((scnhdr.s_flags & S_TYPMASK) == S_TCONTEXT) 
+           tcontext_offset[n_threads++] = scnhdr.s_scnptr;
+       }
+
+      /* Read the context block, struct user, struct proc,
+        and the comm regs.  */
+
+      lseek (corechan, context_offset, 0);
+      if (myread (corechan, &c, sizeof c) < 0)
+       perror_with_name (filename);
+      lseek (corechan, c.core_user_p, 0);
+      if (myread (corechan, &u, sizeof u) < 0)
+       perror_with_name (filename);
+      lseek (corechan, c.core_proc_p, 0);
+      if (myread (corechan, &pr, sizeof pr) < 0)
+       perror_with_name (filename);
+      comm_registers = pr.p_creg;
+
+      /* Core file apparently is really there.  Make it really exist
+        for xfer_core_file so we can do read_memory on it. */
+
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       corefile = concat (current_directory, "/", filename);
+
+      printf_filtered ("Program %s ", u.u_comm);
+
+      /* Read the thread registers and fill in the thread_xxx[] data.  */
+
+      for (n = 0; n < n_threads; n++)
+       {
+         select_thread (n);
+
+         lseek (corechan, tcontext_offset[n], 0);
+         if (myread (corechan, &tc, sizeof tc) < 0)
+           perror_with_name (corefile);
+         lseek (corechan, tc.core_thread_p, 0);
+         if (myread (corechan, &th, sizeof th) < 0)
+           perror_with_name (corefile);
+
+         lseek (corechan, tc.core_syscall_context_p, 0);
+         if (myread (corechan, registers, REGISTER_BYTES) < 0)
+           perror_with_name (corefile);
+
+         thread_signal[n] = th.t_cursig;
+         thread_sigcode[n] = th.t_code;
+         thread_state[n] = th.t_state;
+         thread_pc[n] = read_pc ();
+
+         if (thread_pc[n] > STACK_END_ADDR)
+           {
+             POP_FRAME;
+             if (is_break_pc (thread_pc[n]))
+               thread_pc[n] = read_pc () - 2;
+             else
+               thread_pc[n] = read_pc ();
+             write_register (PC_REGNUM, thread_pc[n]);
+           }
+
+         printf_filtered ("thread %d received signal %d, %s\n",
+                          n, thread_signal[n],
+                          thread_signal[n] < NSIG
+                          ? sys_siglist[thread_signal[n]]
+                          : "(undocumented)");
+       }
+
+      /* Select an interesting thread -- also-rans died with SIGKILL,
+        so find one that didn't.  */
+
+      for (n = 0; n < n_threads; n++)
+       if (thread_signal[n] != 0 && thread_signal[n] != SIGKILL)
+         {
+           select_thread (n);
+           stop_signal = thread_signal[n];
+           stop_sigcode = thread_sigcode[n];
+           break;
+         }
+
+      core_aouthdr.a_magic = 0;
+
+      flush_cached_frames ();
+      set_current_frame (create_new_frame (read_register (FP_REGNUM),
+                                            read_pc ()));
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+
+      print_sel_frame (1);
+    }
+  else if (from_tty)
+    printf_filtered ("No core file now.\n");
+}
diff --git a/gdb/copying.awk b/gdb/copying.awk
new file mode 100644 (file)
index 0000000..378d620
--- /dev/null
@@ -0,0 +1,55 @@
+BEGIN  {
+         FS="\"";
+         print "/* Do not modify this file; it is created automatically";
+         print "   by copying.awk.  */";
+         print "#include \"defs.h\""
+         print "#include \"command.h\""
+         print "extern int immediate_quit;";
+         print "static void";
+         print "copying_info ()";
+         print "{";
+         print "  immediate_quit++;";
+       }
+NR == 1,/^[    ]*NO WARRANTY[  ]*$/    {
+         if (! ($0 ~ /^[       ]*NO WARRANTY[  ]*$/)) 
+           {
+             printf "  printf_filtered (\"";
+             for (i = 1; i < NF; i++)
+               printf "%s\\\"", $i;
+             printf "%s\\n\");\n", $NF;
+           }
+       }
+/^[     ]*NO WARRANTY[         ]*$/    {
+         print "  immediate_quit--;";
+         print "}";
+         print "";
+         print "static void";
+         print "warranty_info ()";
+         print "{";
+         print "  immediate_quit++;";
+       }
+/^[    ]*NO WARRANTY[  ]*$/, /^[       ]*END OF TERMS AND CONDITIONS[  ]*$/{  
+         if (! ($0 ~ /^[       ]*END OF TERMS AND CONDITIONS[  ]*$/)) 
+           {
+             printf "  printf_filtered (\"";
+             for (i = 1; i < NF; i++)
+               printf "%s\\\"", $i;
+             printf "%s\\n\");\n", $NF;
+           }
+       }
+END    {
+         print "  immediate_quit--;";
+         print "}";
+         print "";
+         print "void"
+         print "_initialize_copying ()";
+         print "{";
+         print "  add_info (\"copying\", copying_info,";
+         print "           \"Conditions for redistributing copies of GDB.\");";
+         print "  add_info (\"warranty\", warranty_info,";
+         print "         \"Various kinds of warranty you do not have.\");";
+         print "}";
+       }
+
+
+           
diff --git a/gdb/copying.c b/gdb/copying.c
new file mode 100644 (file)
index 0000000..9164891
--- /dev/null
@@ -0,0 +1,217 @@
+/* Do not modify this file; it is created automatically
+   by copying.awk.  */
+#include "defs.h"
+#include "command.h"
+extern int immediate_quit;
+static void
+copying_info ()
+{
+  immediate_quit++;
+  printf_filtered ("\n");
+  printf_filtered ("               GNU GENERAL PUBLIC LICENSE\n");
+  printf_filtered ("                Version 1, February 1989\n");
+  printf_filtered ("\n");
+  printf_filtered (" Copyright (C) 1989 Free Software Foundation, Inc.\n");
+  printf_filtered ("                    675 Mass Ave, Cambridge, MA 02139, USA\n");
+  printf_filtered (" Everyone is permitted to copy and distribute verbatim copies\n");
+  printf_filtered (" of this license document, but changing it is not allowed.\n");
+  printf_filtered ("\n");
+  printf_filtered ("                       Preamble\n");
+  printf_filtered ("\n");
+  printf_filtered ("  The license agreements of most software companies try to keep users\n");
+  printf_filtered ("at the mercy of those companies.  By contrast, our General Public\n");
+  printf_filtered ("License is intended to guarantee your freedom to share and change free\n");
+  printf_filtered ("software--to make sure the software is free for all its users.  The\n");
+  printf_filtered ("General Public License applies to the Free Software Foundation's\n");
+  printf_filtered ("software and to any other program whose authors commit to using it.\n");
+  printf_filtered ("You can use it for your programs, too.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  When we speak of free software, we are referring to freedom, not\n");
+  printf_filtered ("price.  Specifically, the General Public License is designed to make\n");
+  printf_filtered ("sure that you have the freedom to give away or sell copies of free\n");
+  printf_filtered ("software, that you receive source code or can get it if you want it,\n");
+  printf_filtered ("that you can change the software or use pieces of it in new free\n");
+  printf_filtered ("programs; and that you know you can do these things.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  To protect your rights, we need to make restrictions that forbid\n");
+  printf_filtered ("anyone to deny you these rights or to ask you to surrender the rights.\n");
+  printf_filtered ("These restrictions translate to certain responsibilities for you if you\n");
+  printf_filtered ("distribute copies of the software, or if you modify it.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  For example, if you distribute copies of a such a program, whether\n");
+  printf_filtered ("gratis or for a fee, you must give the recipients all the rights that\n");
+  printf_filtered ("you have.  You must make sure that they, too, receive or can get the\n");
+  printf_filtered ("source code.  And you must tell them their rights.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  We protect your rights with two steps: (1) copyright the software, and\n");
+  printf_filtered ("(2) offer you this license which gives you legal permission to copy,\n");
+  printf_filtered ("distribute and/or modify the software.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  Also, for each author's protection and ours, we want to make certain\n");
+  printf_filtered ("that everyone understands that there is no warranty for this free\n");
+  printf_filtered ("software.  If the software is modified by someone else and passed on, we\n");
+  printf_filtered ("want its recipients to know that what they have is not the original, so\n");
+  printf_filtered ("that any problems introduced by others will not reflect on the original\n");
+  printf_filtered ("authors' reputations.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  The precise terms and conditions for copying, distribution and\n");
+  printf_filtered ("modification follow.\n");
+  printf_filtered ("\f\n");
+  printf_filtered ("               GNU GENERAL PUBLIC LICENSE\n");
+  printf_filtered ("   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n");
+  printf_filtered ("\n");
+  printf_filtered ("  0. This License Agreement applies to any program or other work which\n");
+  printf_filtered ("contains a notice placed by the copyright holder saying it may be\n");
+  printf_filtered ("distributed under the terms of this General Public License.  The\n");
+  printf_filtered ("\"Program\", below, refers to any such program or work, and a \"work based\n");
+  printf_filtered ("on the Program\" means either the Program or any work containing the\n");
+  printf_filtered ("Program or a portion of it, either verbatim or with modifications.  Each\n");
+  printf_filtered ("licensee is addressed as \"you\".\n");
+  printf_filtered ("\n");
+  printf_filtered ("  1. You may copy and distribute verbatim copies of the Program's source\n");
+  printf_filtered ("code as you receive it, in any medium, provided that you conspicuously and\n");
+  printf_filtered ("appropriately publish on each copy an appropriate copyright notice and\n");
+  printf_filtered ("disclaimer of warranty; keep intact all the notices that refer to this\n");
+  printf_filtered ("General Public License and to the absence of any warranty; and give any\n");
+  printf_filtered ("other recipients of the Program a copy of this General Public License\n");
+  printf_filtered ("along with the Program.  You may charge a fee for the physical act of\n");
+  printf_filtered ("transferring a copy.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  2. You may modify your copy or copies of the Program or any portion of\n");
+  printf_filtered ("it, and copy and distribute such modifications under the terms of Paragraph\n");
+  printf_filtered ("1 above, provided that you also do the following:\n");
+  printf_filtered ("\n");
+  printf_filtered ("    a) cause the modified files to carry prominent notices stating that\n");
+  printf_filtered ("    you changed the files and the date of any change; and\n");
+  printf_filtered ("\n");
+  printf_filtered ("    b) cause the whole of any work that you distribute or publish, that\n");
+  printf_filtered ("    in whole or in part contains the Program or any part thereof, either\n");
+  printf_filtered ("    with or without modifications, to be licensed at no charge to all\n");
+  printf_filtered ("    third parties under the terms of this General Public License (except\n");
+  printf_filtered ("    that you may choose to grant warranty protection to some or all\n");
+  printf_filtered ("    third parties, at your option).\n");
+  printf_filtered ("\n");
+  printf_filtered ("    c) If the modified program normally reads commands interactively when\n");
+  printf_filtered ("    run, you must cause it, when started running for such interactive use\n");
+  printf_filtered ("    in the simplest and most usual way, to print or display an\n");
+  printf_filtered ("    announcement including an appropriate copyright notice and a notice\n");
+  printf_filtered ("    that there is no warranty (or else, saying that you provide a\n");
+  printf_filtered ("    warranty) and that users may redistribute the program under these\n");
+  printf_filtered ("    conditions, and telling the user how to view a copy of this General\n");
+  printf_filtered ("    Public License.\n");
+  printf_filtered ("\n");
+  printf_filtered ("    d) You may charge a fee for the physical act of transferring a\n");
+  printf_filtered ("    copy, and you may at your option offer warranty protection in\n");
+  printf_filtered ("    exchange for a fee.\n");
+  printf_filtered ("\n");
+  printf_filtered ("Mere aggregation of another independent work with the Program (or its\n");
+  printf_filtered ("derivative) on a volume of a storage or distribution medium does not bring\n");
+  printf_filtered ("the other work under the scope of these terms.\n");
+  printf_filtered ("\f\n");
+  printf_filtered ("  3. You may copy and distribute the Program (or a portion or derivative of\n");
+  printf_filtered ("it, under Paragraph 2) in object code or executable form under the terms of\n");
+  printf_filtered ("Paragraphs 1 and 2 above provided that you also do one of the following:\n");
+  printf_filtered ("\n");
+  printf_filtered ("    a) accompany it with the complete corresponding machine-readable\n");
+  printf_filtered ("    source code, which must be distributed under the terms of\n");
+  printf_filtered ("    Paragraphs 1 and 2 above; or,\n");
+  printf_filtered ("\n");
+  printf_filtered ("    b) accompany it with a written offer, valid for at least three\n");
+  printf_filtered ("    years, to give any third party free (except for a nominal charge\n");
+  printf_filtered ("    for the cost of distribution) a complete machine-readable copy of the\n");
+  printf_filtered ("    corresponding source code, to be distributed under the terms of\n");
+  printf_filtered ("    Paragraphs 1 and 2 above; or,\n");
+  printf_filtered ("\n");
+  printf_filtered ("    c) accompany it with the information you received as to where the\n");
+  printf_filtered ("    corresponding source code may be obtained.  (This alternative is\n");
+  printf_filtered ("    allowed only for noncommercial distribution and only if you\n");
+  printf_filtered ("    received the program in object code or executable form alone.)\n");
+  printf_filtered ("\n");
+  printf_filtered ("Source code for a work means the preferred form of the work for making\n");
+  printf_filtered ("modifications to it.  For an executable file, complete source code means\n");
+  printf_filtered ("all the source code for all modules it contains; but, as a special\n");
+  printf_filtered ("exception, it need not include source code for modules which are standard\n");
+  printf_filtered ("libraries that accompany the operating system on which the executable\n");
+  printf_filtered ("file runs, or for standard header files or definitions files that\n");
+  printf_filtered ("accompany that operating system.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  4. You may not copy, modify, sublicense, distribute or transfer the\n");
+  printf_filtered ("Program except as expressly provided under this General Public License.\n");
+  printf_filtered ("Any attempt otherwise to copy, modify, sublicense, distribute or transfer\n");
+  printf_filtered ("the Program is void, and will automatically terminate your rights to use\n");
+  printf_filtered ("the Program under this License.  However, parties who have received\n");
+  printf_filtered ("copies, or rights to use copies, from you under this General Public\n");
+  printf_filtered ("License will not have their licenses terminated so long as such parties\n");
+  printf_filtered ("remain in full compliance.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  5. By copying, distributing or modifying the Program (or any work based\n");
+  printf_filtered ("on the Program) you indicate your acceptance of this license to do so,\n");
+  printf_filtered ("and all its terms and conditions.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  6. Each time you redistribute the Program (or any work based on the\n");
+  printf_filtered ("Program), the recipient automatically receives a license from the original\n");
+  printf_filtered ("licensor to copy, distribute or modify the Program subject to these\n");
+  printf_filtered ("terms and conditions.  You may not impose any further restrictions on the\n");
+  printf_filtered ("recipients' exercise of the rights granted herein.\n");
+  printf_filtered ("\f\n");
+  printf_filtered ("  7. The Free Software Foundation may publish revised and/or new versions\n");
+  printf_filtered ("of the General Public License from time to time.  Such new versions will\n");
+  printf_filtered ("be similar in spirit to the present version, but may differ in detail to\n");
+  printf_filtered ("address new problems or concerns.\n");
+  printf_filtered ("\n");
+  printf_filtered ("Each version is given a distinguishing version number.  If the Program\n");
+  printf_filtered ("specifies a version number of the license which applies to it and \"any\n");
+  printf_filtered ("later version\", you have the option of following the terms and conditions\n");
+  printf_filtered ("either of that version or of any later version published by the Free\n");
+  printf_filtered ("Software Foundation.  If the Program does not specify a version number of\n");
+  printf_filtered ("the license, you may choose any version ever published by the Free Software\n");
+  printf_filtered ("Foundation.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  8. If you wish to incorporate parts of the Program into other free\n");
+  printf_filtered ("programs whose distribution conditions are different, write to the author\n");
+  printf_filtered ("to ask for permission.  For software which is copyrighted by the Free\n");
+  printf_filtered ("Software Foundation, write to the Free Software Foundation; we sometimes\n");
+  printf_filtered ("make exceptions for this.  Our decision will be guided by the two goals\n");
+  printf_filtered ("of preserving the free status of all derivatives of our free software and\n");
+  printf_filtered ("of promoting the sharing and reuse of software generally.\n");
+  printf_filtered ("\n");
+  immediate_quit--;
+}
+
+static void
+warranty_info ()
+{
+  immediate_quit++;
+  printf_filtered ("                       NO WARRANTY\n");
+  printf_filtered ("\n");
+  printf_filtered ("  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");
+  printf_filtered ("FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n");
+  printf_filtered ("OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");
+  printf_filtered ("PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");
+  printf_filtered ("OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");
+  printf_filtered ("MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n");
+  printf_filtered ("TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n");
+  printf_filtered ("PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");
+  printf_filtered ("REPAIR OR CORRECTION.\n");
+  printf_filtered ("\n");
+  printf_filtered ("  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");
+  printf_filtered ("WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");
+  printf_filtered ("REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");
+  printf_filtered ("INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");
+  printf_filtered ("OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");
+  printf_filtered ("TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");
+  printf_filtered ("YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");
+  printf_filtered ("PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");
+  printf_filtered ("POSSIBILITY OF SUCH DAMAGES.\n");
+  printf_filtered ("\n");
+  immediate_quit--;
+}
+
+void
+_initialize_copying ()
+{
+  add_info ("copying", copying_info,
+           "Conditions for redistributing copies of GDB.");
+  add_info ("warranty", warranty_info,
+         "Various kinds of warranty you do not have.");
+}
diff --git a/gdb/core.c b/gdb/core.c
new file mode 100644 (file)
index 0000000..2936e46
--- /dev/null
@@ -0,0 +1,447 @@
+/* Work with core dump and executable files, for GDB.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"  /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+
+extern int xfer_memory ();
+extern void child_attach (), child_create_inferior ();
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+extern char *sys_siglist[];
+
+extern char registers[];
+
+/* Hook for `exec_file_command' command to call.  */
+
+void (*exec_file_display_hook) () = NULL;
+
+struct section_table *core_sections, *core_sections_end;
+
+/* Binary file diddling handle for the core file.  */
+
+bfd *core_bfd = NULL;
+
+/* Forward decl */
+extern struct target_ops core_ops;
+
+\f
+/* Discard all vestiges of any previous core file
+   and mark data and stack spaces as empty.  */
+
+void
+core_close (quitting)
+     int quitting;
+{
+  if (core_bfd) {
+    free (bfd_get_filename (core_bfd));
+    bfd_close (core_bfd);
+    core_bfd = NULL;
+  }
+}
+
+/* This routine opens and sets up the core file bfd */
+
+void
+core_open (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  char *p;
+  int siggy;
+  struct cleanup *old_chain;
+  char *temp;
+  bfd *temp_bfd;
+  int ontop;
+
+  if (!filename)
+    {
+      error (core_bfd? 
+       "No core file specified.  (Use `detach' to stop debugging a core file.)"
+     : "No core file specified.");
+    }
+
+  filename = tilde_expand (filename);
+  if (filename[0] != '/') {
+    temp = concat (current_directory, "/", filename);
+    free (filename);
+    filename = temp;
+  }
+
+  old_chain = make_cleanup (free, filename);
+  temp_bfd = bfd_openr (filename, NULL);
+  if (temp_bfd == NULL)
+    {
+      perror_with_name (filename);
+    }
+
+  if (!bfd_check_format (temp_bfd, bfd_core))
+    {
+      bfd_close (temp_bfd);
+      error ("\"%s\" does not appear to be a core dump", filename);
+    }
+
+  /* Looks semi-reasonable.  Toss the old core file and work on the new.  */
+
+  discard_cleanups (old_chain);                /* Don't free filename any more */
+  unpush_target (&core_ops);
+  core_bfd = temp_bfd;
+  old_chain = make_cleanup (core_close, core_bfd);
+
+  validate_files ();
+
+  /* Find the data section */
+  if (build_section_table (core_bfd, &core_sections, &core_sections_end))
+    error ("Can't find sections in `%s': %s", bfd_get_filename(core_bfd),
+          bfd_errmsg (bfd_error));
+
+  ontop = !push_target (&core_ops);
+
+  p = bfd_core_file_failing_command (core_bfd);
+  if (p)
+    printf ("Core file invoked as `%s'.\n", p);
+
+  siggy = bfd_core_file_failing_signal (core_bfd);
+  if (siggy > 0)
+    printf ("Program terminated with signal %d, %s.\n", siggy,
+           siggy < NSIG ? sys_siglist[siggy] : "(undocumented)");
+
+  if (ontop) {
+    /* Fetch all registers from core file */
+    target_fetch_registers (-1);
+    set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                         read_pc ()));
+    select_frame (get_current_frame (), 0);
+    /* FIXME, handle shared library reading here.  */
+    print_sel_frame (0);       /* Print the top frame and source line */
+  } else {
+    printf (
+"Warning: you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''\n", current_target->to_longname);
+  }
+
+  discard_cleanups (old_chain);
+}
+
+void
+core_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  dont_repeat ();
+  if (args)
+    error ("Too many arguments");
+  pop_target ();
+  if (from_tty)
+    printf ("No core file now.\n");
+}
+
+/* Backward compatability with old way of specifying core files.  */
+
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  if (!filename)
+    core_detach (filename, from_tty);
+  else
+    core_open (filename, from_tty);
+}
+
+\f
+/* Call this to specify the hook for exec_file_command to call back.
+   This is called from the x-window display code.  */
+
+void
+specify_exec_file_hook (hook)
+     void (*hook) ();
+{
+  exec_file_display_hook = hook;
+}
+
+/* The exec file must be closed before running an inferior.
+   If it is needed again after the inferior dies, it must
+   be reopened.  */
+
+void
+close_exec_file ()
+{
+#ifdef FIXME
+  if (exec_bfd)
+    bfd_tempclose (exec_bfd);
+#endif
+}
+
+void
+reopen_exec_file ()
+{
+#ifdef FIXME
+  if (exec_bfd)
+    bfd_reopen (exec_bfd);
+#endif
+}
+\f
+/* If we have both a core file and an exec file,
+   print a warning if they don't go together.
+   This should really check that the core file came
+   from that exec file, but I don't know how to do it.  */
+
+void
+validate_files ()
+{
+  if (exec_bfd && core_bfd)
+    {
+      if (core_file_matches_executable_p (core_bfd, exec_bfd))
+       printf ("Warning: core file does not match specified executable file.\n");
+      else if (bfd_get_mtime(exec_bfd) > bfd_get_mtime(core_bfd))
+       printf ("Warning: exec file is newer than core file.\n");
+    }
+}
+
+/* Return the name of the executable file as a string.
+   ERR nonzero means get error if there is none specified;
+   otherwise return 0 in that case.  */
+
+char *
+get_exec_file (err)
+     int err;
+{
+  if (exec_bfd) return bfd_get_filename(exec_bfd);
+  if (!err)     return NULL;
+
+  error ("No executable file specified.\n\
+Use the \"file\" or \"exec-file\" command.");
+  return NULL;
+}
+
+static void
+core_files_info ()
+{
+  struct section_table *p;
+
+  printf ("\tCore file `%s'.\n", bfd_get_filename(core_bfd));
+
+  for (p = core_sections; p < core_sections_end; p++)
+    printf("\tcore file  from 0x%08x to 0x%08x is %s\n",
+       p->addr, p->endaddr,
+       bfd_section_name (core_bfd, p->sec_ptr));
+}
+\f
+void
+memory_error (status, memaddr)
+     int status;
+     CORE_ADDR memaddr;
+{
+
+  if (status == EIO)
+    {
+      /* Actually, address between memaddr and memaddr + len
+        was out of bounds. */
+      error ("Cannot access memory: address 0x%x out of bounds.", memaddr);
+    }
+  else
+    {
+      if (status >= sys_nerr || status < 0)
+       error ("Error accessing memory address 0x%x: unknown error (%d).",
+              memaddr, status);
+      else
+       error ("Error accessing memory address 0x%x: %s.",
+              memaddr, sys_errlist[status]);
+    }
+}
+
+/* Same as target_read_memory, but report an error if can't read.  */
+void
+read_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int status;
+  status = target_read_memory (memaddr, myaddr, len);
+  if (status != 0)
+    memory_error (status, memaddr);
+}
+
+/* Same as target_write_memory, but report an error if can't write.  */
+void
+write_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int status;
+
+  status = target_write_memory (memaddr, myaddr, len);
+  if (status != 0)
+    memory_error (status, memaddr);
+}
+
+/* Read an integer from debugged memory, given address and number of bytes.  */
+
+long
+read_memory_integer (memaddr, len)
+     CORE_ADDR memaddr;
+     int len;
+{
+  char cbuf;
+  short sbuf;
+  int ibuf;
+  long lbuf;
+
+  if (len == sizeof (char))
+    {
+      read_memory (memaddr, &cbuf, len);
+      return cbuf;
+    }
+  if (len == sizeof (short))
+    {
+      read_memory (memaddr, (char *)&sbuf, len);
+      SWAP_TARGET_AND_HOST (&sbuf, sizeof (short));
+      return sbuf;
+    }
+  if (len == sizeof (int))
+    {
+      read_memory (memaddr, (char *)&ibuf, len);
+      SWAP_TARGET_AND_HOST (&ibuf, sizeof (int));
+      return ibuf;
+    }
+  if (len == sizeof (lbuf))
+    {
+      read_memory (memaddr, (char *)&lbuf, len);
+      SWAP_TARGET_AND_HOST (&lbuf, sizeof (lbuf));
+      return lbuf;
+    }
+  error ("Cannot handle integers of %d bytes.", len);
+  return -1;   /* for lint */
+}
+\f
+/* Read or write the core file.
+
+   Args are address within core file, address within gdb address-space,
+   length, and a flag indicating whether to read or write.
+
+   Result is a length:
+
+       0:    We cannot handle this address and length.
+       > 0:  We have handled N bytes starting at this address.
+             (If N == length, we did it all.)  We might be able
+             to handle more bytes beyond this length, but no
+             promises.
+       < 0:  We cannot handle this address, but if somebody
+             else handles (-N) bytes, we can start from there.
+
+   The actual work is done by xfer_memory in exec.c, which we share
+   in common with exec_xfer_memory().  */
+
+static int
+core_xfer_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  return xfer_memory (memaddr, myaddr, len, write,
+                     core_bfd, core_sections, core_sections_end);
+}
+\f
+/* Get the registers out of a core file.  This is the machine-
+   independent part.  Fetch_core_registers is the machine-dependent
+   part, typically implemented in the xm-file for each architecture.  */
+
+static int
+get_core_registers (regno)
+     int regno;
+{
+  sec_ptr reg_sec;
+  unsigned size;
+  char *the_regs;
+
+  reg_sec = bfd_get_section_by_name (core_bfd, ".reg");
+  size = bfd_section_size (core_bfd, reg_sec);
+  the_regs = alloca (size);
+  if (bfd_get_section_contents (core_bfd, reg_sec, the_regs,
+                               (unsigned)0, size))
+    {
+      fetch_core_registers (the_regs, size, 0);
+    }
+  else
+    {
+      fprintf (stderr, "Couldn't fetch registers from core file: %s\n",
+              bfd_errmsg (bfd_error));
+    }
+
+  /* Now do it again for the float registers, if they exist.  */
+  reg_sec = bfd_get_section_by_name (core_bfd, ".reg2");
+  if (reg_sec) {
+    size = bfd_section_size (core_bfd, reg_sec);
+    the_regs = alloca (size);
+    if (bfd_get_section_contents (core_bfd, reg_sec, the_regs,
+                                 (unsigned)0, size))
+      {
+       fetch_core_registers (the_regs, size, 2);
+      }
+    else
+      {
+       fprintf (stderr, "Couldn't fetch register set 2 from core file: %s\n",
+                bfd_errmsg (bfd_error));
+      }
+  }
+  registers_fetched();
+  return 0;  /* FIXME, what result goes here?  */
+}
+\f
+struct target_ops core_ops = {
+       "core", "Local core dump file",
+       core_open, core_close,
+       child_attach, core_detach, 0, 0, /* resume, wait */
+       get_core_registers, 
+       0, 0, 0, 0, /* store_regs, prepare_to_store, conv_to, conv_from */
+       core_xfer_memory, core_files_info,
+       0, 0, /* core_insert_breakpoint, core_remove_breakpoint, */
+       0, 0, 0, 0, 0, /* terminal stuff */
+       0, 0, 0, 0, 0, /* kill, load, add_syms, call fn, lookup sym */
+       child_create_inferior, 0, /* mourn_inferior */
+       core_stratum, 0, /* next */
+       0, 1, 1, 1, 0,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_core()
+{
+
+  add_com ("core-file", class_files, core_file_command,
+          "Use FILE as core dump for examining memory and registers.\n\
+No arg means have no core file.  This command has been superseded by the\n\
+`target core' and `detach' commands.");
+  add_target (&core_ops);
+}
diff --git a/gdb/coredep.c b/gdb/coredep.c
new file mode 100644 (file)
index 0000000..ea1c273
--- /dev/null
@@ -0,0 +1,86 @@
+/* Extract registers from a "standard" core file, for GDB.
+   Copyright (C) 1988-1991  Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* core.c is supposed to be the more machine-independent aspects of this;
+   this file is more machine-specific.  */
+
+#include "defs.h"
+#include "param.h"
+#include "gdbcore.h"
+
+/* Some of these are needed on various systems, perhaps, to expand
+   REGISTER_U_ADDR appropriately?  */
+/* #include <sys/core.h> */
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/user.h>
+
+
+/* Extract the register values out of the core file and store
+   them where `read_register' will find them.  */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size)
+     char *core_reg_sect;
+     unsigned core_reg_size;
+{
+  register int regno;
+  register unsigned int addr;
+  int bad_reg = -1;
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      addr = register_addr (regno, core_reg_size);
+      if (addr >= core_reg_size) {
+       if (bad_reg < 0)
+         bad_reg = regno;
+      } else {
+       supply_register (regno, core_reg_sect + addr);
+      }
+    }
+  if (bad_reg > 0)
+    {
+      error ("Register %s not found in core file.", reg_names[bad_reg]);
+    }
+}
+
+
+#ifdef REGISTER_U_ADDR
+
+/* Return the address in the core dump or inferior of register REGNO.
+   BLOCKEND is the address of the end of the user structure.  */
+
+unsigned int
+register_addr (regno, blockend)
+     int regno;
+     int blockend;
+{
+  int addr;
+
+  if (regno < 0 || regno >= NUM_REGS)
+    error ("Invalid register number %d.", regno);
+
+  REGISTER_U_ADDR (addr, blockend, regno);
+
+  return addr;
+}
+
+#endif /* REGISTER_U_ADDR */
diff --git a/gdb/cplus-dem.c b/gdb/cplus-dem.c
new file mode 100644 (file)
index 0000000..48109d8
--- /dev/null
@@ -0,0 +1,1001 @@
+/* Demangler for GNU C++ 
+   Copyright (C) 1989 Free Software Foundation, Inc.
+   written by James Clark (jjc@jclark.uucp)
+   
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is for g++ 1.36.1 (November 6 version). It will probably
+   require changes for any other version.
+
+   Modified for g++ 1.36.2 (November 18 version).  */
+
+/* This file exports one function
+
+   char *cplus_demangle (const char *name, int mode)
+   
+   If NAME is a mangled function name produced by GNU C++, then
+   a pointer to a malloced string giving a C++ representation
+   of the name will be returned; otherwise NULL will be returned.
+   It is the caller's responsibility to free the string which
+   is returned.
+
+   If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
+   Otherwise they are not.
+   If MODE >= 0, parameters are emitted; otherwise not.
+
+   For example,
+   
+   cplus_demangle ("foo__1Ai",  0)     => "A::foo(int)"
+   cplus_demangle ("foo__1Ai",  1)     => "A::foo(int)"
+   cplus_demangle ("foo__1Ai", -1)     => "A::foo"
+
+   cplus_demangle ("foo__1Afe",  0)    => "A::foo(float,...)"
+   cplus_demangle ("foo__1Afe",  1)    => "A::foo(float,...)"
+   cplus_demangle ("foo__1Afe", -1)    => "A::foo"
+
+   This file imports xmalloc and xrealloc, which are like malloc and
+   realloc except that they generate a fatal error if there is no
+   available memory. */
+
+/* define this if names don't start with _ */
+/* #define nounderscore 1 */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef USG
+#include <memory.h>
+#include <string.h>
+#else
+#include <strings.h>
+#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
+#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
+#define strchr index 
+#define strrchr rindex
+#endif
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifdef __STDC__
+extern char *cplus_demangle (const char *type, int mode);
+#else
+extern char *cplus_demangle ();
+#endif
+
+#ifdef __STDC__
+extern char *xmalloc (int);
+extern char *xrealloc (char *, int);
+extern void free (char *);
+#else
+extern char *xmalloc ();
+extern char *xrealloc ();
+extern void free ();
+#endif
+
+static char **typevec = 0;
+static int ntypes = 0;
+static int typevec_size = 0;
+
+static struct {
+  const char *in;
+  const char *out;
+} optable[] = {
+  "new", " new",
+  "delete", " delete",
+  "ne", "!=",
+  "eq", "==",
+  "ge", ">=",
+  "gt", ">",
+  "le", "<=",
+  "lt", "<",
+  "plus", "+",
+  "minus", "-",
+  "mult", "*",
+  "convert", "+",      /* unary + */
+  "negate", "-",       /* unary - */
+  "trunc_mod", "%",
+  "trunc_div", "/",
+  "truth_andif", "&&",
+  "truth_orif", "||",
+  "truth_not", "!",
+  "postincrement", "++",
+  "postdecrement", "--",
+  "bit_ior", "|",
+  "bit_xor", "^",
+  "bit_and", "&",
+  "bit_not", "~",
+  "call", "()",
+  "cond", "?:",
+  "alshift", "<<",
+  "arshift", ">>",
+  "component", "->",
+  "indirect", "*",
+  "method_call", "->()",
+  "addr", "&",         /* unary & */
+  "array", "[]",
+  "nop", "",                   /* for operator= */
+};
+
+/* Beware: these aren't '\0' terminated. */
+
+typedef struct {
+  char *b;                     /* pointer to start of string */
+  char *p;                     /* pointer after last character */
+  char *e;                     /* pointer after end of allocated space */
+} string;
+
+#ifdef __STDC__
+static void string_need (string *s, int n);
+static void string_delete (string *s);
+static void string_init (string *s);
+static void string_clear (string *s);
+static int string_empty (string *s);
+static void string_append (string *p, const char *s);
+static void string_appends (string *p, string *s);
+static void string_appendn (string *p, const char *s, int n);
+static void string_prepend (string *p, const char *s);
+#if 0
+static void string_prepends (string *p, string *s);
+#endif
+static void string_prependn (string *p, const char *s, int n);
+static int get_count (const char **type, int *count);
+static int do_args (const char **type, string *decl, int arg_mode);
+static int do_type (const char **type, string *result, int arg_mode);
+static int do_arg (const char **type, string *result, int arg_mode);
+static void munge_function_name (string *name, int arg_mode);
+static void remember_type (const char *type, int len);
+#else
+static void string_need ();
+static void string_delete ();
+static void string_init ();
+static void string_clear ();
+static int string_empty ();
+static void string_append ();
+static void string_appends ();
+static void string_appendn ();
+static void string_prepend ();
+#if 0
+static void string_prepends ();
+#endif
+static void string_prependn ();
+static int get_count ();
+static int do_args ();
+static int do_type ();
+static int do_arg ();
+static int do_args ();
+static void munge_function_name ();
+static void remember_type ();
+#endif
+
+char *
+cplus_demangle (type, arg_mode)
+     const char *type;
+     int arg_mode;
+{
+  string decl;
+  int n;
+  int success = 0;
+  int constructor = 0;
+  int const_flag = 0;
+  int i;
+  const char *p;
+#ifndef LONGERNAMES
+  const char *premangle;
+#endif
+
+# define print_ansi_qualifiers (arg_mode >  0)
+# define print_arg_types       (arg_mode >= 0)
+
+  if (type == NULL || *type == '\0')
+    return NULL;
+#ifndef nounderscore
+  if (*type++ != '_')
+    return NULL;
+#endif
+  p = type;
+  while (*p != '\0' && !(*p == '_' && p[1] == '_'))
+    p++;
+  if (*p == '\0')
+    {
+      /* destructor */
+      if (type[0] == '_' && type[1] == '$' && type[2] == '_')
+       {
+         int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
+         char *tem = (char *) xmalloc (n);
+         strcpy (tem, type + 3);
+         strcat (tem, "::~");
+         strcat (tem, type + 3);
+         strcat (tem, "()");
+         return tem;
+       }
+      /* static data member */
+      if (*type != '_' && (p = strchr (type, '$')) != NULL)
+       {
+         int n = strlen (type) + 2;
+         char *tem = (char *) xmalloc (n);
+         memcpy (tem, type, p - type);
+         strcpy (tem + (p - type), "::");
+         strcpy (tem + (p - type) + 2, p + 1);
+         return tem;
+       }
+      /* virtual table "_vt$" */
+      if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
+       {
+         int n = strlen (type + 4) + 14 + 1;
+         char *tem = (char *) xmalloc (n);
+         strcpy (tem, type + 4);
+         strcat (tem, " virtual table");
+         return tem;
+       }
+      return NULL;
+    }
+
+  string_init (&decl);
+
+  if (p == type)
+    {
+      if (!isdigit (p[2]))
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      constructor = 1;
+    }
+  else
+    {
+      string_appendn (&decl, type, p - type);
+      munge_function_name (&decl, arg_mode);
+    }
+  p += 2;
+
+#ifndef LONGERNAMES
+  premangle = p;
+#endif
+  switch (*p)
+    {
+    case 'C':
+      /* a const member function */
+      if (!isdigit (p[1]))
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      p += 1;
+      const_flag = 1;
+      /* fall through */
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      n = 0;
+      do
+       {
+         n *= 10;
+         n += *p - '0';
+         p += 1;
+       }
+      while (isdigit (*p));
+      if (strlen (p) < n)
+       {
+         string_delete (&decl);
+         return NULL;
+       }
+      if (constructor)
+       {
+         string_appendn (&decl, p, n);
+         string_append (&decl, "::");
+         string_appendn (&decl, p, n);
+       }
+      else
+       {
+         string_prepend (&decl, "::");
+         string_prependn (&decl, p, n);
+       }
+      p += n;
+#ifndef LONGERNAMES
+      remember_type (premangle, p - premangle);
+#endif
+      success = do_args (&p, &decl, arg_mode);
+      if (const_flag && print_arg_types)
+       string_append (&decl, " const");
+      break;
+    case 'F':
+      p += 1;
+      success = do_args (&p, &decl, arg_mode);
+      break;
+    }
+
+  for (i = 0; i < ntypes; i++)
+    if (typevec[i] != NULL)
+      free (typevec[i]);
+  ntypes = 0;
+  if (typevec != NULL)
+    {
+      free ((char *)typevec);
+      typevec = NULL;
+      typevec_size = 0;
+    }
+
+  if (success)
+    {
+      string_appendn (&decl, "", 1);
+      return decl.b;
+    }
+  else
+    {
+      string_delete (&decl);
+      return NULL;
+    }
+}
+
+static int
+get_count (type, count)
+     const char **type;
+     int *count;
+{
+  if (!isdigit (**type))
+    return 0;
+  *count = **type - '0';
+  *type += 1;
+  /* see flush_repeats in cplus-method.c */
+  if (isdigit (**type))
+    {
+      const char *p = *type;
+      int n = *count;
+      do 
+       {
+         n *= 10;
+         n += *p - '0';
+         p += 1;
+       } 
+      while (isdigit (*p));
+      if (*p == '_')
+       {
+         *type = p + 1;
+         *count = n;
+       }
+    }
+  return 1;
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (type, result, arg_mode)
+     const char **type;
+     string *result;
+     int arg_mode;
+{
+  int n;
+  int done;
+  int non_empty = 0;
+  int success;
+  string decl;
+  const char *remembered_type;
+
+  string_init (&decl);
+  string_init (result);
+
+  done = 0;
+  success = 1;
+  while (success && !done)
+    {
+      int member;
+      switch (**type)
+       {
+       case 'P':
+         *type += 1;
+         string_prepend (&decl, "*");
+         break;
+
+       case 'R':
+         *type += 1;
+         string_prepend (&decl, "&");
+         break;
+
+       case 'T':
+         *type += 1;
+         if (!get_count (type, &n) || n >= ntypes)
+           success = 0;
+         else
+           {
+             remembered_type = typevec[n];
+             type = &remembered_type;
+           }
+         break;
+
+       case 'F':
+         *type += 1;
+         if (!string_empty (&decl) && decl.b[0] == '*')
+           {
+             string_prepend (&decl, "(");
+             string_append (&decl, ")");
+           }
+         if (!do_args (type, &decl, arg_mode) || **type != '_')
+           success = 0;
+         else
+           *type += 1;
+         break;
+
+       case 'M':
+       case 'O':
+         {
+           int constp = 0;
+           int volatilep = 0;
+
+           member = **type == 'M';
+           *type += 1;
+           if (!isdigit (**type))
+             {
+               success = 0;
+               break;
+             }
+           n = 0;
+           do
+             {
+               n *= 10;
+               n += **type - '0';
+               *type += 1;
+             } 
+           while (isdigit (**type));
+           if (strlen (*type) < n)
+             {
+               success = 0;
+               break;
+             }
+           string_append (&decl, ")");
+           string_prepend (&decl, "::");
+           string_prependn (&decl, *type, n);
+           string_prepend (&decl, "(");
+           *type += n;
+           if (member)
+             {
+               if (**type == 'C')
+                 {
+                   *type += 1;
+                   constp = 1;
+                 }
+               if (**type == 'V')
+                 {
+                   *type += 1;
+                   volatilep = 1;
+                 }
+               if (*(*type)++ != 'F')
+                 {
+                   success = 0;
+                   break;
+                 }
+             }
+           if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
+             {
+               success = 0;
+               break;
+             }
+           *type += 1;
+           if (! print_ansi_qualifiers)
+             break;
+           if (constp)
+             {
+               if (non_empty)
+                 string_append (&decl, " ");
+               else
+                 non_empty = 1;
+               string_append (&decl, "const");
+             }
+           if (volatilep)
+             {
+               if (non_empty)
+                 string_append (&decl, " ");
+               else
+                 non_empty = 1;
+               string_append (&decl, "volatile");
+             }
+           break;
+         }
+
+       case 'C':
+         if ((*type)[1] == 'P')
+           {
+             *type += 1;
+             if (print_ansi_qualifiers)
+               {
+                 if (!string_empty (&decl))
+                   string_prepend (&decl, " ");
+                 string_prepend (&decl, "const");
+               }
+             break;
+           }
+
+         /* fall through */
+       default:
+         done = 1;
+         break;
+       }
+    }
+
+  done = 0;
+  non_empty = 0;
+  while (success && !done)
+    {
+      switch (**type)
+       {
+       case 'C':
+         *type += 1;
+         if (print_ansi_qualifiers)
+           {
+             if (non_empty)
+               string_append (result, " ");
+             else
+               non_empty = 1;
+             string_append (result, "const");
+           }
+         break;
+       case 'U':
+         *type += 1;
+         if (non_empty)
+           string_append (result, " ");
+         else
+           non_empty = 1;
+         string_append (result, "unsigned");
+         break;
+       case 'V':
+         *type += 1;
+         if (print_ansi_qualifiers)
+           {
+             if (non_empty)
+               string_append (result, " ");
+             else
+               non_empty = 1;
+             string_append (result, "volatile");
+           }
+         break;
+       default:
+         done = 1;
+         break;
+       }
+    }
+
+  if (success)
+    switch (**type)
+      {
+      case '\0':
+      case '_':
+       break;
+      case 'v':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "void");
+       break;
+      case 'x':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "long long");
+       break;
+      case 'l':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "long");
+       break;
+      case 'i':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "int");
+       break;
+      case 's':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "short");
+       break;
+      case 'c':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "char");
+       break;
+      case 'r':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "long double");
+       break;
+      case 'd':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "double");
+       break;
+      case 'f':
+       *type += 1;
+       if (non_empty)
+         string_append (result, " ");
+       string_append (result, "float");
+       break;
+      case 'G':
+       *type += 1;
+       if (!isdigit (**type))
+         {
+           success = 0;
+           break;
+         }
+       /* fall through */
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+       n = 0;
+       do
+         {
+           n *= 10;
+           n += **type - '0';
+           *type += 1;
+         }
+       while (isdigit (**type));
+       if (strlen (*type) < n)
+         {
+           success = 0;
+           break;
+         }
+       if (non_empty)
+         string_append (result, " ");
+       string_appendn (result, *type, n);
+       *type += n;
+       break;
+      default:
+       success = 0;
+       break;
+      }
+
+  if (success)
+    {
+      if (!string_empty (&decl))
+       {
+         string_append (result, " ");
+         string_appends (result, &decl);
+       }
+      string_delete (&decl);
+      return 1;
+    }
+  else
+    {
+      string_delete (&decl);
+      string_delete (result);
+      return 0;
+    }
+}
+
+/* `result' will be initialised in do_type; it will be freed on failure */
+
+static int
+do_arg (type, result, arg_mode)
+     const char **type;
+     string *result;
+     int arg_mode;
+{
+  const char *start = *type;
+
+  if (!do_type (type, result, arg_mode))
+    return 0;
+  remember_type (start, *type - start);
+  return 1;
+}
+
+static void
+remember_type (start, len)
+     const char *start;
+     int len;
+{
+  char *tem;
+
+  if (ntypes >= typevec_size)
+    {
+      if (typevec_size == 0)
+       {
+         typevec_size = 3;
+         typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
+       }
+      else
+       {
+         typevec_size *= 2;
+         typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
+       }
+    }
+  tem = (char *) xmalloc (len + 1);
+  memcpy (tem, start, len);
+  tem[len] = '\0';
+  typevec[ntypes++] = tem;
+}
+
+/* `decl' must be already initialised, usually non-empty;
+   it won't be freed on failure */
+
+static int
+do_args (type, decl, arg_mode)
+     const char **type;
+     string *decl;
+     int arg_mode;
+{
+  string arg;
+  int need_comma = 0;
+
+  if (print_arg_types)
+    string_append (decl, "(");
+
+  while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
+    {
+      if (**type == 'N')
+       {
+         int r;
+         int t;
+         *type += 1;
+         if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
+           return 0;
+         while (--r >= 0)
+           {
+             const char *tem = typevec[t];
+             if (need_comma && print_arg_types)
+               string_append (decl, ", ");
+             if (!do_arg (&tem, &arg, arg_mode))
+               return 0;
+             if (print_arg_types)
+               string_appends (decl, &arg);
+             string_delete (&arg);
+             need_comma = 1;
+           }
+       }
+      else
+       {
+         if (need_comma & print_arg_types)
+           string_append (decl, ", ");
+         if (!do_arg (type, &arg, arg_mode))
+           return 0;
+         if (print_arg_types)
+           string_appends (decl, &arg);
+         string_delete (&arg);
+         need_comma = 1;
+       }
+    }
+
+  if (**type == 'v')
+    *type += 1;
+  else if (**type == 'e')
+    {
+      *type += 1;
+      if (print_arg_types)
+       {
+         if (need_comma)
+           string_append (decl, ",");
+         string_append (decl, "...");
+       }
+    }
+
+  if (print_arg_types)
+    string_append (decl, ")");
+  return 1;
+}
+
+static void
+munge_function_name (name, arg_mode)
+     string *name;
+     int arg_mode;
+{
+  if (!string_empty (name) && name->p - name->b >= 3 
+      && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
+    {
+      int i;
+      /* see if it's an assignment expression */
+      if (name->p - name->b >= 10 /* op$assign_ */
+         && memcmp (name->b + 3, "assign_", 7) == 0)
+       {
+         for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+           {
+             int len = name->p - name->b - 10;
+             if (strlen (optable[i].in) == len
+                 && memcmp (optable[i].in, name->b + 10, len) == 0)
+               {
+                 string_clear (name);
+                 string_append (name, "operator");
+                 string_append (name, optable[i].out);
+                 string_append (name, "=");
+                 return;
+               }
+           }
+       }
+      else
+       {
+         for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+           {
+             int len = name->p - name->b - 3;
+             if (strlen (optable[i].in) == len 
+                 && memcmp (optable[i].in, name->b + 3, len) == 0)
+               {
+                 string_clear (name);
+                 string_append (name, "operator");
+                 string_append (name, optable[i].out);
+                 return;
+               }
+           }
+       }
+      return;
+    }
+  else if (!string_empty (name) && name->p - name->b >= 5
+          && memcmp (name->b, "type$", 5) == 0)
+    {
+      /* type conversion operator */
+      string type;
+      const char *tem = name->b + 5;
+      if (do_type (&tem, &type, arg_mode))
+       {
+         string_clear (name);
+         string_append (name, "operator ");
+         string_appends (name, &type);
+         string_delete (&type);
+         return;
+       }
+    }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+     string *s;
+     int n;
+{
+  if (s->b == NULL)
+    {
+      if (n < 32)
+       n = 32;
+      s->p = s->b = (char *) xmalloc (n);
+      s->e = s->b + n;
+    }
+  else if (s->e - s->p < n)
+    {
+      int tem = s->p - s->b;
+      n += tem;
+      n *= 2;
+      s->b = (char *) xrealloc (s->b, n);
+      s->p = s->b + tem;
+      s->e = s->b + n;
+    }
+}
+
+static void
+string_delete (s)
+     string *s;
+{
+  if (s->b != NULL)
+    {
+      free (s->b);
+      s->b = s->e = s->p = NULL;
+    }
+}
+
+static void
+string_init (s)
+     string *s;
+{
+  s->b = s->p = s->e = NULL;
+}
+
+static void 
+string_clear (s)
+     string *s;
+{
+  s->p = s->b;
+}
+
+static int
+string_empty (s)
+     string *s;
+{
+  return s->b == s->p;
+}
+
+static void
+string_append (p, s)
+     string *p;
+     const char *s;
+{
+  int n;
+  if (s == NULL || *s == '\0')
+    return;
+  n = strlen (s);
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_appends (p, s)
+     string *p, *s;
+{
+  int n;
+  if (s->b == s->p)
+    return;
+  n = s->p - s->b;
+  string_need (p, n);
+  memcpy (p->p, s->b, n);
+  p->p += n;
+}
+
+static void
+string_appendn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  if (n == 0)
+    return;
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_prepend (p, s)
+     string *p;
+     const char *s;
+{
+  if (s == NULL || *s == '\0')
+    return;
+  string_prependn (p, s, strlen (s));
+}
+
+#if 0
+static void
+string_prepends (p, s)
+     string *p, *s;
+{
+  if (s->b == s->p)
+    return;
+  string_prependn (p, s->b, s->p - s->b);
+}
+#endif
+
+static void
+string_prependn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  char *q;
+
+  if (n == 0)
+    return;
+  string_need (p, n);
+  for (q = p->p - 1; q >= p->b; q--)
+    q[n] = q[0];
+  memcpy (p->b, s, n);
+  p->p += n;
+}
diff --git a/gdb/createtags b/gdb/createtags
new file mode 100755 (executable)
index 0000000..6f02ff2
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Here we check to see if we are compiling in a directory that contains
+# symlinks to the source files instead of the actual files.  If this is so, 
+# we setup the TAGS entries to point to the actual source directory.
+#
+filelist=""
+if test "`find main.c -type l -print `" != "" ; then
+       prefix=`ls -l main.c | awk '{print $11}' | sed 's;main.c$;;'`
+else
+       prefix=""
+fi
+
+# Replace .o at end of filename with .c
+for i in $@ ; do
+       file=`echo $i-x- | sed -e 's/\.o-x-/\.c-x-/' | sed -e 's/-x-//'`
+       filelist="$filelist $prefix$file"
+done
+
+etags $filelist
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
new file mode 100644 (file)
index 0000000..37f456b
--- /dev/null
@@ -0,0 +1,5348 @@
+/* Read dbx symbol tables and convert to internal format, for GDB.
+   Copyright (C) 1986-1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+/* Symbol read-in occurs in two phases:
+   1.  A scan (read_dbx_symtab()) of the entire executable, whose sole
+       purpose is to make a list of symbols (partial symbol table)
+       which will cause symbols
+       to be read in if referenced.  This scan happens when the
+       "symbol-file" command is given (symbol_file_command()).
+   1a. The "add-file" command.  Similar to #1.
+   2.  Full read-in of symbols.  (dbx_psymtab_to_symtab()).  This happens
+       when a symbol in a file for which symbols have not yet been
+       read in is referenced.  */
+
+/* There used to be some PROFILE_TYPES code in this file which counted
+   the number of occurances of various symbols.  I'd suggest instead:
+     nm -ap foo | awk 'print $5' | sort | uniq -c
+   to print how many of each n_type, or something like
+     nm -ap foo | awk '$5 == "LSYM" {print $6 $7 $8 $9 $10 $11}' | \
+     awk 'BEGIN {FS=":"}
+     {print substr($2,1,1)}' | sort | uniq -c
+   to print the number of each kind of symbol descriptor (i.e. the letter
+   after ':').  */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+
+#ifdef USG
+#include <sys/types.h>
+#include <fcntl.h>
+#define L_SET 0
+#define L_INCR 1
+#endif
+
+#include "a.out.gnu.h"         
+#include "stab.gnu.h"          /* We always use GNU stabs, not native, now */
+#include <ctype.h>
+
+#ifndef NO_GNU_STABS
+/*
+ * Define specifically gnu symbols here.
+ */
+
+/* The following type indicates the definition of a symbol as being
+   an indirect reference to another symbol.  The other symbol
+   appears as an undefined reference, immediately following this symbol.
+
+   Indirection is asymmetrical.  The other symbol's value will be used
+   to satisfy requests for the indirect symbol, but not vice versa.
+   If the other symbol does not have a definition, libraries will
+   be searched to find a definition.  */
+#ifndef N_INDR
+#define N_INDR 0xa
+#endif
+
+/* The following symbols refer to set elements.
+   All the N_SET[ATDB] symbols with the same name form one set.
+   Space is allocated for the set in the text section, and each set
+   element's value is stored into one word of the space.
+   The first word of the space is the length of the set (number of elements).
+
+   The address of the set is made into an N_SETV symbol
+   whose name is the same as the name of the set.
+   This symbol acts like a N_DATA global symbol
+   in that it can satisfy undefined external references.  */
+
+#ifndef N_SETA
+#define        N_SETA  0x14            /* Absolute set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+#ifndef N_SETT
+#define        N_SETT  0x16            /* Text set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+#ifndef N_SETD
+#define        N_SETD  0x18            /* Data set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+#ifndef N_SETB
+#define        N_SETB  0x1A            /* Bss set element symbol */
+#endif                         /* This is input to LD, in a .o file.  */
+
+/* Macros dealing with the set element symbols defined in a.out.h */
+#define        SET_ELEMENT_P(x)        ((x)>=N_SETA&&(x)<=(N_SETB|N_EXT))
+#define TYPE_OF_SET_ELEMENT(x) ((x)-N_SETA+N_ABS)
+
+#ifndef N_SETV
+#define N_SETV 0x1C            /* Pointer to set vector in data area.  */
+#endif                         /* This is output from LD.  */
+
+#ifndef N_WARNING
+#define N_WARNING 0x1E         /* Warning message to print if file included */
+#endif                         /* This is input to ld */
+
+#endif /* NO_GNU_STABS */
+
+#include <obstack.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include "symtab.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "target.h"
+#include "gdbcore.h"           /* for bfd stuff */
+#include "liba.out.h"          /* FIXME Secret internal BFD stuff for a.out */
+#include "symfile.h"
+
+struct dbx_symfile_info {
+  asection *text_sect;         /* Text section accessor */
+  int symcount;                        /* How many symbols are there in the file */
+  char *stringtab;             /* The actual string table */
+  int stringtab_size;          /* Its size */
+  off_t symtab_offset;         /* Offset in file to symbol table */
+  int desc;                    /* File descriptor of symbol file */
+};
+
+extern void qsort ();
+extern double atof ();
+extern struct cmd_list_element *cmdlist;
+
+extern void symbol_file_command ();
+
+/* Forward declarations */
+
+static void add_symbol_to_list ();
+static void read_dbx_symtab ();
+static void init_psymbol_list ();
+static void process_one_symbol ();
+static struct type *read_type ();
+static struct type *read_range_type ();
+static struct type *read_enum_type ();
+static struct type *read_struct_type ();
+static struct type *read_array_type ();
+static long read_number ();
+static void finish_block ();
+static struct blockvector *make_blockvector ();
+static struct symbol *define_symbol ();
+static void start_subfile ();
+static int hashname ();
+static struct pending *copy_pending ();
+static void fix_common_block ();
+static void add_undefined_type ();
+static void cleanup_undefined_types ();
+static void scan_file_globals ();
+static void read_ofile_symtab ();
+static void dbx_psymtab_to_symtab ();
+
+/* C++ */
+static struct type **read_args ();
+
+static const char vptr_name[] = { '_','v','p','t','r',CPLUS_MARKER };
+static const char vb_name[] =   { '_','v','b',CPLUS_MARKER };
+
+/* Macro to determine which symbols to ignore when reading the first symbol
+   of a file.  Some machines override this definition. */
+#ifndef IGNORE_SYMBOL
+/* This code is used on Ultrix systems.  Ignore it */
+#define IGNORE_SYMBOL(type)  (type == (int)N_NSYMS)
+#endif
+
+/* Macro for name of symbol to indicate a file compiled with gcc. */
+#ifndef GCC_COMPILED_FLAG_SYMBOL
+#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled."
+#endif
+
+/* Convert stab register number (from `r' declaration) to a gdb REGNUM.  */
+
+#ifndef STAB_REG_TO_REGNUM
+#define STAB_REG_TO_REGNUM(VALUE) (VALUE)
+#endif
+
+/* Define this as 1 if a pcc declaration of a char or short argument
+   gives the correct address.  Otherwise assume pcc gives the
+   address of the corresponding int, which is not the same on a
+   big-endian machine.  */
+
+#ifndef BELIEVE_PCC_PROMOTION
+#define BELIEVE_PCC_PROMOTION 0
+#endif
+\f
+/* Nonzero means give verbose info on gdb action.  From main.c.  */
+extern int info_verbose;
+
+/* Name of source file whose symbol data we are now processing.
+   This comes from a symbol of type N_SO.  */
+
+static char *last_source_file;
+
+/* Core address of start of text of current source file.
+   This too comes from the N_SO symbol.  */
+
+static CORE_ADDR last_source_start_addr;
+
+/* The entry point of a file we are reading.  */
+CORE_ADDR entry_point;
+
+/* The list of sub-source-files within the current individual compilation.
+   Each file gets its own symtab with its own linetable and associated info,
+   but they all share one blockvector.  */
+
+struct subfile
+{
+  struct subfile *next;
+  char *name;
+  char *dirname;
+  struct linetable *line_vector;
+  int line_vector_length;
+  int line_vector_index;
+  int prev_line_number;
+};
+
+static struct subfile *subfiles;
+
+static struct subfile *current_subfile;
+
+/* Count symbols as they are processed, for error messages.  */
+
+static unsigned int symnum;
+
+/* Vector of types defined so far, indexed by their dbx type numbers.
+   (In newer sun systems, dbx uses a pair of numbers in parens,
+    as in "(SUBFILENUM,NUMWITHINSUBFILE)".  Then these numbers must be
+    translated through the type_translations hash table to get
+    the index into the type vector.)  */
+
+static struct typevector *type_vector;
+
+/* Number of elements allocated for type_vector currently.  */
+
+static int type_vector_length;
+
+/* Vector of line number information.  */
+
+static struct linetable *line_vector;
+
+/* Index of next entry to go in line_vector_index.  */
+
+static int line_vector_index;
+
+/* Last line number recorded in the line vector.  */
+
+static int prev_line_number;
+
+/* Number of elements allocated for line_vector currently.  */
+
+static int line_vector_length;
+
+/* Hash table of global symbols whose values are not known yet.
+   They are chained thru the SYMBOL_VALUE_CHAIN, since we don't
+   have the correct data for that slot yet.  */
+/* The use of the LOC_BLOCK code in this chain is nonstandard--
+   it refers to a FORTRAN common block rather than the usual meaning.  */
+
+#define HASHSIZE 127
+static struct symbol *global_sym_chain[HASHSIZE];
+
+/* Record the symbols defined for each context in a list.
+   We don't create a struct block for the context until we
+   know how long to make it.  */
+
+#define PENDINGSIZE 100
+
+struct pending
+{
+  struct pending *next;
+  int nsyms;
+  struct symbol *symbol[PENDINGSIZE];
+};
+
+/* List of free `struct pending' structures for reuse.  */
+struct pending *free_pendings;
+
+/* Here are the three lists that symbols are put on.  */
+
+struct pending *file_symbols;  /* static at top level, and types */
+
+struct pending *global_symbols;        /* global functions and variables */
+
+struct pending *local_symbols; /* everything local to lexical context */
+
+/* List of symbols declared since the last BCOMM.  This list is a tail
+   of local_symbols.  When ECOMM is seen, the symbols on the list
+   are noted so their proper addresses can be filled in later,
+   using the common block base address gotten from the assembler
+   stabs.  */
+
+struct pending *common_block;
+int common_block_i;
+
+/* Stack representing unclosed lexical contexts
+   (that will become blocks, eventually).  */
+
+struct context_stack
+{
+  struct pending *locals;
+  struct pending_block *old_blocks;
+  struct symbol *name;
+  CORE_ADDR start_addr;
+  CORE_ADDR end_addr;          /* Temp slot for exception handling. */
+  int depth;
+};
+
+struct context_stack *context_stack;
+
+/* Index of first unused entry in context stack.  */
+int context_stack_depth;
+
+/* Currently allocated size of context stack.  */
+
+int context_stack_size;
+
+/* Nonzero if within a function (so symbols should be local,
+   if nothing says specifically).  */
+
+int within_function;
+
+/* List of blocks already made (lexical contexts already closed).
+   This is used at the end to make the blockvector.  */
+
+struct pending_block
+{
+  struct pending_block *next;
+  struct block *block;
+};
+
+struct pending_block *pending_blocks;
+
+extern CORE_ADDR startup_file_start;   /* From blockframe.c */
+extern CORE_ADDR startup_file_end;     /* From blockframe.c */
+
+/* Global variable which, when set, indicates that we are processing a
+   .o file compiled with gcc */
+
+static unsigned char processing_gcc_compilation;
+
+/* Make a list of forward references which haven't been defined.  */
+static struct type **undef_types;
+static int undef_types_allocated, undef_types_length;
+
+/* String table for the main symbol file.  It is kept in memory
+   permanently, to speed up symbol reading.  Other files' symbol tables
+   are read in on demand.  FIXME, this should be cleaner.  */
+
+static char *symfile_string_table;
+static int symfile_string_table_size;
+
+  /* Setup a define to deal cleanly with the underscore problem */
+
+#ifdef NAMES_HAVE_UNDERSCORE
+#define HASH_OFFSET 1
+#else
+#define HASH_OFFSET 0
+#endif
+
+/* Complaints about the symbols we have encountered.  */
+
+struct complaint innerblock_complaint =
+  {"inner block not inside outer block in %s", 0, 0};
+
+struct complaint blockvector_complaint = 
+  {"block at %x out of order", 0, 0};
+
+struct complaint lbrac_complaint = 
+  {"bad block start address patched", 0, 0};
+
+#if 0
+struct complaint dbx_class_complaint =
+  {"encountered DBX-style class variable debugging information.\n\
+You seem to have compiled your program with \
+\"g++ -g0\" instead of \"g++ -g\".\n\
+Therefore GDB will not know about your class variables", 0, 0};
+#endif
+
+struct complaint string_table_offset_complaint =
+  {"bad string table offset in symbol %d", 0, 0};
+
+struct complaint unknown_symtype_complaint =
+  {"unknown symbol type 0x%x", 0, 0};
+
+struct complaint lbrac_rbrac_complaint =
+  {"block start larger than block end", 0, 0};
+
+struct complaint const_vol_complaint =
+  {"const/volatile indicator missing, got '%c'", 0, 0};
+
+struct complaint error_type_complaint =
+  {"C++ type mismatch between compiler and debugger", 0, 0};
+
+struct complaint invalid_member_complaint =
+  {"invalid (minimal) member type data format at symtab pos %d.", 0, 0};
+\f
+/* Support for Sun changes to dbx symbol format */
+
+/* For each identified header file, we have a table of types defined
+   in that header file.
+
+   header_files maps header file names to their type tables.
+   It is a vector of n_header_files elements.
+   Each element describes one header file.
+   It contains a vector of types.
+
+   Sometimes it can happen that the same header file produces
+   different results when included in different places.
+   This can result from conditionals or from different
+   things done before including the file.
+   When this happens, there are multiple entries for the file in this table,
+   one entry for each distinct set of results.
+   The entries are distinguished by the INSTANCE field.
+   The INSTANCE field appears in the N_BINCL and N_EXCL symbol table and is
+   used to match header-file references to their corresponding data.  */
+
+struct header_file
+{
+  char *name;                  /* Name of header file */
+  int instance;                        /* Numeric code distinguishing instances
+                                  of one header file that produced
+                                  different results when included.
+                                  It comes from the N_BINCL or N_EXCL.  */
+  struct type **vector;                /* Pointer to vector of types */
+  int length;                  /* Allocated length (# elts) of that vector */
+};
+
+static struct header_file *header_files = 0;
+
+static int n_header_files;
+
+static int n_allocated_header_files;
+
+/* During initial symbol readin, we need to have a structure to keep
+   track of which psymtabs have which bincls in them.  This structure
+   is used during readin to setup the list of dependencies within each
+   partial symbol table. */
+
+struct header_file_location
+{
+  char *name;                  /* Name of header file */
+  int instance;                        /* See above */
+  struct partial_symtab *pst;  /* Partial symtab that has the
+                                  BINCL/EINCL defs for this file */
+};
+
+/* The actual list and controling variables */
+static struct header_file_location *bincl_list, *next_bincl;
+static int bincls_allocated;
+
+/* Within each object file, various header files are assigned numbers.
+   A type is defined or referred to with a pair of numbers
+   (FILENUM,TYPENUM) where FILENUM is the number of the header file
+   and TYPENUM is the number within that header file.
+   TYPENUM is the index within the vector of types for that header file.
+
+   FILENUM == 1 is special; it refers to the main source of the object file,
+   and not to any header file.  FILENUM != 1 is interpreted by looking it up
+   in the following table, which contains indices in header_files.  */
+
+static int *this_object_header_files = 0;
+
+static int n_this_object_header_files;
+
+static int n_allocated_this_object_header_files;
+
+/* When a header file is getting special overriding definitions
+   for one source file, record here the header_files index
+   of its normal definition vector.
+   At other times, this is -1.  */
+
+static int header_file_prev_index;
+
+/* Free up old header file tables, and allocate new ones.
+   We're reading a new symbol file now.  */
+
+void
+free_and_init_header_files ()
+{
+  register int i;
+  for (i = 0; i < n_header_files; i++)
+    free (header_files[i].name);
+  if (header_files)                    /* First time null */
+    free (header_files);
+  if (this_object_header_files)                /* First time null */
+    free (this_object_header_files);
+
+  n_allocated_header_files = 10;
+  header_files = (struct header_file *) xmalloc (10 * sizeof (struct header_file));
+  n_header_files = 0;
+
+  n_allocated_this_object_header_files = 10;
+  this_object_header_files = (int *) xmalloc (10 * sizeof (int));
+}
+
+/* Called at the start of each object file's symbols.
+   Clear out the mapping of header file numbers to header files.  */
+
+static void
+new_object_header_files ()
+{
+  /* Leave FILENUM of 0 free for builtin types and this file's types.  */
+  n_this_object_header_files = 1;
+  header_file_prev_index = -1;
+}
+
+/* Add header file number I for this object file
+   at the next successive FILENUM.  */
+
+static void
+add_this_object_header_file (i)
+     int i;
+{
+  if (n_this_object_header_files == n_allocated_this_object_header_files)
+    {
+      n_allocated_this_object_header_files *= 2;
+      this_object_header_files
+       = (int *) xrealloc (this_object_header_files,
+                           n_allocated_this_object_header_files * sizeof (int));
+    }
+
+  this_object_header_files[n_this_object_header_files++] = i;
+}
+
+/* Add to this file an "old" header file, one already seen in
+   a previous object file.  NAME is the header file's name.
+   INSTANCE is its instance code, to select among multiple
+   symbol tables for the same header file.  */
+
+static void
+add_old_header_file (name, instance)
+     char *name;
+     int instance;
+{
+  register struct header_file *p = header_files;
+  register int i;
+
+  for (i = 0; i < n_header_files; i++)
+    if (!strcmp (p[i].name, name) && instance == p[i].instance)
+      {
+       add_this_object_header_file (i);
+       return;
+      }
+  error ("Invalid symbol data: \"repeated\" header file that hasn't been seen before, at symtab pos %d.",
+        symnum);
+}
+
+/* Add to this file a "new" header file: definitions for its types follow.
+   NAME is the header file's name.
+   Most often this happens only once for each distinct header file,
+   but not necessarily.  If it happens more than once, INSTANCE has
+   a different value each time, and references to the header file
+   use INSTANCE values to select among them.
+
+   dbx output contains "begin" and "end" markers for each new header file,
+   but at this level we just need to know which files there have been;
+   so we record the file when its "begin" is seen and ignore the "end".  */
+
+static void
+add_new_header_file (name, instance)
+     char *name;
+     int instance;
+{
+  register int i;
+  header_file_prev_index = -1;
+
+  /* Make sure there is room for one more header file.  */
+
+  if (n_header_files == n_allocated_header_files)
+    {
+      n_allocated_header_files *= 2;
+      header_files = (struct header_file *)
+       xrealloc (header_files,
+                 (n_allocated_header_files
+                  * sizeof (struct header_file)));
+    }
+
+  /* Create an entry for this header file.  */
+
+  i = n_header_files++;
+  header_files[i].name = savestring (name, strlen(name));
+  header_files[i].instance = instance;
+  header_files[i].length = 10;
+  header_files[i].vector
+    = (struct type **) xmalloc (10 * sizeof (struct type *));
+  bzero (header_files[i].vector, 10 * sizeof (struct type *));
+
+  add_this_object_header_file (i);
+}
+
+/* Look up a dbx type-number pair.  Return the address of the slot
+   where the type for that number-pair is stored.
+   The number-pair is in TYPENUMS.
+
+   This can be used for finding the type associated with that pair
+   or for associating a new type with the pair.  */
+
+static struct type **
+dbx_lookup_type (typenums)
+     int typenums[2];
+{
+  register int filenum = typenums[0], index = typenums[1];
+
+  if (filenum < 0 || filenum >= n_this_object_header_files)
+    error ("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.",
+          filenum, index, symnum);
+
+  if (filenum == 0)
+    {
+      /* Type is defined outside of header files.
+        Find it in this object file's type vector.  */
+      if (index >= type_vector_length)
+       {
+         type_vector_length *= 2;
+         type_vector = (struct typevector *)
+           xrealloc (type_vector,
+                     (sizeof (struct typevector)
+                      + type_vector_length * sizeof (struct type *)));
+         bzero (&type_vector->type[type_vector_length / 2],
+                type_vector_length * sizeof (struct type *) / 2);
+       }
+      return &type_vector->type[index];
+    }
+  else
+    {
+      register int real_filenum = this_object_header_files[filenum];
+      register struct header_file *f;
+      int f_orig_length;
+
+      if (real_filenum >= n_header_files)
+       abort ();
+
+      f = &header_files[real_filenum];
+
+      f_orig_length = f->length;
+      if (index >= f_orig_length)
+       {
+         while (index >= f->length)
+           f->length *= 2;
+         f->vector = (struct type **)
+           xrealloc (f->vector, f->length * sizeof (struct type *));
+         bzero (&f->vector[f_orig_length],
+                (f->length - f_orig_length) * sizeof (struct type *));
+       }
+      return &f->vector[index];
+    }
+}
+
+/* Create a type object.  Occaisionally used when you need a type
+   which isn't going to be given a type number.  */
+
+static struct type *
+dbx_create_type ()
+{
+  register struct type *type =
+    (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type));
+
+  bzero (type, sizeof (struct type));
+  TYPE_VPTR_FIELDNO (type) = -1;
+  return type;
+}
+
+/* Make sure there is a type allocated for type numbers TYPENUMS
+   and return the type object.
+   This can create an empty (zeroed) type object.
+   TYPENUMS may be (-1, -1) to return a new type object that is not
+   put into the type vector, and so may not be referred to by number. */
+
+static struct type *
+dbx_alloc_type (typenums)
+     int typenums[2];
+{
+  register struct type **type_addr;
+  register struct type *type;
+
+  if (typenums[1] != -1)
+    {
+      type_addr = dbx_lookup_type (typenums);
+      type = *type_addr;
+    }
+  else
+    {
+      type_addr = 0;
+      type = 0;
+    }
+
+  /* If we are referring to a type not known at all yet,
+     allocate an empty type for it.
+     We will fill it in later if we find out how.  */
+  if (type == 0)
+    {
+      type = dbx_create_type ();
+      if (type_addr)
+       *type_addr = type;
+    }
+  
+  return type;
+}
+
+#if 0
+static struct type **
+explicit_lookup_type (real_filenum, index)
+     int real_filenum, index;
+{
+  register struct header_file *f = &header_files[real_filenum];
+
+  if (index >= f->length)
+    {
+      f->length *= 2;
+      f->vector = (struct type **)
+       xrealloc (f->vector, f->length * sizeof (struct type *));
+      bzero (&f->vector[f->length / 2],
+            f->length * sizeof (struct type *) / 2);
+    }
+  return &f->vector[index];
+}
+#endif
+\f
+/* maintain the lists of symbols and blocks */
+
+/* Add a symbol to one of the lists of symbols.  */
+static void
+add_symbol_to_list (symbol, listhead)
+     struct symbol *symbol;
+     struct pending **listhead;
+{
+  /* We keep PENDINGSIZE symbols in each link of the list.
+     If we don't have a link with room in it, add a new link.  */
+  if (*listhead == 0 || (*listhead)->nsyms == PENDINGSIZE)
+    {
+      register struct pending *link;
+      if (free_pendings)
+       {
+         link = free_pendings;
+         free_pendings = link->next;
+       }
+      else
+       link = (struct pending *) xmalloc (sizeof (struct pending));
+
+      link->next = *listhead;
+      *listhead = link;
+      link->nsyms = 0;
+    }
+
+  (*listhead)->symbol[(*listhead)->nsyms++] = symbol;
+}
+
+/* At end of reading syms, or in case of quit,
+   really free as many `struct pending's as we can easily find.  */
+
+/* ARGSUSED */
+static void
+really_free_pendings (foo)
+     int foo;
+{
+  struct pending *next, *next1;
+  struct pending_block *bnext, *bnext1;
+
+  for (next = free_pendings; next; next = next1)
+    {
+      next1 = next->next;
+      free (next);
+    }
+  free_pendings = 0;
+
+#if 0 /* Now we make the links in the symbol_obstack, so don't free them.  */
+  for (bnext = pending_blocks; bnext; bnext = bnext1)
+    {
+      bnext1 = bnext->next;
+      free (bnext);
+    }
+#endif
+  pending_blocks = 0;
+
+  for (next = file_symbols; next; next = next1)
+    {
+      next1 = next->next;
+      free (next);
+    }
+  for (next = global_symbols; next; next = next1)
+    {
+      next1 = next->next;
+      free (next);
+    }
+}
+
+/* Take one of the lists of symbols and make a block from it.
+   Keep the order the symbols have in the list (reversed from the input file).
+   Put the block on the list of pending blocks.  */
+
+static void
+finish_block (symbol, listhead, old_blocks, start, end)
+     struct symbol *symbol;
+     struct pending **listhead;
+     struct pending_block *old_blocks;
+     CORE_ADDR start, end;
+{
+  register struct pending *next, *next1;
+  register struct block *block;
+  register struct pending_block *pblock;
+  struct pending_block *opblock;
+  register int i;
+
+  /* Count the length of the list of symbols.  */
+
+  for (next = *listhead, i = 0; next; i += next->nsyms, next = next->next)
+    /*EMPTY*/;
+
+  block = (struct block *) obstack_alloc (symbol_obstack,
+                                         (sizeof (struct block)
+                                          + ((i - 1)
+                                             * sizeof (struct symbol *))));
+
+  /* Copy the symbols into the block.  */
+
+  BLOCK_NSYMS (block) = i;
+  for (next = *listhead; next; next = next->next)
+    {
+      register int j;
+      for (j = next->nsyms - 1; j >= 0; j--)
+       BLOCK_SYM (block, --i) = next->symbol[j];
+    }
+
+  BLOCK_START (block) = start;
+  BLOCK_END (block) = end;
+  BLOCK_SUPERBLOCK (block) = 0;        /* Filled in when containing block is made */
+  BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
+
+  /* Put the block in as the value of the symbol that names it.  */
+
+  if (symbol)
+    {
+      SYMBOL_BLOCK_VALUE (symbol) = block;
+      BLOCK_FUNCTION (block) = symbol;
+    }
+  else
+    BLOCK_FUNCTION (block) = 0;
+
+  /* Now "free" the links of the list, and empty the list.  */
+
+  for (next = *listhead; next; next = next1)
+    {
+      next1 = next->next;
+      next->next = free_pendings;
+      free_pendings = next;
+    }
+  *listhead = 0;
+
+  /* Install this block as the superblock
+     of all blocks made since the start of this scope
+     that don't have superblocks yet.  */
+
+  opblock = 0;
+  for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next)
+    {
+      if (BLOCK_SUPERBLOCK (pblock->block) == 0) {
+#if 1
+       /* Check to be sure the blocks are nested as we receive them. 
+          If the compiler/assembler/linker work, this just burns a small
+          amount of time.  */
+       if (BLOCK_START (pblock->block) < BLOCK_START (block)
+        || BLOCK_END   (pblock->block) > BLOCK_END   (block)) {
+         complain(&innerblock_complaint, symbol? SYMBOL_NAME (symbol):
+                                                "(don't know)");
+         BLOCK_START (pblock->block) = BLOCK_START (block);
+         BLOCK_END   (pblock->block) = BLOCK_END   (block);
+       }
+#endif
+       BLOCK_SUPERBLOCK (pblock->block) = block;
+      }
+      opblock = pblock;
+    }
+
+  /* Record this block on the list of all blocks in the file.
+     Put it after opblock, or at the beginning if opblock is 0.
+     This puts the block in the list after all its subblocks.  */
+
+  /* Allocate in the symbol_obstack to save time.
+     It wastes a little space.  */
+  pblock = (struct pending_block *)
+    obstack_alloc (symbol_obstack,
+                  sizeof (struct pending_block));
+  pblock->block = block;
+  if (opblock)
+    {
+      pblock->next = opblock->next;
+      opblock->next = pblock;
+    }
+  else
+    {
+      pblock->next = pending_blocks;
+      pending_blocks = pblock;
+    }
+}
+
+static struct blockvector *
+make_blockvector ()
+{
+  register struct pending_block *next;
+  register struct blockvector *blockvector;
+  register int i;
+
+  /* Count the length of the list of blocks.  */
+
+  for (next = pending_blocks, i = 0; next; next = next->next, i++);
+
+  blockvector = (struct blockvector *)
+    obstack_alloc (symbol_obstack,
+                  (sizeof (struct blockvector)
+                   + (i - 1) * sizeof (struct block *)));
+
+  /* Copy the blocks into the blockvector.
+     This is done in reverse order, which happens to put
+     the blocks into the proper order (ascending starting address).
+     finish_block has hair to insert each block into the list
+     after its subblocks in order to make sure this is true.  */
+
+  BLOCKVECTOR_NBLOCKS (blockvector) = i;
+  for (next = pending_blocks; next; next = next->next) {
+    BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
+  }
+
+#if 0 /* Now we make the links in the obstack, so don't free them.  */
+  /* Now free the links of the list, and empty the list.  */
+
+  for (next = pending_blocks; next; next = next1)
+    {
+      next1 = next->next;
+      free (next);
+    }
+#endif
+  pending_blocks = 0;
+
+#if 1  /* FIXME, shut this off after a while to speed up symbol reading.  */
+  /* Some compilers output blocks in the wrong order, but we depend
+     on their being in the right order so we can binary search. 
+     Check the order and moan about it.  FIXME.  */
+  if (BLOCKVECTOR_NBLOCKS (blockvector) > 1)
+    for (i = 1; i < BLOCKVECTOR_NBLOCKS (blockvector); i++) {
+      if (BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i-1))
+         > BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i))) {
+       complain (&blockvector_complaint, 
+         BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i)));
+      }
+    }
+#endif
+
+  return blockvector;
+}
+\f
+/* Manage the vector of line numbers.  */
+
+static void
+record_line (line, pc)
+     int line;
+     CORE_ADDR pc;
+{
+  struct linetable_entry *e;
+  /* Ignore the dummy line number in libg.o */
+
+  if (line == 0xffff)
+    return;
+
+  /* Make sure line vector is big enough.  */
+
+  if (line_vector_index + 1 >= line_vector_length)
+    {
+      line_vector_length *= 2;
+      line_vector = (struct linetable *)
+       xrealloc (line_vector,
+                 (sizeof (struct linetable)
+                  + line_vector_length * sizeof (struct linetable_entry)));
+      current_subfile->line_vector = line_vector;
+    }
+
+  e = line_vector->item + line_vector_index++;
+  e->line = line; e->pc = pc;
+}
+\f
+/* Start a new symtab for a new source file.
+   This is called when a dbx symbol of type N_SO is seen;
+   it indicates the start of data for one original source file.  */
+
+static void
+start_symtab (name, dirname, start_addr)
+     char *name;
+     char *dirname;
+     CORE_ADDR start_addr;
+{
+
+  last_source_file = name;
+  last_source_start_addr = start_addr;
+  file_symbols = 0;
+  global_symbols = 0;
+  within_function = 0;
+
+  /* Context stack is initially empty, with room for 10 levels.  */
+  context_stack
+    = (struct context_stack *) xmalloc (10 * sizeof (struct context_stack));
+  context_stack_size = 10;
+  context_stack_depth = 0;
+
+  new_object_header_files ();
+
+  type_vector_length = 160;
+  type_vector = (struct typevector *)
+    xmalloc (sizeof (struct typevector)
+             + type_vector_length * sizeof (struct type *));
+  bzero (type_vector->type, type_vector_length * sizeof (struct type *));
+
+  /* Initialize the list of sub source files with one entry
+     for this file (the top-level source file).  */
+
+  subfiles = 0;
+  current_subfile = 0;
+  start_subfile (name, dirname);
+}
+
+/* Handle an N_SOL symbol, which indicates the start of
+   code that came from an included (or otherwise merged-in)
+   source file with a different name.  */
+
+static void
+start_subfile (name, dirname)
+     char *name;
+     char *dirname;
+{
+  register struct subfile *subfile;
+
+  /* Save the current subfile's line vector data.  */
+
+  if (current_subfile)
+    {
+      current_subfile->line_vector_index = line_vector_index;
+      current_subfile->line_vector_length = line_vector_length;
+      current_subfile->prev_line_number = prev_line_number;
+    }
+
+  /* See if this subfile is already known as a subfile of the
+     current main source file.  */
+
+  for (subfile = subfiles; subfile; subfile = subfile->next)
+    {
+      if (!strcmp (subfile->name, name))
+       {
+         line_vector = subfile->line_vector;
+         line_vector_index = subfile->line_vector_index;
+         line_vector_length = subfile->line_vector_length;
+         prev_line_number = subfile->prev_line_number;
+         current_subfile = subfile;
+         return;
+       }
+    }
+
+  /* This subfile is not known.  Add an entry for it.  */
+
+  line_vector_index = 0;
+  line_vector_length = 1000;
+  prev_line_number = -2;       /* Force first line number to be explicit */
+  line_vector = (struct linetable *)
+    xmalloc (sizeof (struct linetable)
+             + line_vector_length * sizeof (struct linetable_entry));
+
+  /* Make an entry for this subfile in the list of all subfiles
+     of the current main source file.  */
+
+  subfile = (struct subfile *) xmalloc (sizeof (struct subfile));
+  subfile->next = subfiles;
+  subfile->name = obsavestring (name, strlen (name));
+  if (dirname == NULL)
+    subfile->dirname = NULL;
+  else
+    subfile->dirname = obsavestring (dirname, strlen (dirname));
+  
+  subfile->line_vector = line_vector;
+  subfiles = subfile;
+  current_subfile = subfile;
+}
+
+/* Finish the symbol definitions for one main source file,
+   close off all the lexical contexts for that file
+   (creating struct block's for them), then make the struct symtab
+   for that file and put it in the list of all such.
+
+   END_ADDR is the address of the end of the file's text.  */
+
+static void
+end_symtab (end_addr)
+     CORE_ADDR end_addr;
+{
+  register struct symtab *symtab;
+  register struct blockvector *blockvector;
+  register struct subfile *subfile;
+  register struct linetable *lv;
+  struct subfile *nextsub;
+
+  /* Finish the lexical context of the last function in the file;
+     pop the context stack.  */
+
+  if (context_stack_depth > 0)
+    {
+      register struct context_stack *cstk;
+      context_stack_depth--;
+      cstk = &context_stack[context_stack_depth];
+      /* Make a block for the local symbols within.  */
+      finish_block (cstk->name, &local_symbols, cstk->old_blocks,
+                   cstk->start_addr, end_addr);
+    }
+
+  /* Cleanup any undefined types that have been left hanging around
+     (this needs to be done before the finish_blocks so that
+     file_symbols is still good).  */
+  cleanup_undefined_types ();
+
+  /* Finish defining all the blocks of this symtab.  */
+  finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr);
+  finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr);
+  blockvector = make_blockvector ();
+
+  current_subfile->line_vector_index = line_vector_index;
+
+  /* Now create the symtab objects proper, one for each subfile.  */
+  /* (The main file is one of them.)  */
+
+  for (subfile = subfiles; subfile; subfile = nextsub)
+    {
+      symtab = (struct symtab *) xmalloc (sizeof (struct symtab));
+
+      /* Fill in its components.  */
+      symtab->blockvector = blockvector;
+      lv = subfile->line_vector;
+      lv->nitems = subfile->line_vector_index;
+      symtab->linetable = (struct linetable *)
+       xrealloc (lv, (sizeof (struct linetable)
+                      + lv->nitems * sizeof (struct linetable_entry)));
+      type_vector->length = type_vector_length;
+      symtab->typevector = type_vector;
+
+      symtab->filename = subfile->name;
+      symtab->dirname = subfile->dirname;
+
+      symtab->free_code = free_linetable;
+      symtab->free_ptr = 0;
+      if (subfile->next == 0)
+       symtab->free_ptr = (char *) type_vector;
+
+      symtab->nlines = 0;
+      symtab->line_charpos = 0;
+
+      symtab->language = language_unknown;
+      symtab->fullname = NULL;
+
+      /* If there is already a symtab for a file of this name, remove it,
+        and clear out other dependent data structures such as
+        breakpoints.  This happens in VxWorks maybe?  -gnu@cygnus */
+      free_named_symtab (symtab->filename);
+
+      /* Link the new symtab into the list of such.  */
+      symtab->next = symtab_list;
+      symtab_list = symtab;
+
+      nextsub = subfile->next;
+      free (subfile);
+    }
+
+  type_vector = 0;
+  type_vector_length = -1;
+  line_vector = 0;
+  line_vector_length = -1;
+  last_source_file = 0;
+}
+\f
+/* Handle the N_BINCL and N_EINCL symbol types
+   that act like N_SOL for switching source files
+   (different subfiles, as we call them) within one object file,
+   but using a stack rather than in an arbitrary order.  */
+
+struct subfile_stack
+{
+  struct subfile_stack *next;
+  char *name;
+  int prev_index;
+};
+
+struct subfile_stack *subfile_stack;
+
+static void
+push_subfile ()
+{
+  register struct subfile_stack *tem
+    = (struct subfile_stack *) xmalloc (sizeof (struct subfile_stack));
+
+  tem->next = subfile_stack;
+  subfile_stack = tem;
+  if (current_subfile == 0 || current_subfile->name == 0)
+    abort ();
+  tem->name = current_subfile->name;
+  tem->prev_index = header_file_prev_index;
+}
+
+static char *
+pop_subfile ()
+{
+  register char *name;
+  register struct subfile_stack *link = subfile_stack;
+
+  if (link == 0)
+    abort ();
+
+  name = link->name;
+  subfile_stack = link->next;
+  header_file_prev_index = link->prev_index;
+  free (link);
+
+  return name;
+}
+\f
+void
+record_misc_function (name, address, type)
+     char *name;
+     CORE_ADDR address;
+     int type;
+{
+  enum misc_function_type misc_type =
+    (type == (N_TEXT | N_EXT) ? mf_text :
+     (type == (N_DATA | N_EXT)
+      || type == (N_DATA)
+      || type == (N_SETV | N_EXT)
+      ) ? mf_data :
+     type == (N_BSS | N_EXT) ? mf_bss :
+     type == (N_ABS | N_EXT) ? mf_abs : mf_unknown);
+
+  prim_record_misc_function (obsavestring (name, strlen (name)),
+                            address, misc_type);
+}
+\f
+/* Scan and build partial symbols for a symbol file.
+   We have been initialized by a call to dbx_symfile_init, which 
+   put all the relevant info into a "struct dbx_symfile_info"
+   hung off the struct sym_fns SF.
+
+   ADDR is the address relative to which the symbols in it are (e.g.
+   the base address of the text segment).
+   MAINLINE is true if we are reading the main symbol
+   table (as opposed to a shared lib or dynamically loaded file).  */
+
+void
+dbx_symfile_read (sf, addr, mainline)
+     struct sym_fns *sf;
+     CORE_ADDR addr;
+     int mainline;     /* FIXME comments above */
+{
+  struct dbx_symfile_info *info = (struct dbx_symfile_info *) (sf->sym_private);
+  bfd *sym_bfd = sf->sym_bfd;
+  int val;
+  char *filename = bfd_get_filename (sym_bfd);
+
+  val = lseek (info->desc, info->symtab_offset, L_SET);
+  if (val < 0)
+    perror_with_name (filename);
+
+  /* If mainline, set global string table pointers, and reinitialize global
+     partial symbol list.  */
+  if (mainline) {
+    symfile_string_table = info->stringtab;
+    symfile_string_table_size = info->stringtab_size;
+    init_psymbol_list (info->symcount);
+  }
+
+  symfile_bfd = sym_bfd;               /* Kludge for SWAP_SYMBOL */
+
+  pending_blocks = 0;
+  make_cleanup (really_free_pendings, 0);
+
+  init_misc_bunches ();
+  make_cleanup (discard_misc_bunches, 0);
+
+  /* Now that the symbol table data of the executable file are all in core,
+     process them and define symbols accordingly.  */
+
+  read_dbx_symtab (filename, 
+                  addr - bfd_section_vma (sym_bfd, info->text_sect), /*offset*/
+                  info->desc, info->stringtab, info->stringtab_size,
+                  info->symcount,
+                  bfd_section_vma  (sym_bfd, info->text_sect),
+                  bfd_section_size (sym_bfd, info->text_sect));
+
+  /* Go over the misc symbol bunches and install them in vector.  */
+
+  condense_misc_bunches (!mainline);
+
+  /* Free up any memory we allocated for ourselves.  */
+
+  if (!mainline) {
+    free (info->stringtab);    /* Stringtab is only saved for mainline */
+  }
+  free (info);
+  sf->sym_private = 0;         /* Zap pointer to our (now gone) info struct */
+
+  /* Call to select_source_symtab used to be here; it was using too
+     much time.  I'll make sure that list_sources can handle the lack
+     of current_source_symtab */
+
+  if (!partial_symtab_list)
+    printf_filtered ("\n(no debugging symbols found)...");
+}
+
+/* Discard any information we have cached during the reading of a
+   single symbol file.  This should not toss global information
+   from previous symbol files that have been read.  E.g. we might
+   be discarding info from reading a shared library, and should not
+   throw away the info from the main file.  */
+
+void
+dbx_symfile_discard ()
+{
+
+  /* Empty the hash table of global syms looking for values.  */
+  bzero (global_sym_chain, sizeof global_sym_chain);
+
+  free_pendings = 0;
+  file_symbols = 0;
+  global_symbols = 0;
+}
+
+/* Initialize anything that needs initializing when a completely new
+   symbol file is specified (not just adding some symbols from another
+   file, e.g. a shared library).  */
+
+void
+dbx_new_init ()
+{
+  dbx_symfile_discard ();
+  /* Don't put these on the cleanup chain; they need to stick around
+     until the next call to symbol_file_command.  *Then* we'll free
+     them. */
+  if (symfile_string_table)
+    {
+      free (symfile_string_table);
+      symfile_string_table = 0;
+      symfile_string_table_size = 0;
+    }
+  free_and_init_header_files ();
+}
+
+
+/* dbx_symfile_init ()
+   is the dbx-specific initialization routine for reading symbols.
+   It is passed a struct sym_fns which contains, among other things,
+   the BFD for the file whose symbols are being read, and a slot for a pointer
+   to "private data" which we fill with goodies.
+
+   We read the string table into malloc'd space and stash a pointer to it.
+
+   Since BFD doesn't know how to read debug symbols in a format-independent
+   way (and may never do so...), we have to do it ourselves.  We will never
+   be called unless this is an a.out (or very similar) file. 
+   FIXME, there should be a cleaner peephole into the BFD environment here.  */
+
+void
+dbx_symfile_init (sf)
+  struct sym_fns *sf;
+{
+  int val;
+  int desc;
+  struct stat statbuf;
+  bfd *sym_bfd = sf->sym_bfd;
+  char *name = bfd_get_filename (sym_bfd);
+  struct dbx_symfile_info *info;
+  unsigned char size_temp[4];
+
+  /* Allocate struct to keep track of the symfile */
+  sf->sym_private = xmalloc (sizeof (*info));   /* FIXME storage leak */
+  info = (struct dbx_symfile_info *)sf->sym_private;
+
+  /* FIXME POKING INSIDE BFD DATA STRUCTURES */
+  desc = fileno ((FILE *)(sym_bfd->iostream)); /* Raw file descriptor */
+#define        STRING_TABLE_OFFSET     (sym_bfd->origin + obj_str_filepos (sym_bfd))
+#define        SYMBOL_TABLE_OFFSET     (sym_bfd->origin + obj_sym_filepos (sym_bfd))
+  /* FIXME POKING INSIDE BFD DATA STRUCTURES */
+
+  info->desc = desc;
+  info->text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+  if (!info->text_sect)
+    abort();
+  info->symcount = bfd_get_symcount_upper_bound(sym_bfd);   /* It's exact for a.out */
+
+  /* Read the string table size and check it for bogosity.  */
+  val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
+  if (val < 0)
+      perror_with_name (name);
+  if (fstat (desc, &statbuf) == -1)
+      perror_with_name (name);
+
+  val = myread (desc, size_temp, sizeof (long));
+  if (val < 0)
+      perror_with_name (name);
+  info->stringtab_size = bfd_h_getlong (sym_bfd, size_temp);
+  
+  if (info->stringtab_size >= 0 && info->stringtab_size < statbuf.st_size)
+    {
+      info->stringtab = (char *) xmalloc (info->stringtab_size);
+      /* Caller is responsible for freeing the string table.  No cleanup. */
+    }
+  else
+    info->stringtab = NULL;
+  if (info->stringtab == NULL && info->stringtab_size != 0)
+    error ("ridiculous string table size: %d bytes", info->stringtab_size);
+
+  /* Now read in the string table in one big gulp.  */
+
+  val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
+  if (val < 0)
+    perror_with_name (name);
+  val = myread (desc, info->stringtab, info->stringtab_size);
+  if (val < 0)
+    perror_with_name (name);
+
+  /* Record the position of the symbol table for later use.  */
+
+  info->symtab_offset = SYMBOL_TABLE_OFFSET;
+}
+\f
+/* Buffer for reading the symbol table entries.  */
+static struct nlist symbuf[4096];
+static int symbuf_idx;
+static int symbuf_end;
+
+/* I/O descriptor for reading the symbol table.  */
+static int symtab_input_desc;
+
+/* The address in memory of the string table of the object file we are
+   reading (which might not be the "main" object file, but might be a
+   shared library or some other dynamically loaded thing).  This is set
+   by read_dbx_symtab when building psymtabs, and by read_ofile_symtab 
+   when building symtabs, and is used only by next_symbol_text.  */
+static char *stringtab_global;
+
+/* Refill the symbol table input buffer
+   and set the variables that control fetching entries from it.
+   Reports an error if no data available.
+   This function can read past the end of the symbol table
+   (into the string table) but this does no harm.  */
+
+static int
+fill_symbuf ()
+{
+  int nbytes = myread (symtab_input_desc, symbuf, sizeof (symbuf));
+  if (nbytes < 0)
+    perror_with_name ("<symbol file>");
+  else if (nbytes == 0)
+    error ("Premature end of file reading symbol table");
+  symbuf_end = nbytes / sizeof (struct nlist);
+  symbuf_idx = 0;
+  return 1;
+}
+
+#define SWAP_SYMBOL(symp) \
+  { \
+    (symp)->n_un.n_strx = bfd_h_getlong(symfile_bfd,                   \
+                               (unsigned char *)&(symp)->n_un.n_strx); \
+    (symp)->n_desc = bfd_h_getshort (symfile_bfd,                      \
+                               (unsigned char *)&(symp)->n_desc);      \
+    (symp)->n_value = bfd_h_getlong (symfile_bfd,                      \
+                               (unsigned char *)&(symp)->n_value);     \
+  }
+
+/* Invariant: The symbol pointed to by symbuf_idx is the first one
+   that hasn't been swapped.  Swap the symbol at the same time
+   that symbuf_idx is incremented.  */
+
+/* dbx allows the text of a symbol name to be continued into the
+   next symbol name!  When such a continuation is encountered
+   (a \ at the end of the text of a name)
+   call this function to get the continuation.  */
+
+static char *
+next_symbol_text ()
+{
+  if (symbuf_idx == symbuf_end)
+    fill_symbuf ();
+  symnum++;
+  SWAP_SYMBOL(&symbuf[symbuf_idx]);
+  return symbuf[symbuf_idx++].n_un.n_strx + stringtab_global;
+}
+\f
+/* Initializes storage for all of the partial symbols that will be
+   created by read_dbx_symtab and subsidiaries.  */
+
+static void
+init_psymbol_list (total_symbols)
+     int total_symbols;
+{
+  /* Free any previously allocated psymbol lists.  */
+  if (global_psymbols.list)
+    free (global_psymbols.list);
+  if (static_psymbols.list)
+    free (static_psymbols.list);
+
+  /* Current best guess is that there are approximately a twentieth
+     of the total symbols (in a debugging file) are global or static
+     oriented symbols */
+  global_psymbols.size = total_symbols / 10;
+  static_psymbols.size = total_symbols / 10;
+  global_psymbols.next = global_psymbols.list = (struct partial_symbol *)
+    xmalloc (global_psymbols.size * sizeof (struct partial_symbol));
+  static_psymbols.next = static_psymbols.list = (struct partial_symbol *)
+    xmalloc (static_psymbols.size * sizeof (struct partial_symbol));
+}
+
+/* Initialize the list of bincls to contain none and have some
+   allocated.  */
+
+static void
+init_bincl_list (number)
+     int number;
+{
+  bincls_allocated = number;
+  next_bincl = bincl_list = (struct header_file_location *)
+      xmalloc (bincls_allocated * sizeof(struct header_file_location));
+}
+
+/* Add a bincl to the list.  */
+
+static void
+add_bincl_to_list (pst, name, instance)
+     struct partial_symtab *pst;
+     char *name;
+     int instance;
+{
+  if (next_bincl >= bincl_list + bincls_allocated)
+    {
+      int offset = next_bincl - bincl_list;
+      bincls_allocated *= 2;
+      bincl_list = (struct header_file_location *)
+       xrealloc ((char *)bincl_list,
+                 bincls_allocated * sizeof (struct header_file_location));
+      next_bincl = bincl_list + offset;
+    }
+  next_bincl->pst = pst;
+  next_bincl->instance = instance;
+  next_bincl++->name = name;
+}
+
+/* Given a name, value pair, find the corresponding
+   bincl in the list.  Return the partial symtab associated
+   with that header_file_location.  */
+
+struct partial_symtab *
+find_corresponding_bincl_psymtab (name, instance)
+     char *name;
+     int instance;
+{
+  struct header_file_location *bincl;
+
+  for (bincl = bincl_list; bincl < next_bincl; bincl++)
+    if (bincl->instance == instance
+       && !strcmp (name, bincl->name))
+      return bincl->pst;
+
+  return (struct partial_symtab *) 0;
+}
+
+/* Free the storage allocated for the bincl list.  */
+
+static void
+free_bincl_list ()
+{
+  free (bincl_list);
+  bincls_allocated = 0;
+}
+
+static struct partial_symtab *start_psymtab ();
+static void end_psymtab();
+
+#ifdef DEBUG
+/* This is normally a macro defined in read_dbx_symtab, but this
+   is a lot easier to debug.  */
+
+ADD_PSYMBOL_TO_PLIST(NAME, NAMELENGTH, NAMESPACE, CLASS, PLIST, VALUE)
+     char *NAME;
+     int NAMELENGTH;
+     enum namespace NAMESPACE;
+     enum address_class CLASS;
+     struct psymbol_allocation_list *PLIST;
+     unsigned long VALUE;
+{
+  register struct partial_symbol *psym;
+
+#define LIST *PLIST
+  do {                                                                 
+    if ((LIST).next >=                                 
+       (LIST).list + (LIST).size)                      
+      {                                                                        
+       (LIST).list = (struct partial_symbol *)                         
+         xrealloc ((LIST).list,                                        
+                   ((LIST).size * 2                                    
+                    * sizeof (struct partial_symbol)));                
+       /* Next assumes we only went one over.  Should be good if       
+          program works correctly */                                   
+       (LIST).next =                                                   
+         (LIST).list + (LIST).size;                            
+       (LIST).size *= 2;                               
+      }                                                                        
+    psym = (LIST).next++;                                              
+#undef LIST
+
+    SYMBOL_NAME (psym) = (char *) obstack_alloc (psymbol_obstack,      
+                                                (NAMELENGTH) + 1);     
+    strncpy (SYMBOL_NAME (psym), (NAME), (NAMELENGTH));                        
+    SYMBOL_NAME (psym)[(NAMELENGTH)] = '\0';                           
+    SYMBOL_NAMESPACE (psym) = (NAMESPACE);                             
+    SYMBOL_CLASS (psym) = (CLASS);                             
+    SYMBOL_VALUE (psym) = (VALUE);                                     
+  } while (0);
+}
+
+/* Since one arg is a struct, we have to pass in a ptr and deref it (sigh) */
+#define        ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS,  LIST, VALUE) \
+       ADD_PSYMBOL_TO_PLIST(NAME, NAMELENGTH, NAMESPACE, CLASS, &LIST, VALUE)
+
+#endif /* DEBUG */
+
+/* Given pointers to an a.out symbol table in core containing dbx
+   style data, setup partial_symtab's describing each source file for
+   which debugging information is available.  NLISTLEN is the number
+   of symbols in the symbol table.  All symbol names are given as
+   offsets relative to STRINGTAB.  STRINGTAB_SIZE is the size of
+   STRINGTAB.  SYMFILE_NAME is the name of the file we are reading from
+   and ADDR is its relocated address (if incremental) or 0 (if not).  */
+
+static void
+read_dbx_symtab (symfile_name, addr,
+                desc, stringtab, stringtab_size, nlistlen,
+                text_addr, text_size)
+     char *symfile_name;
+     CORE_ADDR addr;
+     int desc;
+     register char *stringtab;
+     register long stringtab_size;
+     register int nlistlen;
+     CORE_ADDR text_addr;
+     int text_size;
+{
+  register struct nlist *bufp;
+  register char *namestring;
+  register struct partial_symbol *psym;
+  int nsl;
+  int past_first_source_file = 0;
+  CORE_ADDR last_o_file_start = 0;
+  struct cleanup *old_chain;
+  char *p;
+
+  /* End of the text segment of the executable file.  */
+  CORE_ADDR end_of_text_addr;
+
+  /* Current partial symtab */
+  struct partial_symtab *pst;
+
+  /* List of current psymtab's include files */
+  char **psymtab_include_list;
+  int includes_allocated;
+  int includes_used;
+
+  /* Index within current psymtab dependency list */
+  struct partial_symtab **dependency_list;
+  int dependencies_used, dependencies_allocated;
+
+  stringtab_global = stringtab;
+  
+  pst = (struct partial_symtab *) 0;
+
+  includes_allocated = 30;
+  includes_used = 0;
+  psymtab_include_list = (char **) alloca (includes_allocated *
+                                          sizeof (char *));
+
+  dependencies_allocated = 30;
+  dependencies_used = 0;
+  dependency_list =
+    (struct partial_symtab **) alloca (dependencies_allocated *
+                                      sizeof (struct partial_symtab *));
+
+  /* FIXME!!  If an error occurs, this blows away the whole symbol table! 
+     It should only blow away the psymtabs created herein.  We could
+     be reading a shared library or a dynloaded file!  */
+  old_chain = make_cleanup (free_all_psymtabs, 0);
+
+  /* Init bincl list */
+  init_bincl_list (20);
+  make_cleanup (free_bincl_list, 0);
+
+  last_source_file = 0;
+
+#ifdef END_OF_TEXT_DEFAULT
+  end_of_text_addr = END_OF_TEXT_DEFAULT;
+#else
+  end_of_text_addr = addr + text_size;
+#endif
+
+  symtab_input_desc = desc;    /* This is needed for fill_symbuf below */
+  symbuf_end = symbuf_idx = 0;
+
+  for (symnum = 0; symnum < nlistlen; symnum++)
+    {
+      /* Get the symbol for this run and pull out some info */
+      QUIT;    /* allow this to be interruptable */
+      if (symbuf_idx == symbuf_end)
+       fill_symbuf ();
+      bufp = &symbuf[symbuf_idx++];
+
+      /*
+       * Special case to speed up readin.
+       */
+      if (bufp->n_type == (unsigned char)N_SLINE) continue;
+
+      SWAP_SYMBOL (bufp);
+
+      /* Ok.  There is a lot of code duplicated in the rest of this
+         switch statement (for efficiency reasons).  Since I don't
+         like duplicating code, I will do my penance here, and
+         describe the code which is duplicated:
+
+        *) The assignment to namestring.
+        *) The call to strchr.
+        *) The addition of a partial symbol the the two partial
+           symbol lists.  This last is a large section of code, so
+           I've imbedded it in the following macro.
+        */
+      
+/* Set namestring based on bufp.  If the string table index is invalid, 
+   give a fake name, and print a single error message per symbol file read,
+   rather than abort the symbol reading or flood the user with messages.  */
+#define SET_NAMESTRING()\
+  if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size) {  \
+    complain (&string_table_offset_complaint, symnum);                 \
+    namestring = "foo";                                                        \
+  } else                                                               \
+    namestring = bufp->n_un.n_strx + stringtab
+
+/* Add a symbol with an integer value to a psymtab. */
+/* This is a macro unless we're debugging.  See above this function. */
+#ifndef DEBUG
+#  define ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE) \
+ ADD_PSYMBOL_VT_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE, \
+                        SYMBOL_VALUE)
+#endif /* DEBUG */
+
+/* Add a symbol with a CORE_ADDR value to a psymtab. */
+#define        ADD_PSYMBOL_ADDR_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE) \
+ ADD_PSYMBOL_VT_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE, \
+                        SYMBOL_VALUE_ADDRESS)
+
+/* Add any kind of symbol to a psymtab. */
+#define        ADD_PSYMBOL_VT_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE, VT)\
+  do {                                                                 \
+    if ((LIST).next >=                                                 \
+       (LIST).list + (LIST).size)                                      \
+      {                                                                        \
+       (LIST).list = (struct partial_symbol *)                         \
+         xrealloc ((LIST).list,                                        \
+                   ((LIST).size * 2                                    \
+                    * sizeof (struct partial_symbol)));                \
+       /* Next assumes we only went one over.  Should be good if       \
+          program works correctly */                                   \
+       (LIST).next =                                                   \
+         (LIST).list + (LIST).size;                                    \
+       (LIST).size *= 2;                                               \
+      }                                                                        \
+    psym = (LIST).next++;                                              \
+                                                                       \
+    SYMBOL_NAME (psym) = (char *) obstack_alloc (psymbol_obstack,      \
+                                                (NAMELENGTH) + 1);     \
+    strncpy (SYMBOL_NAME (psym), (NAME), (NAMELENGTH));                        \
+    SYMBOL_NAME (psym)[(NAMELENGTH)] = '\0';                           \
+    SYMBOL_NAMESPACE (psym) = (NAMESPACE);                             \
+    SYMBOL_CLASS (psym) = (CLASS);                                     \
+    VT (psym) = (VALUE);                                               \
+  } while (0);
+
+/* End of macro definitions, now let's handle them symbols!  */
+
+      switch (bufp->n_type)
+       {
+         /*
+          * Standard, external, non-debugger, symbols
+          */
+
+       case N_TEXT | N_EXT:
+       case N_NBTEXT | N_EXT:
+       case N_NBDATA | N_EXT:
+       case N_NBBSS | N_EXT:
+       case N_SETV | N_EXT:
+       case N_ABS | N_EXT:
+       case N_DATA | N_EXT:
+       case N_BSS | N_EXT:
+
+         bufp->n_value += addr;                /* Relocate */
+
+         SET_NAMESTRING();
+
+       bss_ext_symbol:
+         record_misc_function (namestring, bufp->n_value,
+                               bufp->n_type); /* Always */
+
+         continue;
+
+         /* Standard, local, non-debugger, symbols */
+
+       case N_NBTEXT:
+
+         /* We need to be able to deal with both N_FN or N_TEXT,
+            because we have no way of knowing whether the sys-supplied ld
+            or GNU ld was used to make the executable.  */
+#if ! (N_FN & N_EXT)
+       case N_FN:
+#endif
+       case N_FN | N_EXT:
+       case N_TEXT:
+         bufp->n_value += addr;                /* Relocate */
+         SET_NAMESTRING();
+         if ((namestring[0] == '-' && namestring[1] == 'l')
+             || (namestring [(nsl = strlen (namestring)) - 1] == 'o'
+                 && namestring [nsl - 2] == '.'))
+           {
+             if (entry_point < bufp->n_value
+                 && entry_point >= last_o_file_start
+                 && addr == 0)         /* FIXME nogood nomore */
+               {
+                 startup_file_start = last_o_file_start;
+                 startup_file_end = bufp->n_value;
+               }
+             if (past_first_source_file && pst
+                 /* The gould NP1 uses low values for .o and -l symbols
+                    which are not the address.  */
+                 && bufp->n_value > pst->textlow)
+               {
+                 end_psymtab (pst, psymtab_include_list, includes_used,
+                              symnum * sizeof (struct nlist), bufp->n_value,
+                              dependency_list, dependencies_used,
+                              global_psymbols.next, static_psymbols.next);
+                 pst = (struct partial_symtab *) 0;
+                 includes_used = 0;
+                 dependencies_used = 0;
+               }
+             else
+               past_first_source_file = 1;
+             last_o_file_start = bufp->n_value;
+           }
+         continue;
+
+       case N_DATA:
+         bufp->n_value += addr;                /* Relocate */
+         SET_NAMESTRING ();
+         /* Check for __DYNAMIC, which is used by Sun shared libraries. 
+            Record it even if it's local, not global, so we can find it.  */
+         if (namestring[8] == 'C' && (strcmp ("__DYNAMIC", namestring) == 0))
+           {
+             /* Not really a function here, but... */
+             record_misc_function (namestring, bufp->n_value,
+                                   bufp->n_type); /* Always */
+         }
+         continue;
+
+       case N_UNDF | N_EXT:
+         if (bufp->n_value != 0) {
+           /* This is a "Fortran COMMON" symbol.  See if the target
+              environment knows where it has been relocated to.  */
+
+           CORE_ADDR reladdr;
+
+           SET_NAMESTRING();
+           if (target_lookup_symbol (namestring, &reladdr)) {
+             continue;         /* Error in lookup; ignore symbol for now.  */
+           }
+           bufp->n_type ^= (N_BSS^N_UNDF);     /* Define it as a bss-symbol */
+           bufp->n_value = reladdr;
+           goto bss_ext_symbol;
+         }
+         continue;     /* Just undefined, not COMMON */
+
+           /* Lots of symbol types we can just ignore.  */
+
+       case N_UNDF:
+       case N_ABS:
+       case N_BSS:
+       case N_NBDATA:
+       case N_NBBSS:
+         continue;
+
+         /* Keep going . . .*/
+
+         /*
+          * Special symbol types for GNU
+          */
+       case N_INDR:
+       case N_INDR | N_EXT:
+       case N_SETA:
+       case N_SETA | N_EXT:
+       case N_SETT:
+       case N_SETT | N_EXT:
+       case N_SETD:
+       case N_SETD | N_EXT:
+       case N_SETB:
+       case N_SETB | N_EXT:
+       case N_SETV:
+         continue;
+
+         /*
+          * Debugger symbols
+          */
+
+       case N_SO: {
+         unsigned long valu = bufp->n_value;
+         /* Symbol number of the first symbol of this file (i.e. the N_SO
+            if there is just one, or the first if we have a pair).  */
+         int first_symnum = symnum;
+         
+         /* End the current partial symtab and start a new one */
+
+         SET_NAMESTRING();
+
+         /* Peek at the next symbol.  If it is also an N_SO, the
+            first one just indicates the directory.  */
+         if (symbuf_idx == symbuf_end)
+           fill_symbuf ();
+         bufp = &symbuf[symbuf_idx];
+         /* n_type is only a char, so swapping swapping is irrelevant.  */
+         if (bufp->n_type == (unsigned char)N_SO)
+           {
+             SWAP_SYMBOL (bufp);
+             SET_NAMESTRING ();
+             valu = bufp->n_value;
+             symbuf_idx++;
+             symnum++;
+           }
+         valu += addr;         /* Relocate */
+
+         if (pst && past_first_source_file)
+           {
+             end_psymtab (pst, psymtab_include_list, includes_used,
+                          first_symnum * sizeof (struct nlist), valu,
+                          dependency_list, dependencies_used,
+                          global_psymbols.next, static_psymbols.next);
+             pst = (struct partial_symtab *) 0;
+             includes_used = 0;
+             dependencies_used = 0;
+           }
+         else
+           past_first_source_file = 1;
+
+         pst = start_psymtab (symfile_name, addr,
+                              namestring, valu,
+                              first_symnum * sizeof (struct nlist),
+                              global_psymbols.next, static_psymbols.next);
+
+         continue;
+       }
+
+       case N_BINCL:
+         /* Add this bincl to the bincl_list for future EXCLs.  No
+            need to save the string; it'll be around until
+            read_dbx_symtab function returns */
+
+         SET_NAMESTRING();
+
+         add_bincl_to_list (pst, namestring, bufp->n_value);
+
+         /* Mark down an include file in the current psymtab */
+
+         psymtab_include_list[includes_used++] = namestring;
+         if (includes_used >= includes_allocated)
+           {
+             char **orig = psymtab_include_list;
+
+             psymtab_include_list = (char **)
+               alloca ((includes_allocated *= 2) *
+                       sizeof (char *));
+             bcopy (orig, psymtab_include_list,
+                    includes_used * sizeof (char *));
+           }
+
+         continue;
+
+       case N_SOL:
+         /* Mark down an include file in the current psymtab */
+
+         SET_NAMESTRING();
+
+         /* In C++, one may expect the same filename to come round many
+            times, when code is coming alternately from the main file
+            and from inline functions in other files. So I check to see
+            if this is a file we've seen before.
+
+            This seems to be a lot of time to be spending on N_SOL, but
+            things like "break expread.y:435" need to work (I
+            suppose the psymtab_include_list could be hashed or put
+            in a binary tree, if profiling shows this is a major hog).  */
+         {
+           register int i;
+           for (i = 0; i < includes_used; i++)
+             if (!strcmp (namestring, psymtab_include_list[i]))
+               {
+                 i = -1; 
+                 break;
+               }
+           if (i == -1)
+             continue;
+         }
+
+         psymtab_include_list[includes_used++] = namestring;
+         if (includes_used >= includes_allocated)
+           {
+             char **orig = psymtab_include_list;
+
+             psymtab_include_list = (char **)
+               alloca ((includes_allocated *= 2) *
+                       sizeof (char *));
+             bcopy (orig, psymtab_include_list,
+                    includes_used * sizeof (char *));
+           }
+         continue;
+
+       case N_LSYM:            /* Typedef or automatic variable. */
+         SET_NAMESTRING();
+
+         p = (char *) strchr (namestring, ':');
+
+         /* Skip if there is no :.  */
+         if (!p) continue;
+
+         switch (p[1])
+           {
+           case 'T':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  STRUCT_NAMESPACE, LOC_TYPEDEF,
+                                  static_psymbols, bufp->n_value);
+             if (p[2] == 't')
+               {
+                 /* Also a typedef with the same name.  */
+                 ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                      VAR_NAMESPACE, LOC_TYPEDEF,
+                                      static_psymbols, bufp->n_value);
+                 p += 1;
+               }
+             goto check_enum;
+           case 't':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_TYPEDEF,
+                                  static_psymbols, bufp->n_value);
+           check_enum:
+             /* If this is an enumerated type, we need to
+                add all the enum constants to the partial symbol
+                table.  This does not cover enums without names, e.g.
+                "enum {a, b} c;" in C, but fortunately those are
+                rare.  There is no way for GDB to find those from the
+                enum type without spending too much time on it.  Thus
+                to solve this problem, the compiler needs to put out separate
+                constant symbols ('c' N_LSYMS) for enum constants in
+                enums without names, or put out a dummy type.  */
+
+             /* We are looking for something of the form
+                <name> ":" ("t" | "T") [<number> "="] "e"
+                {<constant> ":" <value> ","} ";".  */
+
+             /* Skip over the colon and the 't' or 'T'.  */
+             p += 2;
+             /* This type may be given a number.  Skip over it.  */
+             while ((*p >= '0' && *p <= '9')
+                    || *p == '=')
+               p++;
+
+             if (*p++ == 'e')
+               {
+                 /* We have found an enumerated type.  */
+                 /* According to comments in read_enum_type
+                    a comma could end it instead of a semicolon.
+                    I don't know where that happens.
+                    Accept either.  */
+                 while (*p && *p != ';' && *p != ',')
+                   {
+                     char *q;
+
+                     /* Check for and handle cretinous dbx symbol name
+                        continuation!  */
+                     if (*p == '\\')
+                       p = next_symbol_text ();
+
+                     /* Point to the character after the name
+                        of the enum constant.  */
+                     for (q = p; *q && *q != ':'; q++)
+                       ;
+                     /* Note that the value doesn't matter for
+                        enum constants in psymtabs, just in symtabs.  */
+                     ADD_PSYMBOL_TO_LIST (p, q - p,
+                                          VAR_NAMESPACE, LOC_CONST,
+                                          static_psymbols, 0);
+                     /* Point past the name.  */
+                     p = q;
+                     /* Skip over the value.  */
+                     while (*p && *p != ',')
+                       p++;
+                     /* Advance past the comma.  */
+                     if (*p)
+                       p++;
+                   }
+               }
+
+             continue;
+           case 'c':
+             /* Constant, e.g. from "const" in Pascal.  */
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_CONST,
+                                  static_psymbols, bufp->n_value);
+             continue;
+           default:
+             /* Skip if the thing following the : is
+                not a letter (which indicates declaration of a local
+                variable, which we aren't interested in).  */
+             continue;
+           }
+
+       case N_FUN:
+       case N_GSYM:            /* Global (extern) variable; can be
+                                  data or bss (sigh).  */
+       case N_STSYM:           /* Data seg var -- static  */
+       case N_LCSYM:           /* BSS      "  */
+
+       case N_NBSTS:           /* Gould nobase.  */
+       case N_NBLCS:           /* symbols.  */
+
+       /* Following may probably be ignored; I'll leave them here
+          for now (until I do Pascal and Modula 2 extensions).  */
+
+       case N_PC:              /* I may or may not need this; I
+                                  suspect not.  */
+       case N_M2C:             /* I suspect that I can ignore this here. */
+       case N_SCOPE:           /* Same.   */
+
+         SET_NAMESTRING();
+
+         p = (char *) strchr (namestring, ':');
+         if (!p)
+           continue;           /* Not a debugging symbol.   */
+
+
+
+         /* Main processing section for debugging symbols which
+            the initial read through the symbol tables needs to worry
+            about.  If we reach this point, the symbol which we are
+            considering is definitely one we are interested in.
+            p must also contain the (valid) index into the namestring
+            which indicates the debugging type symbol.  */
+
+         switch (p[1])
+           {
+           case 'c':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_CONST,
+                                  static_psymbols, bufp->n_value);
+             continue;
+           case 'S':
+             bufp->n_value += addr;            /* Relocate */
+             ADD_PSYMBOL_ADDR_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_STATIC,
+                                  static_psymbols, bufp->n_value);
+             continue;
+           case 'G':
+             bufp->n_value += addr;            /* Relocate */
+             ADD_PSYMBOL_ADDR_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_EXTERNAL,
+                                  global_psymbols, bufp->n_value);
+             continue;
+
+           case 't':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_TYPEDEF,
+                                  global_psymbols, bufp->n_value);
+             continue;
+
+           case 'f':
+             ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+                                  VAR_NAMESPACE, LOC_BLOCK,
+                                  static_psymbols, bufp->n_value);
+             continue;
+
+             /* Two things show up here (hopefully); static symbols of
+                local scope (static used inside braces) or extensions
+                of structure symbols.  We can ignore both.  */
+           case 'V':
+           case '(':
+           case '0':
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+           case '8':
+           case '9':
+             /* Global functions are ignored here.  I'm not
+                sure what psymtab they go into (or just the misc
+                function vector).  */
+           case 'F':
+             continue;
+
+           default:
+             /* Unexpected symbol.  Ignore it; perhaps it is an extension
+                that we don't know about.
+
+                Someone says sun cc puts out symbols like
+                /foo/baz/maclib::/usr/local/bin/maclib,
+                which would get here with a symbol type of ':'.  */
+             continue;
+           }
+
+       case N_EXCL:
+
+         SET_NAMESTRING();
+
+         /* Find the corresponding bincl and mark that psymtab on the
+            psymtab dependency list */
+         {
+           struct partial_symtab *needed_pst =
+             find_corresponding_bincl_psymtab (namestring, bufp->n_value);
+
+           /* If this include file was defined earlier in this file,
+              leave it alone.  */
+           if (needed_pst == pst) continue;
+
+           if (needed_pst)
+             {
+               int i;
+               int found = 0;
+
+               for (i = 0; i < dependencies_used; i++)
+                 if (dependency_list[i] == needed_pst)
+                   {
+                     found = 1;
+                     break;
+                   }
+
+               /* If it's already in the list, skip the rest.  */
+               if (found) continue;
+
+               dependency_list[dependencies_used++] = needed_pst;
+               if (dependencies_used >= dependencies_allocated)
+                 {
+                   struct partial_symtab **orig = dependency_list;
+                   dependency_list =
+                     (struct partial_symtab **)
+                       alloca ((dependencies_allocated *= 2)
+                               * sizeof (struct partial_symtab *));
+                   bcopy (orig, dependency_list,
+                          (dependencies_used
+                           * sizeof (struct partial_symtab *)));
+#ifdef DEBUG_INFO
+                   fprintf (stderr, "Had to reallocate dependency list.\n");
+                   fprintf (stderr, "New dependencies allocated: %d\n",
+                            dependencies_allocated);
+#endif
+                 }
+             }
+           else
+             error ("Invalid symbol data: \"repeated\" header file not previously seen, at symtab pos %d.",
+                    symnum);
+         }
+         continue;
+
+       case N_EINCL:
+       case N_DSLINE:
+       case N_BSLINE:
+       case N_SSYM:            /* Claim: Structure or union element.
+                                  Hopefully, I can ignore this.  */
+       case N_ENTRY:           /* Alternate entry point; can ignore. */
+       case N_MAIN:            /* Can definitely ignore this.   */
+       case N_CATCH:           /* These are GNU C++ extensions */
+       case N_EHDECL:          /* that can safely be ignored here. */
+       case N_LENG:
+       case N_BCOMM:
+       case N_ECOMM:
+       case N_ECOML:
+       case N_FNAME:
+       case N_SLINE:
+       case N_RSYM:
+       case N_PSYM:
+       case N_LBRAC:
+       case N_RBRAC:
+       case N_NSYMS:           /* Ultrix 4.0: symbol count */
+         /* These symbols aren't interesting; don't worry about them */
+
+         continue;
+
+       default:
+         /* If we haven't found it yet, ignore it.  It's probably some
+            new type we don't know about yet.  */
+         complain (&unknown_symtype_complaint, bufp->n_type);
+         continue;
+       }
+    }
+
+  /* If there's stuff to be cleaned up, clean it up.  */
+  if (entry_point < bufp->n_value
+      && entry_point >= last_o_file_start)
+    {
+      startup_file_start = last_o_file_start;
+      startup_file_end = bufp->n_value;
+    }
+
+  if (pst)
+    {
+      end_psymtab (pst, psymtab_include_list, includes_used,
+                  symnum * sizeof (struct nlist), end_of_text_addr,
+                  dependency_list, dependencies_used,
+                  global_psymbols.next, static_psymbols.next);
+      includes_used = 0;
+      dependencies_used = 0;
+      pst = (struct partial_symtab *) 0;
+    }
+
+  free_bincl_list ();
+  discard_cleanups (old_chain);
+}
+
+/*
+ * Allocate and partially fill a partial symtab.  It will be
+ * completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal).  */
+static struct partial_symtab *
+start_psymtab (symfile_name, addr,
+              filename, textlow, ldsymoff, global_syms, static_syms)
+     char *symfile_name;
+     CORE_ADDR addr;
+     char *filename;
+     CORE_ADDR textlow;
+     int ldsymoff;
+     struct partial_symbol *global_syms;
+     struct partial_symbol *static_syms;
+{
+  struct partial_symtab *result =
+    (struct partial_symtab *) obstack_alloc (psymbol_obstack,
+                                            sizeof (struct partial_symtab));
+
+  result->addr = addr;
+
+  result->symfile_name =
+    (char *) obstack_alloc (psymbol_obstack,
+                           strlen (symfile_name) + 1);
+  strcpy (result->symfile_name, symfile_name);
+  
+  result->filename =
+    (char *) obstack_alloc (psymbol_obstack,
+                           strlen (filename) + 1);
+  strcpy (result->filename, filename);
+
+  result->textlow = textlow;
+  result->ldsymoff = ldsymoff;
+
+  result->readin = 0;
+  result->symtab = 0;
+  result->read_symtab = dbx_psymtab_to_symtab;
+
+  result->globals_offset = global_syms - global_psymbols.list;
+  result->statics_offset = static_syms - static_psymbols.list;
+
+  result->n_global_syms = 0;
+  result->n_static_syms = 0;
+
+
+  return result;
+}
+
+static int
+compare_psymbols (s1, s2)
+     register struct partial_symbol *s1, *s2;
+{
+  register char
+    *st1 = SYMBOL_NAME (s1),
+    *st2 = SYMBOL_NAME (s2);
+
+  return (st1[0] - st2[0] ? st1[0] - st2[0] :
+         strcmp (st1 + 1, st2 + 1));
+}
+
+
+/* Close off the current usage of a partial_symbol table entry.  This
+   involves setting the correct number of includes (with a realloc),
+   setting the high text mark, setting the symbol length in the
+   executable, and setting the length of the global and static lists
+   of psymbols.
+
+   The global symbols and static symbols are then seperately sorted.
+
+   Then the partial symtab is put on the global list.
+   *** List variables and peculiarities of same. ***
+   */
+static void
+end_psymtab (pst, include_list, num_includes, capping_symbol_offset,
+            capping_text, dependency_list, number_dependencies,
+            capping_global, capping_static)
+     struct partial_symtab *pst;
+     char **include_list;
+     int num_includes;
+     int capping_symbol_offset;
+     CORE_ADDR capping_text;
+     struct partial_symtab **dependency_list;
+     int number_dependencies;
+     struct partial_symbol *capping_global, *capping_static;
+{
+  int i;
+
+  pst->ldsymlen = capping_symbol_offset - pst->ldsymoff;
+  pst->texthigh = capping_text;
+
+  pst->n_global_syms =
+    capping_global - (global_psymbols.list + pst->globals_offset);
+  pst->n_static_syms =
+    capping_static - (static_psymbols.list + pst->statics_offset);
+
+  pst->number_of_dependencies = number_dependencies;
+  if (number_dependencies)
+    {
+      pst->dependencies = (struct partial_symtab **)
+       obstack_alloc (psymbol_obstack,
+                      number_dependencies * sizeof (struct partial_symtab *));
+      bcopy (dependency_list, pst->dependencies,
+            number_dependencies * sizeof (struct partial_symtab *));
+    }
+  else
+    pst->dependencies = 0;
+
+  for (i = 0; i < num_includes; i++)
+    {
+      /* Eventually, put this on obstack */
+      struct partial_symtab *subpst =
+       (struct partial_symtab *)
+         obstack_alloc (psymbol_obstack,
+                        sizeof (struct partial_symtab));
+
+      subpst->filename =
+       (char *) obstack_alloc (psymbol_obstack,
+                               strlen (include_list[i]) + 1);
+      strcpy (subpst->filename, include_list[i]);
+
+      subpst->symfile_name = pst->symfile_name;
+      subpst->addr = pst->addr;
+      subpst->ldsymoff =
+       subpst->ldsymlen =
+         subpst->textlow =
+           subpst->texthigh = 0;
+
+      subpst->dependencies = (struct partial_symtab **)
+       obstack_alloc (psymbol_obstack,
+                      sizeof (struct partial_symtab *));
+      subpst->dependencies[0] = pst;
+      subpst->number_of_dependencies = 1;
+
+      subpst->globals_offset =
+       subpst->n_global_syms =
+         subpst->statics_offset =
+           subpst->n_static_syms = 0;
+
+      subpst->readin = 0;
+      subpst->read_symtab = dbx_psymtab_to_symtab;
+
+      subpst->next = partial_symtab_list;
+      partial_symtab_list = subpst;
+    }
+
+  /* Sort the global list; don't sort the static list */
+  qsort (global_psymbols.list + pst->globals_offset, pst->n_global_syms,
+        sizeof (struct partial_symbol), compare_psymbols);
+
+  /* Put the psymtab on the psymtab list */
+  pst->next = partial_symtab_list;
+  partial_symtab_list = pst;
+}
+\f
+static void
+psymtab_to_symtab_1 (pst, desc, stringtab, stringtab_size, sym_offset)
+     struct partial_symtab *pst;
+     int desc;
+     char *stringtab;
+     int stringtab_size;
+     int sym_offset;
+{
+  struct cleanup *old_chain;
+  int i;
+  
+  if (!pst)
+    return;
+
+  if (pst->readin)
+    {
+      fprintf (stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",
+              pst->filename);
+      return;
+    }
+
+  /* Read in all partial symbtabs on which this one is dependent */
+  for (i = 0; i < pst->number_of_dependencies; i++)
+    if (!pst->dependencies[i]->readin)
+      {
+       /* Inform about additional files that need to be read in.  */
+       if (info_verbose)
+         {
+           fputs_filtered (" ", stdout);
+           wrap_here ("");
+           fputs_filtered ("and ", stdout);
+           wrap_here ("");
+           printf_filtered ("%s...", pst->dependencies[i]->filename);
+           wrap_here ("");             /* Flush output */
+           fflush (stdout);
+         }
+       psymtab_to_symtab_1 (pst->dependencies[i], desc,
+                            stringtab, stringtab_size, sym_offset);
+      }
+
+  if (pst->ldsymlen)           /* Otherwise it's a dummy */
+    {
+      /* Init stuff necessary for reading in symbols */
+      free_pendings = 0;
+      pending_blocks = 0;
+      file_symbols = 0;
+      global_symbols = 0;
+      old_chain = make_cleanup (really_free_pendings, 0);
+
+      /* Read in this files symbols */
+      lseek (desc, sym_offset, L_SET);
+      read_ofile_symtab (desc, stringtab, stringtab_size,
+                        pst->ldsymoff,
+                        pst->ldsymlen, pst->textlow,
+                        pst->texthigh - pst->textlow, pst->addr);
+      sort_symtab_syms (symtab_list); /* At beginning since just added */
+
+      do_cleanups (old_chain);
+    }
+
+  pst->readin = 1;
+}
+
+/*
+ * Read in all of the symbols for a given psymtab for real.
+ * Be verbose about it if the user wants that.
+ */
+static void
+dbx_psymtab_to_symtab (pst)
+     struct partial_symtab *pst;
+{
+  int desc;
+  char *stringtab;
+  int stsize, val;
+  struct stat statbuf;
+  struct cleanup *old_chain;
+  bfd *sym_bfd;
+  long st_temp;
+
+  if (!pst)
+    return;
+
+  if (pst->readin)
+    {
+      fprintf (stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",
+              pst->filename);
+      return;
+    }
+
+  if (pst->ldsymlen || pst->number_of_dependencies)
+    {
+      /* Print the message now, before reading the string table,
+        to avoid disconcerting pauses.  */
+      if (info_verbose)
+       {
+         printf_filtered ("Reading in symbols for %s...", pst->filename);
+         fflush (stdout);
+       }
+
+      /* Open symbol file and read in string table.  Symbol_file_command
+        guarantees that the symbol file name will be absolute, so there is
+        no need for openp.  */
+      desc = open(pst->symfile_name, O_RDONLY, 0);
+
+      if (desc < 0)
+       perror_with_name (pst->symfile_name);
+
+      sym_bfd = bfd_fdopenr (pst->symfile_name, NULL, desc);
+      if (!sym_bfd)
+       {
+         (void)close (desc);
+         error ("Could not open `%s' to read symbols: %s",
+                pst->symfile_name, bfd_errmsg (bfd_error));
+       }
+      old_chain = make_cleanup (bfd_close, sym_bfd);
+      if (!bfd_check_format (sym_bfd, bfd_object))
+         error ("\"%s\": can't read symbols: %s.",
+                pst->symfile_name, bfd_errmsg (bfd_error));
+
+      /* We keep the string table for symfile resident in memory, but
+        not the string table for any other symbol files.  */
+      if (0 != strcmp(pst->symfile_name, symfile))
+       {
+         /* Read in the string table */
+
+         /* FIXME, this uses internal BFD variables.  See above in
+            dbx_symbol_file_open where the macro is defined!  */
+         lseek (desc, STRING_TABLE_OFFSET, L_SET);
+
+         val = myread (desc, &st_temp, sizeof st_temp);
+         if (val < 0)
+             perror_with_name (pst->symfile_name);
+         stsize = bfd_h_getlong (sym_bfd, (unsigned char *)&st_temp);
+         if (fstat (desc, &statbuf) < 0)
+           perror_with_name (pst->symfile_name);
+         
+         if (stsize >= 0 && stsize < statbuf.st_size)
+           {
+#ifdef BROKEN_LARGE_ALLOCA
+             stringtab = (char *) xmalloc (stsize);
+             make_cleanup (free, stringtab);
+#else
+             stringtab = (char *) alloca (stsize);
+#endif
+           }
+         else
+           stringtab = NULL;
+         if (stringtab == NULL && stsize != 0)
+           error ("ridiculous string table size: %d bytes", stsize);
+
+         /* FIXME, this uses internal BFD variables.  See above in
+            dbx_symbol_file_open where the macro is defined!  */
+         val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
+         if (val < 0)
+           perror_with_name (pst->symfile_name);
+         val = myread (desc, stringtab, stsize);
+         if (val < 0)
+           perror_with_name (pst->symfile_name);
+       }
+      else
+       {
+         stringtab = symfile_string_table;
+         stsize = symfile_string_table_size;
+       }
+
+      symfile_bfd = sym_bfd;           /* Kludge for SWAP_SYMBOL */
+
+      /* FIXME, this uses internal BFD variables.  See above in
+        dbx_symbol_file_open where the macro is defined!  */
+      psymtab_to_symtab_1 (pst, desc, stringtab, stsize,
+                          SYMBOL_TABLE_OFFSET);
+
+      /* Match with global symbols.  This only needs to be done once,
+         after all of the symtabs and dependencies have been read in.   */
+      scan_file_globals ();
+
+      do_cleanups (old_chain);
+
+      /* Finish up the debug error message.  */
+      if (info_verbose)
+       printf_filtered ("done.\n");
+    }
+}
+
+/*
+ * Scan through all of the global symbols defined in the object file,
+ * assigning values to the debugging symbols that need to be assigned
+ * to.  Get these symbols from the misc function list.
+ */
+static void
+scan_file_globals ()
+{
+  int hash;
+  int mf;
+
+  for (mf = 0; mf < misc_function_count; mf++)
+    {
+      char *namestring = misc_function_vector[mf].name;
+      struct symbol *sym, *prev;
+
+      QUIT;
+
+      prev = (struct symbol *) 0;
+
+      /* Get the hash index and check all the symbols
+        under that hash index. */
+
+      hash = hashname (namestring);
+
+      for (sym = global_sym_chain[hash]; sym;)
+       {
+         if (*namestring == SYMBOL_NAME (sym)[0]
+             && !strcmp(namestring + 1, SYMBOL_NAME (sym) + 1))
+           {
+             /* Splice this symbol out of the hash chain and
+                assign the value we have to it. */
+             if (prev)
+               SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym);
+             else
+               global_sym_chain[hash] = SYMBOL_VALUE_CHAIN (sym);
+             
+             /* Check to see whether we need to fix up a common block.  */
+             /* Note: this code might be executed several times for
+                the same symbol if there are multiple references.  */
+             if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+               fix_common_block (sym, misc_function_vector[mf].address);
+             else
+               SYMBOL_VALUE_ADDRESS (sym) = misc_function_vector[mf].address;
+             
+             if (prev)
+               sym = SYMBOL_VALUE_CHAIN (prev);
+             else
+               sym = global_sym_chain[hash];
+           }
+         else
+           {
+             prev = sym;
+             sym = SYMBOL_VALUE_CHAIN (sym);
+           }
+       }
+    }
+}
+
+/* Process a pair of symbols.  Currently they must both be N_SO's.  */
+static void
+process_symbol_pair (type1, desc1, value1, name1,
+                    type2, desc2, value2, name2)
+     int type1;
+     int desc1;
+     CORE_ADDR value1;
+     char *name1;
+     int type2;
+     int desc2;
+     CORE_ADDR value2;
+     char *name2;
+{
+  /* No need to check PCC_SOL_BROKEN, on the assumption that such
+     broken PCC's don't put out N_SO pairs.  */
+  if (last_source_file)
+    end_symtab (value2);
+  start_symtab (name2, name1, value2);
+}
+
+/*
+ * Read in a defined section of a specific object file's symbols.
+ *
+ * DESC is the file descriptor for the file, positioned at the
+ * beginning of the symtab
+ * STRINGTAB is a pointer to the files string
+ * table, already read in
+ * SYM_OFFSET is the offset within the file of
+ * the beginning of the symbols we want to read, NUM_SUMBOLS is the
+ * number of symbols to read
+ * TEXT_OFFSET is the beginning of the text segment we are reading symbols for
+ * TEXT_SIZE is the size of the text segment read in.
+ * OFFSET is a relocation offset which gets added to each symbol
+ */
+
+static void
+read_ofile_symtab (desc, stringtab, stringtab_size, sym_offset,
+                  sym_size, text_offset, text_size, offset)
+     int desc;
+     register char *stringtab;
+     unsigned int stringtab_size;
+     int sym_offset;
+     int sym_size;
+     CORE_ADDR text_offset;
+     int text_size;
+     int offset;
+{
+  register char *namestring;
+  struct nlist *bufp;
+  unsigned char type;
+  subfile_stack = 0;
+
+  stringtab_global = stringtab;
+  last_source_file = 0;
+
+  symtab_input_desc = desc;
+  symbuf_end = symbuf_idx = 0;
+
+  /* It is necessary to actually read one symbol *before* the start
+     of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
+     occurs before the N_SO symbol.
+
+     Detecting this in read_dbx_symtab
+     would slow down initial readin, so we look for it here instead.  */
+  if (sym_offset >= (int)sizeof (struct nlist))
+    {
+      lseek (desc, sym_offset - sizeof (struct nlist), L_INCR);
+      fill_symbuf ();
+      bufp = &symbuf[symbuf_idx++];
+      SWAP_SYMBOL (bufp);
+
+      if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size)
+       error ("Invalid symbol data: bad string table offset: %d",
+              bufp->n_un.n_strx);
+      namestring = bufp->n_un.n_strx + stringtab;
+
+      processing_gcc_compilation =
+       (bufp->n_type == N_TEXT
+        && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL));
+    }
+  else
+    {
+      /* The N_SO starting this symtab is the first symbol, so we
+        better not check the symbol before it.  I'm not this can
+        happen, but it doesn't hurt to check for it.  */
+      lseek(desc, sym_offset, L_INCR);
+      processing_gcc_compilation = 0;
+    }
+
+  if (symbuf_idx == symbuf_end)
+    fill_symbuf();
+  bufp = &symbuf[symbuf_idx];
+  if (bufp->n_type != (unsigned char)N_SO)
+    error("First symbol in segment of executable not a source symbol");
+
+  for (symnum = 0;
+       symnum < sym_size / sizeof(struct nlist);
+       symnum++)
+    {
+      QUIT;                    /* Allow this to be interruptable */
+      if (symbuf_idx == symbuf_end)
+       fill_symbuf();
+      bufp = &symbuf[symbuf_idx++];
+      SWAP_SYMBOL (bufp);
+
+      type = bufp->n_type & N_TYPE;
+      if (type == (unsigned char)N_CATCH)
+       {
+         /* N_CATCH is not fixed up by the linker, and unfortunately,
+            there's no other place to put it in the .stab map.  */
+         /* FIXME, do we also have to add OFFSET or something? -- gnu@cygnus */
+         bufp->n_value += text_offset;
+       }
+      else if (type == N_TEXT || type == N_DATA || type == N_BSS)
+       bufp->n_value += offset;
+
+      type = bufp->n_type;
+      if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size)
+       error ("Invalid symbol data: bad string table offset: %d",
+              bufp->n_un.n_strx);
+      namestring = bufp->n_un.n_strx + stringtab;
+
+      if (type & N_STAB)
+       {
+         short desc = bufp->n_desc;
+         unsigned long valu = bufp->n_value;
+
+         /* Check for a pair of N_SO symbols.  */
+         if (type == (unsigned char)N_SO)
+           {
+             if (symbuf_idx == symbuf_end)
+               fill_symbuf ();
+             bufp = &symbuf[symbuf_idx];
+             if (bufp->n_type == (unsigned char)N_SO)
+               {
+                 char *namestring2;
+
+                 SWAP_SYMBOL (bufp);
+                 bufp->n_value += offset;              /* Relocate */
+                 symbuf_idx++;
+                 symnum++;
+
+                 if (bufp->n_un.n_strx < 0
+                     || bufp->n_un.n_strx >= stringtab_size)
+                   error ("Invalid symbol data: bad string table offset: %d",
+                          bufp->n_un.n_strx);
+                 namestring2 = bufp->n_un.n_strx + stringtab;
+
+                 process_symbol_pair (N_SO, desc, valu, namestring,
+                                      N_SO, bufp->n_desc, bufp->n_value,
+                                      namestring2);
+               }
+             else
+               process_one_symbol(type, desc, valu, namestring);
+           }
+         else
+           process_one_symbol (type, desc, valu, namestring);
+       }
+      /* We skip checking for a new .o or -l file; that should never
+         happen in this routine. */
+      else if (type == N_TEXT
+              && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL))
+       /* I don't think this code will ever be executed, because
+          the GCC_COMPILED_FLAG_SYMBOL usually is right before
+          the N_SO symbol which starts this source file.
+          However, there is no reason not to accept
+          the GCC_COMPILED_FLAG_SYMBOL anywhere.  */
+       processing_gcc_compilation = 1;
+      else if (type & N_EXT || type == (unsigned char)N_TEXT
+              || type == (unsigned char)N_NBTEXT
+              )
+         /* Global symbol: see if we came across a dbx defintion for
+            a corresponding symbol.  If so, store the value.  Remove
+            syms from the chain when their values are stored, but
+            search the whole chain, as there may be several syms from
+            different files with the same name. */
+         /* This is probably not true.  Since the files will be read
+            in one at a time, each reference to a global symbol will
+            be satisfied in each file as it appears. So we skip this
+            section. */
+         ;
+    }
+  end_symtab (text_offset + text_size);
+}
+\f
+static int
+hashname (name)
+     char *name;
+{
+  register char *p = name;
+  register int total = p[0];
+  register int c;
+
+  c = p[1];
+  total += c << 2;
+  if (c)
+    {
+      c = p[2];
+      total += c << 4;
+      if (c)
+       total += p[3] << 6;
+    }
+
+  /* Ensure result is positive.  */
+  if (total < 0) total += (1000 << 6);
+  return total % HASHSIZE;
+}
+
+\f
+static void
+process_one_symbol (type, desc, valu, name)
+     int type, desc;
+     CORE_ADDR valu;
+     char *name;
+{
+#ifndef SUN_FIXED_LBRAC_BUG
+  /* This records the last pc address we've seen.  We depend on their being
+     an SLINE or FUN or SO before the first LBRAC, since the variable does
+     not get reset in between reads of different symbol files.  */
+  static CORE_ADDR last_pc_address;
+#endif
+  register struct context_stack *new;
+  char *colon_pos;
+
+  /* Something is wrong if we see real data before
+     seeing a source file name.  */
+
+  if (last_source_file == 0 && type != (unsigned char)N_SO)
+    {
+      /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines
+        where that code is defined.  */
+      if (IGNORE_SYMBOL (type))
+       return;
+
+      /* FIXME, this should not be an error, since it precludes extending
+         the symbol table information in this way...  */
+      error ("Invalid symbol data: does not start by identifying a source file.");
+    }
+
+  switch (type)
+    {
+    case N_FUN:
+    case N_FNAME:
+      /* Either of these types of symbols indicates the start of
+        a new function.  We must process its "name" normally for dbx,
+        but also record the start of a new lexical context, and possibly
+        also the end of the lexical context for the previous function.  */
+      /* This is not always true.  This type of symbol may indicate a
+         text segment variable.  */
+
+#ifndef SUN_FIXED_LBRAC_BUG
+      last_pc_address = valu;  /* Save for SunOS bug circumcision */
+#endif
+
+      colon_pos = strchr (name, ':');
+      if (!colon_pos++
+         || (*colon_pos != 'f' && *colon_pos != 'F'))
+       {
+         define_symbol (valu, name, desc, type);
+         break;
+       }
+
+      within_function = 1;
+      if (context_stack_depth > 0)
+       {
+         new = &context_stack[--context_stack_depth];
+         /* Make a block for the local symbols within.  */
+         finish_block (new->name, &local_symbols, new->old_blocks,
+                       new->start_addr, valu);
+       }
+      /* Stack must be empty now.  */
+      if (context_stack_depth != 0)
+       error ("Invalid symbol data: unmatched N_LBRAC before symtab pos %d.",
+              symnum);
+
+      new = &context_stack[context_stack_depth++];
+      new->old_blocks = pending_blocks;
+      new->start_addr = valu;
+      new->name = define_symbol (valu, name, desc, type);
+      local_symbols = 0;
+      break;
+
+    case N_CATCH:
+      /* Record the address at which this catch takes place.  */
+      define_symbol (valu, name, desc, type);
+      break;
+
+    case N_EHDECL:
+      /* Don't know what to do with these yet.  */
+      error ("action uncertain for eh extensions");
+      break;
+
+    case N_LBRAC:
+      /* This "symbol" just indicates the start of an inner lexical
+        context within a function.  */
+
+#if !defined (BLOCK_ADDRESS_ABSOLUTE)
+      /* On most machines, the block addresses are relative to the
+        N_SO, the linker did not relocate them (sigh).  */
+      valu += last_source_start_addr;
+#endif
+
+#ifndef SUN_FIXED_LBRAC_BUG
+      if (valu < last_pc_address) {
+       /* Patch current LBRAC pc value to match last handy pc value */
+       complain (&lbrac_complaint, 0);
+       valu = last_pc_address;
+      }
+#endif
+      if (context_stack_depth == context_stack_size)
+       {
+         context_stack_size *= 2;
+         context_stack = (struct context_stack *)
+           xrealloc (context_stack,
+                     (context_stack_size
+                      * sizeof (struct context_stack)));
+       }
+
+      new = &context_stack[context_stack_depth++];
+      new->depth = desc;
+      new->locals = local_symbols;
+      new->old_blocks = pending_blocks;
+      new->start_addr = valu;
+      new->name = 0;
+      local_symbols = 0;
+      break;
+
+    case N_RBRAC:
+      /* This "symbol" just indicates the end of an inner lexical
+        context that was started with N_LBRAC.  */
+
+#if !defined (BLOCK_ADDRESS_ABSOLUTE)
+      /* On most machines, the block addresses are relative to the
+        N_SO, the linker did not relocate them (sigh).  */
+      valu += last_source_start_addr;
+#endif
+
+      new = &context_stack[--context_stack_depth];
+      if (desc != new->depth)
+       error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum);
+
+      /* Some compilers put the variable decls inside of an
+         LBRAC/RBRAC block.  This macro should be nonzero if this
+        is true.  DESC is N_DESC from the N_RBRAC symbol.
+        GCC_P is true if we've detected the GCC_COMPILED_SYMBOL.  */
+#if !defined (VARIABLES_INSIDE_BLOCK)
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) 0
+#endif
+
+      /* Can only use new->locals as local symbols here if we're in
+         gcc or on a machine that puts them before the lbrack.  */
+      if (!VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+       local_symbols = new->locals;
+
+      /* If this is not the outermost LBRAC...RBRAC pair in the
+        function, its local symbols preceded it, and are the ones
+        just recovered from the context stack.  Defined the block for them.
+
+        If this is the outermost LBRAC...RBRAC pair, there is no
+        need to do anything; leave the symbols that preceded it
+        to be attached to the function's own block.  However, if
+        it is so, we need to indicate that we just moved outside
+        of the function.  */
+      if (local_symbols
+         && (context_stack_depth
+             > !VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation)))
+       {
+         /* FIXME Muzzle a compiler bug that makes end < start.  */
+         if (new->start_addr > valu)
+           {
+             complain(&lbrac_rbrac_complaint, 0);
+             new->start_addr = valu;
+           }
+         /* Make a block for the local symbols within.  */
+         finish_block (0, &local_symbols, new->old_blocks,
+                       new->start_addr, valu);
+       }
+      else
+       {
+         within_function = 0;
+       }
+      if (VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+       /* Now pop locals of block just finished.  */
+       local_symbols = new->locals;
+      break;
+
+    case N_FN | N_EXT:
+      /* This kind of symbol supposedly indicates the start
+        of an object file.  In fact this type does not appear.  */
+      break;
+
+    case N_SO:
+      /* This type of symbol indicates the start of data
+        for one source file.
+        Finish the symbol table of the previous source file
+        (if any) and start accumulating a new symbol table.  */
+#ifndef SUN_FIXED_LBRAC_BUG
+      last_pc_address = valu;  /* Save for SunOS bug circumcision */
+#endif
+  
+#ifdef PCC_SOL_BROKEN
+      /* pcc bug, occasionally puts out SO for SOL.  */
+      if (context_stack_depth > 0)
+       {
+         start_subfile (name, NULL);
+         break;
+       }
+#endif
+      if (last_source_file)
+       end_symtab (valu);
+      start_symtab (name, NULL, valu);
+      break;
+
+    case N_SOL:
+      /* This type of symbol indicates the start of data for
+        a sub-source-file, one whose contents were copied or
+        included in the compilation of the main source file
+        (whose name was given in the N_SO symbol.)  */
+      start_subfile (name, NULL);
+      break;
+
+    case N_BINCL:
+      push_subfile ();
+      add_new_header_file (name, valu);
+      start_subfile (name, NULL);
+      break;
+
+    case N_EINCL:
+      start_subfile (pop_subfile (), NULL);
+      break;
+
+    case N_EXCL:
+      add_old_header_file (name, valu);
+      break;
+
+    case N_SLINE:
+      /* This type of "symbol" really just records
+        one line-number -- core-address correspondence.
+        Enter it in the line list for this symbol table.  */
+#ifndef SUN_FIXED_LBRAC_BUG
+      last_pc_address = valu;  /* Save for SunOS bug circumcision */
+#endif
+      record_line (desc, valu);
+      break;
+
+    case N_BCOMM:
+      if (common_block)
+       error ("Invalid symbol data: common within common at symtab pos %d",
+              symnum);
+      common_block = local_symbols;
+      common_block_i = local_symbols ? local_symbols->nsyms : 0;
+      break;
+
+    case N_ECOMM:
+      /* Symbols declared since the BCOMM are to have the common block
+        start address added in when we know it.  common_block points to
+        the first symbol after the BCOMM in the local_symbols list;
+        copy the list and hang it off the symbol for the common block name
+        for later fixup.  */
+      {
+       int i;
+       struct symbol *sym =
+         (struct symbol *) xmalloc (sizeof (struct symbol));
+       bzero (sym, sizeof *sym);
+       SYMBOL_NAME (sym) = savestring (name, strlen (name));
+       SYMBOL_CLASS (sym) = LOC_BLOCK;
+       SYMBOL_NAMESPACE (sym) = (enum namespace)((long)
+         copy_pending (local_symbols, common_block_i, common_block));
+       i = hashname (SYMBOL_NAME (sym));
+       SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+       global_sym_chain[i] = sym;
+       common_block = 0;
+       break;
+      }
+
+    case N_ECOML:
+    case N_LENG:
+      break;
+
+    default:
+      if (name)
+       define_symbol (valu, name, desc, type);
+    }
+}
+\f
+/* 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.
+   TYPENUMS will then be used as an argument to dbx_lookup_type.  */
+
+static void
+read_type_number (pp, typenums)
+     register char **pp;
+     register int *typenums;
+{
+  if (**pp == '(')
+    {
+      (*pp)++;
+      typenums[0] = read_number (pp, ',');
+      typenums[1] = read_number (pp, ')');
+    }
+  else
+    {
+      typenums[0] = 0;
+      typenums[1] = read_number (pp, 0);
+    }
+}
+\f
+/* To handle GNU C++ typename abbreviation, we need to be able to
+   fill in a type's name as soon as space for that type is allocated.
+   `type_synonym_name' is the name of the type being allocated.
+   It is cleared as soon as it is used (lest all allocated types
+   get this name).  */
+static char *type_synonym_name;
+
+static struct symbol *
+define_symbol (valu, string, desc, type)
+     unsigned int valu;
+     char *string;
+     int desc;
+     int type;
+{
+  register struct symbol *sym;
+  char *p = (char *) strchr (string, ':');
+  int deftype;
+  int synonym = 0;
+  register int i;
+
+  /* Ignore syms with empty names.  */
+  if (string[0] == 0)
+    return 0;
+
+  /* Ignore old-style symbols from cc -go  */
+  if (p == 0)
+    return 0;
+
+  sym = (struct symbol *)obstack_alloc (symbol_obstack, sizeof (struct symbol));
+
+  if (processing_gcc_compilation) {
+    /* 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.  */
+    SYMBOL_LINE(sym) = desc;
+  } else {
+    SYMBOL_LINE(sym) = 0;                      /* unknown */
+  }
+  
+  if (string[0] == CPLUS_MARKER)
+    {
+      /* Special GNU C++ names.  */
+      switch (string[1])
+       {
+       case 't':
+         SYMBOL_NAME (sym) = "this";
+         break;
+       case 'v': /* $vtbl_ptr_type */
+         /* Was: SYMBOL_NAME (sym) = "vptr"; */
+         goto normal;
+       case 'e':
+         SYMBOL_NAME (sym) = "eh_throw";
+         break;
+
+       case '_':
+         /* This was an anonymous type that was never fixed up.  */
+         goto normal;
+
+       default:
+         abort ();
+       }
+    }
+  else
+    {
+    normal:
+      SYMBOL_NAME (sym)
+       = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1));
+      /* Open-coded bcopy--saves function call time.  */
+      {
+       register char *p1 = string;
+       register char *p2 = SYMBOL_NAME (sym);
+       while (p1 != p)
+         *p2++ = *p1++;
+       *p2++ = '\0';
+      }
+    }
+  p++;
+  /* Determine the type of name being defined.  */
+  /* The Acorn RISC machine's compiler can put out locals that don't
+     start with "234=" or "(3,4)=", so assume anything other than the
+     deftypes we know how to handle is a local.  */
+  /* (Peter Watkins @ Computervision)
+     Handle Sun-style local fortran array types 'ar...' . 
+     (gnu@cygnus.com) -- this strchr() handles them properly?
+     (tiemann@cygnus.com) -- 'C' is for catch.  */
+  if (!strchr ("cfFGpPrStTvVXC", *p))
+    deftype = 'l';
+  else
+    deftype = *p++;
+
+  /* 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 (deftype == 'c')
+    {
+      if (*p++ != '=')
+       error ("Invalid symbol data at symtab pos %d.", symnum);
+      switch (*p++)
+       {
+       case 'r':
+         {
+           double d = atof (p);
+           char *valu;
+
+           SYMBOL_TYPE (sym) = builtin_type_double;
+           valu = (char *) obstack_alloc (symbol_obstack, sizeof (double));
+           bcopy (&d, valu, sizeof (double));
+           SWAP_TARGET_AND_HOST (valu, sizeof (double));
+           SYMBOL_VALUE_BYTES (sym) = valu;
+           SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+         }
+         break;
+       case 'i':
+         {
+           SYMBOL_TYPE (sym) = builtin_type_int;
+           SYMBOL_VALUE (sym) = atoi (p);
+           SYMBOL_CLASS (sym) = LOC_CONST;
+         }
+         break;
+       case 'e':
+         /* 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,;").  */
+         {
+           int typenums[2];
+           
+           read_type_number (&p, typenums);
+           if (*p++ != ',')
+             error ("Invalid symbol data: no comma in enum const symbol");
+           
+           SYMBOL_TYPE (sym) = *dbx_lookup_type (typenums);
+           SYMBOL_VALUE (sym) = atoi (p);
+           SYMBOL_CLASS (sym) = LOC_CONST;
+         }
+         break;
+       default:
+         error ("Invalid symbol data at symtab pos %d.", symnum);
+       }
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &file_symbols);
+      return sym;
+    }
+
+  /* Now usually comes a number that says which data type,
+     and possibly more stuff to define the type
+     (all of which is handled by read_type)  */
+
+  if (deftype == 'p' && *p == 'F')
+    /* 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++;
+      SYMBOL_TYPE (sym)
+       = lookup_pointer_type (lookup_function_type (read_type (&p)));
+    }
+  else
+    {
+      struct type *type;
+      synonym = *p == 't';
+
+      if (synonym)
+       {
+         p += 1;
+         type_synonym_name = obsavestring (SYMBOL_NAME (sym),
+                                           strlen (SYMBOL_NAME (sym)));
+       }
+
+      type = read_type (&p);
+
+      if ((deftype == 'F' || deftype == 'f')
+         && TYPE_CODE (type) != TYPE_CODE_FUNC)
+       SYMBOL_TYPE (sym) = lookup_function_type (type);
+      else
+       SYMBOL_TYPE (sym) = type;
+    }
+
+  switch (deftype)
+    {
+    case 'C':
+      /* The name of a caught exception.  */
+      SYMBOL_CLASS (sym) = LOC_LABEL;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      SYMBOL_VALUE_ADDRESS (sym) = valu;
+      add_symbol_to_list (sym, &local_symbols);
+      break;
+
+    case 'f':
+      SYMBOL_CLASS (sym) = LOC_BLOCK;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &file_symbols);
+      break;
+
+    case 'F':
+      SYMBOL_CLASS (sym) = LOC_BLOCK;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &global_symbols);
+      break;
+
+    case 'G':
+      /* For a class G (global) symbol, it appears that the
+        value is not correct.  It is necessary to search for the
+        corresponding linker definition to find the value.
+        These definitions appear at the end of the namelist.  */
+      i = hashname (SYMBOL_NAME (sym));
+      SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+      global_sym_chain[i] = sym;
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &global_symbols);
+      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':
+      SYMBOL_CLASS (sym) = LOC_LOCAL;
+      SYMBOL_VALUE (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+      break;
+
+    case 'p':
+      /* Normally this is a parameter, a LOC_ARG.  On the i960, it
+        can also be a LOC_LOCAL_ARG depending on symbol type.  */
+#ifndef DBX_PARM_SYMBOL_CLASS
+#define        DBX_PARM_SYMBOL_CLASS(type)     LOC_ARG
+#endif
+      SYMBOL_CLASS (sym) = DBX_PARM_SYMBOL_CLASS (type);
+      SYMBOL_VALUE (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+
+      /* If it's gcc-compiled, if it says `short', believe it.  */
+      if (processing_gcc_compilation || BELIEVE_PCC_PROMOTION)
+       break;
+
+#if defined(BELIEVE_PCC_PROMOTION_TYPE)
+      /* This macro is defined on machines (e.g. sparc) where
+        we should believe the type of a PCC 'short' argument,
+        but shouldn't believe the address (the address is
+        the address of the corresponding int).  Note that
+        this is only different from the BELIEVE_PCC_PROMOTION
+        case on big-endian machines.
+
+        My guess is that this correction, as opposed to changing
+        the parameter to an 'int' (as done below, for PCC
+        on most machines), is the right thing to do
+        on all machines, but I don't want to risk breaking
+        something that already works.  On most PCC machines,
+        the sparc problem doesn't come up because the calling
+        function has to zero the top bytes (not knowing whether
+        the called function wants an int or a short), so there
+        is no practical difference between an int and a short
+        (except perhaps what happens when the GDB user types
+        "print short_arg = 0x10000;"). 
+
+        Hacked for SunOS 4.1 by gnu@cygnus.com.  In 4.1, the compiler
+        actually produces the correct address (we don't need to fix it
+        up).  I made this code adapt so that it will offset the symbol
+        if it was pointing at an int-aligned location and not
+        otherwise.  This way you can use the same gdb for 4.0.x and
+        4.1 systems.  */
+
+      if (0 == SYMBOL_VALUE (sym) % sizeof (int))
+       {
+         if (SYMBOL_TYPE (sym) == builtin_type_char
+             || SYMBOL_TYPE (sym) == builtin_type_unsigned_char)
+           SYMBOL_VALUE (sym) += 3;
+         else if (SYMBOL_TYPE (sym) == builtin_type_short
+             || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
+           SYMBOL_VALUE (sym) += 2;
+       }
+      break;
+
+#else /* no BELIEVE_PCC_PROMOTION_TYPE.  */
+
+      /* If PCC says a parameter is a short or a char,
+        it is really an int.  */
+      if (SYMBOL_TYPE (sym) == builtin_type_char
+         || SYMBOL_TYPE (sym) == builtin_type_short)
+       SYMBOL_TYPE (sym) = builtin_type_int;
+      else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
+              || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
+       SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
+      break;
+
+#endif /* no BELIEVE_PCC_PROMOTION_TYPE.  */
+
+    case 'P':
+      SYMBOL_CLASS (sym) = LOC_REGPARM;
+      SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+      break;
+
+    case 'r':
+      SYMBOL_CLASS (sym) = LOC_REGISTER;
+      SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+      break;
+
+    case 'S':
+      /* Static symbol at top level of file */
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+      SYMBOL_VALUE_ADDRESS (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &file_symbols);
+      break;
+
+    case 't':
+      SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+      SYMBOL_VALUE (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
+         && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
+       TYPE_NAME (SYMBOL_TYPE (sym)) =
+         obsavestring (SYMBOL_NAME (sym),
+                       strlen (SYMBOL_NAME (sym)));
+       /* C++ vagaries: we may have a type which is derived from
+        a base type which did not have its name defined when the
+        derived class was output.  We fill in the derived class's
+        base part member's name here in that case.  */
+       else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+                || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
+               && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
+        {
+          int i;
+          for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)) - 1; i >= 0; i--)
+            if (TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), i) == 0)
+              TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), i) =
+                type_name_no_tag (TYPE_BASECLASS (SYMBOL_TYPE (sym), i));
+        }
+
+      add_symbol_to_list (sym, &file_symbols);
+      break;
+
+    case 'T':
+      SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+      SYMBOL_VALUE (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+      if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
+         && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
+       TYPE_NAME (SYMBOL_TYPE (sym))
+         = obconcat ("",
+                     (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM
+                      ? "enum "
+                      : (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+                         ? "struct " : "union ")),
+                     SYMBOL_NAME (sym));
+      add_symbol_to_list (sym, &file_symbols);
+
+      if (synonym)
+       {
+         register struct symbol *typedef_sym
+           = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+         SYMBOL_NAME (typedef_sym) = SYMBOL_NAME (sym);
+         SYMBOL_TYPE (typedef_sym) = SYMBOL_TYPE (sym);
+
+         SYMBOL_CLASS (typedef_sym) = LOC_TYPEDEF;
+         SYMBOL_VALUE (typedef_sym) = valu;
+         SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
+         add_symbol_to_list (typedef_sym, &file_symbols);
+       }
+      break;
+
+    case 'V':
+      /* Static symbol of local scope */
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+      SYMBOL_VALUE_ADDRESS (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+      break;
+
+    case 'v':
+      /* Reference parameter */
+      SYMBOL_CLASS (sym) = LOC_REF_ARG;
+      SYMBOL_VALUE (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+      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.  */
+      SYMBOL_CLASS (sym) = LOC_LOCAL;
+      SYMBOL_VALUE (sym) = valu;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, &local_symbols);
+      break;
+
+    default:
+      error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum);
+    }
+  return sym;
+}
+\f
+/* What about types defined as forward references inside of a small lexical
+   scope?  */
+/* Add a type to the list of undefined types to be checked through
+   once this file has been read in.  */
+static void
+add_undefined_type (type)
+     struct type *type;
+{
+  if (undef_types_length == undef_types_allocated)
+    {
+      undef_types_allocated *= 2;
+      undef_types = (struct type **)
+       xrealloc (undef_types,
+                 undef_types_allocated * sizeof (struct type *));
+    }
+  undef_types[undef_types_length++] = type;
+}
+
+/* Add here something to go through each undefined type, see if it's
+   still undefined, and do a full lookup if so.  */
+static void
+cleanup_undefined_types ()
+{
+  struct type **type;
+
+  for (type = undef_types; type < undef_types + undef_types_length; type++)
+    {
+      /* Reasonable test to see if it's been defined since.  */
+      if (TYPE_NFIELDS (*type) == 0)
+       {
+         struct pending *ppt;
+         int i;
+         /* Name of the type, without "struct" or "union" */
+         char *typename = TYPE_NAME (*type);
+
+         if (!strncmp (typename, "struct ", 7))
+           typename += 7;
+         if (!strncmp (typename, "union ", 6))
+           typename += 6;
+
+         for (ppt = file_symbols; ppt; ppt = ppt->next)
+           for (i = 0; i < ppt->nsyms; i++)
+             {
+               struct symbol *sym = ppt->symbol[i];
+
+               if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                   && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+                   && (TYPE_CODE (SYMBOL_TYPE (sym)) ==
+                       TYPE_CODE (*type))
+                   && !strcmp (SYMBOL_NAME (sym), typename))
+                 bcopy (SYMBOL_TYPE (sym), *type, sizeof (struct type));
+             }
+       }
+      else
+       /* It has been defined; don't mark it as a stub.  */
+       TYPE_FLAGS (*type) &= ~TYPE_FLAG_STUB;
+    }
+  undef_types_length = 0;
+}
+
+/* Skip rest of this symbol and return an error type.
+
+   General notes on error recovery:  error_type always skips to the
+   end of the symbol (modulo cretinous dbx symbol name continuation).
+   Thus code like this:
+
+   if (*(*pp)++ != ';')
+     return error_type (pp);
+
+   is wrong because if *pp starts out pointing at '\0' (typically as the
+   result of an earlier error), it will be incremented to point to the
+   start of the next symbol, which might produce strange results, at least
+   if you run off the end of the string table.  Instead use
+
+   if (**pp != ';')
+     return error_type (pp);
+   ++*pp;
+
+   or
+
+   if (**pp != ';')
+     foo = error_type (pp);
+   else
+     ++*pp;
+
+   And in case it isn't obvious, the point of all this hair is so the compiler
+   can define new types and new syntaxes, and old versions of the
+   debugger will be able to read the new symbol tables.  */
+
+static struct type *
+error_type (pp)
+     char **pp;
+{
+  complain (&error_type_complaint, 0);
+  while (1)
+    {
+      /* Skip to end of symbol.  */
+      while (**pp != '\0')
+       (*pp)++;
+
+      /* Check for and handle cretinous dbx symbol name continuation!  */
+      if ((*pp)[-1] == '\\')
+       *pp = next_symbol_text ();
+      else
+       break;
+    }
+  return builtin_type_error;
+}
+\f
+/* Read a dbx type reference or definition;
+   return the type that is meant.
+   This can be just a number, in which case it references
+   a type already defined and placed in type_vector.
+   Or the number can be followed by an =, in which case
+   it means to define a new type according to the text that
+   follows the =.  */
+
+static
+struct type *
+read_type (pp)
+     register char **pp;
+{
+  register struct type *type = 0;
+  struct type *type1;
+  int typenums[2];
+  int xtypenums[2];
+
+  /* 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 ((**pp >= '0' && **pp <= '9')
+      || **pp == '(')
+    {
+      read_type_number (pp, typenums);
+      
+      /* Detect random reference to type not yet defined.
+        Allocate a type object but leave it zeroed.  */
+      if (**pp != '=')
+       return dbx_alloc_type (typenums);
+
+      *pp += 2;
+    }
+  else
+    {
+      /* '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;
+      *pp += 1;
+    }
+      
+  switch ((*pp)[-1])
+    {
+    case 'x':
+      {
+       enum type_code code;
+
+       /* Used to index through file_symbols.  */
+       struct pending *ppt;
+       int i;
+       
+       /* Name including "struct", etc.  */
+       char *type_name;
+       
+       /* Name without "struct", etc.  */
+       char *type_name_only;
+
+       {
+         char *prefix;
+         char *from, *to;
+         
+         /* Set the type code according to the following letter.  */
+         switch ((*pp)[0])
+           {
+           case 's':
+             code = TYPE_CODE_STRUCT;
+             prefix = "struct ";
+             break;
+           case 'u':
+             code = TYPE_CODE_UNION;
+             prefix = "union ";
+             break;
+           case 'e':
+             code = TYPE_CODE_ENUM;
+             prefix = "enum ";
+             break;
+           default:
+             return error_type (pp);
+           }
+         
+         to = type_name = (char *)
+           obstack_alloc (symbol_obstack,
+                          (strlen (prefix) +
+                           ((char *) strchr (*pp, ':') - (*pp)) + 1));
+       
+         /* Copy the prefix.  */
+         from = prefix;
+         while (*to++ = *from++)
+           ;
+         to--; 
+       
+         type_name_only = to;
+
+         /* Copy the name.  */
+         from = *pp + 1;
+         while ((*to++ = *from++) != ':')
+           ;
+         *--to = '\0';
+         
+         /* Set the pointer ahead of the name which we just read.  */
+         *pp = from;
+       
+#if 0
+         /* The following hack is clearly wrong, because it doesn't
+            check whether we are in a baseclass.  I tried to reproduce
+            the case that it is trying to fix, but I couldn't get
+            g++ to put out a cross reference to a basetype.  Perhaps
+            it doesn't do it anymore.  */
+         /* Note: for C++, the cross reference may be to a base type which
+            has not yet been seen.  In this case, we skip to the comma,
+            which will mark the end of the base class name.  (The ':'
+            at the end of the base class name will be skipped as well.)
+            But sometimes (ie. when the cross ref is the last thing on
+            the line) there will be no ','.  */
+         from = (char *) strchr (*pp, ',');
+         if (from)
+           *pp = from;
+#endif /* 0 */
+       }
+
+       /* Now check to see whether the type has already been declared.  */
+       /* This is necessary at least in the case where the
+          program says something like
+            struct foo bar[5];
+          The compiler puts out a cross-reference; we better find
+          set the length of the structure correctly so we can
+          set the length of the array.  */
+       for (ppt = file_symbols; ppt; ppt = ppt->next)
+         for (i = 0; i < ppt->nsyms; i++)
+           {
+             struct symbol *sym = ppt->symbol[i];
+
+             if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                 && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+                 && (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
+                 && !strcmp (SYMBOL_NAME (sym), type_name_only))
+               {
+                 obstack_free (symbol_obstack, type_name);
+                 type = SYMBOL_TYPE (sym);
+                 return type;
+               }
+           }
+       
+       /* Didn't find the type to which this refers, so we must
+          be dealing with a forward reference.  Allocate a type
+          structure for it, and keep track of it so we can
+          fill in the rest of the fields when we get the full
+          type.  */
+       type = dbx_alloc_type (typenums);
+       TYPE_CODE (type) = code;
+       TYPE_NAME (type) = type_name;
+
+       TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+
+       add_undefined_type (type);
+       return type;
+      }
+
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case '(':
+      (*pp)--;
+      read_type_number (pp, xtypenums);
+      type = *dbx_lookup_type (xtypenums);
+      if (type == 0)
+       type = builtin_type_void;
+      if (typenums[0] != -1)
+       *dbx_lookup_type (typenums) = type;
+      break;
+
+    case '*':
+      type1 = read_type (pp);
+      type = lookup_pointer_type (type1);
+      if (typenums[0] != -1)
+       *dbx_lookup_type (typenums) = type;
+      break;
+
+    case '@':
+      {
+       struct type *domain = read_type (pp);
+       struct type *memtype;
+
+       if (**pp != ',')
+         /* Invalid member type data format.  */
+         return error_type (pp);
+       ++*pp;
+
+       memtype = read_type (pp);
+       type = dbx_alloc_type (typenums);
+       smash_to_member_type (type, domain, memtype);
+      }
+      break;
+
+    case '#':
+      if ((*pp)[0] == '#')
+       {
+         /* We'll get the parameter types from the name.  */
+         struct type *return_type;
+
+         *pp += 1;
+         return_type = read_type (pp);
+         if (*(*pp)++ != ';')
+           complain (&invalid_member_complaint, symnum);
+         type = lookup_function_type (return_type);
+         if (typenums[0] != -1)
+           *dbx_lookup_type (typenums) = type;
+         TYPE_CODE (type) = TYPE_CODE_METHOD;
+         TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+       }
+      else
+       {
+         struct type *domain = read_type (pp);
+         struct type *return_type;
+         struct type **args;
+
+         if (*(*pp)++ != ',')
+           error ("invalid member type data format, at symtab pos %d.",
+                  symnum);
+
+         return_type = read_type (pp);
+         args = read_args (pp, ';');
+         type = dbx_alloc_type (typenums);
+         smash_to_method_type (type, domain, return_type, args);
+       }
+      break;
+
+    case '&':
+      type1 = read_type (pp);
+      type = lookup_reference_type (type1);
+      if (typenums[0] != -1)
+       *dbx_lookup_type (typenums) = type;
+      break;
+
+    case 'f':
+      type1 = read_type (pp);
+      type = lookup_function_type (type1);
+      if (typenums[0] != -1)
+       *dbx_lookup_type (typenums) = type;
+      break;
+
+    case 'r':
+      type = read_range_type (pp, typenums);
+      if (typenums[0] != -1)
+       *dbx_lookup_type (typenums) = type;
+      break;
+
+    case 'e':
+      type = dbx_alloc_type (typenums);
+      type = read_enum_type (pp, type);
+      *dbx_lookup_type (typenums) = type;
+      break;
+
+    case 's':
+      type = dbx_alloc_type (typenums);
+      TYPE_NAME (type) = type_synonym_name;
+      type_synonym_name = 0;
+      type = read_struct_type (pp, type);
+      break;
+
+    case 'u':
+      type = dbx_alloc_type (typenums);
+      TYPE_NAME (type) = type_synonym_name;
+      type_synonym_name = 0;
+      type = read_struct_type (pp, type);
+      TYPE_CODE (type) = TYPE_CODE_UNION;
+      break;
+
+    case 'a':
+      if (**pp != 'r')
+       return error_type (pp);
+      ++*pp;
+      
+      type = dbx_alloc_type (typenums);
+      type = read_array_type (pp, type);
+      break;
+
+    default:
+      return error_type (pp);
+    }
+
+  if (type == 0)
+    abort ();
+
+#if 0
+  /* If this is an overriding temporary alteration for a header file's
+     contents, and this type number is unknown in the global definition,
+     put this type into the global definition at this type number.  */
+  if (header_file_prev_index >= 0)
+    {
+      register struct type **tp
+        = explicit_lookup_type (header_file_prev_index, typenums[1]);
+      if (*tp == 0)
+       *tp = type;
+    }
+#endif
+  return type;
+}
+\f
+#if 0
+/* This would be a good idea, but it doesn't really work.  The problem
+   is that in order to get the virtual context for a particular type,
+   you need to know the virtual info from all of its basetypes,
+   and you need to have processed its methods.  Since GDB reads
+   symbols on a file-by-file basis, this means processing the symbols
+   of all the files that are needed for each baseclass, which
+   means potentially reading in all the debugging info just to fill
+   in information we may never need.  */
+
+/* This page contains subroutines of read_type.  */
+
+/* FOR_TYPE is a struct type defining a virtual function NAME with type
+   FN_TYPE.  The `virtual context' for this virtual function is the
+   first base class of FOR_TYPE in which NAME is defined with signature
+   matching FN_TYPE.  OFFSET serves as a hash on matches here.
+
+   TYPE is the current type in which we are searching.  */
+
+static struct type *
+virtual_context (for_type, type, name, fn_type, offset)
+     struct type *for_type, *type;
+     char *name;
+     struct type *fn_type;
+     int offset;
+{
+  struct type *basetype = 0;
+  int i;
+
+  if (for_type != type)
+    {
+      /* Check the methods of TYPE.  */
+      /* Need to do a check_stub_type here, but that breaks
+        things because we can get infinite regress.  */
+      for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+       if (!strcmp (TYPE_FN_FIELDLIST_NAME (type, i), name))
+         break;
+      if (i >= 0)
+       {
+         int j = TYPE_FN_FIELDLIST_LENGTH (type, i);
+         struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+
+         while (--j >= 0)
+           if (TYPE_FN_FIELD_VOFFSET (f, j) == offset-1)
+             return TYPE_FN_FIELD_FCONTEXT (f, j);
+       }
+    }
+  for (i = TYPE_N_BASECLASSES (type); i > 0; i--)
+    {
+      basetype = virtual_context (for_type, TYPE_BASECLASS (type, i), name,
+                                 fn_type, offset);
+      if (basetype != for_type)
+       return basetype;
+    }
+  return for_type;
+}
+#endif
+
+/* Read the description of a structure (or union type)
+   and return an object describing the type.  */
+
+static struct type *
+read_struct_type (pp, type)
+     char **pp;
+     register struct type *type;
+{
+  /* Total number of methods defined in this class.
+     If the class defines two `f' methods, and one `g' method,
+     then this will have the value 3.  */
+  int total_length = 0;
+
+  struct nextfield
+    {
+      struct nextfield *next;
+      int visibility;                  /* 0=public, 1=protected, 2=public */
+      struct field field;
+    };
+
+  struct next_fnfield
+    {
+      struct next_fnfield *next;
+      int visibility;                  /* 0=public, 1=protected, 2=public */
+      struct fn_field fn_field;
+    };
+
+  struct next_fnfieldlist
+    {
+      struct next_fnfieldlist *next;
+      struct fn_fieldlist fn_fieldlist;
+    };
+
+  register struct nextfield *list = 0;
+  struct nextfield *new;
+  register char *p;
+  int nfields = 0;
+  register int n;
+
+  register struct next_fnfieldlist *mainlist = 0;
+  int nfn_fields = 0;
+
+  if (TYPE_MAIN_VARIANT (type) == 0)
+    {
+      TYPE_MAIN_VARIANT (type) = type;
+    }
+
+  TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+  /* First comes the total size in bytes.  */
+
+  TYPE_LENGTH (type) = read_number (pp, 0);
+
+  /* C++: Now, if the class is a derived class, then the next character
+     will be a '!', followed by the number of base classes derived from.
+     Each element in the list contains visibility information,
+     the offset of this base class in the derived structure,
+     and then the base type. */
+  if (**pp == '!')
+    {
+      int i, n_baseclasses, offset;
+      struct type *baseclass;
+      int via_public;
+
+      /* Nonzero if it is a virtual baseclass, i.e.,
+
+        struct A{};
+        struct B{};
+        struct C : public B, public virtual A {};
+
+        B is a baseclass of C; A is a virtual baseclass for C.  This is a C++
+        2.0 language feature.  */
+      int via_virtual;
+
+      *pp += 1;
+
+      n_baseclasses = read_number (pp, ',');
+      TYPE_FIELD_VIRTUAL_BITS (type) =
+         (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (n_baseclasses));
+      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), n_baseclasses);
+
+      for (i = 0; i < n_baseclasses; i++)
+       {
+         if (**pp == '\\')
+           *pp = next_symbol_text ();
+
+         switch (**pp)
+           {
+           case '0':
+             via_virtual = 0;
+             break;
+           case '1':
+             via_virtual = 1;
+             break;
+           default:
+             /* Bad visibility format.  */
+             return error_type (pp);
+           }
+         ++*pp;
+
+         switch (**pp)
+           {
+           case '0':
+             via_public = 0;
+             break;
+           case '2':
+             via_public = 2;
+             break;
+           default:
+             /* Bad visibility format.  */
+             return error_type (pp);
+           }
+         if (via_virtual) 
+           SET_TYPE_FIELD_VIRTUAL (type, i);
+         ++*pp;
+
+         /* Offset of the portion of the object corresponding to
+            this baseclass.  Always zero in the absence of
+            multiple inheritance.  */
+         offset = read_number (pp, ',');
+         baseclass = read_type (pp);
+         *pp += 1;             /* skip trailing ';' */
+
+#if 0
+/* One's understanding improves, grasshopper... */
+         if (offset != 0)
+           {
+             static int error_printed = 0;
+
+             if (!error_printed)
+               {
+                 fprintf (stderr, 
+"\nWarning:  GDB has limited understanding of multiple inheritance...");
+                 if (!info_verbose)
+                   fprintf(stderr, "\n");
+                 error_printed = 1;
+               }
+           }
+#endif
+
+         /* Make this baseclass visible for structure-printing purposes.  */
+         new = (struct nextfield *) alloca (sizeof (struct nextfield));
+         new->next = list;
+         list = new;
+         list->visibility = via_public;
+         list->field.type = baseclass;
+         list->field.name = type_name_no_tag (baseclass);
+         list->field.bitpos = offset;
+         list->field.bitsize = 0;      /* this should be an unpacked field! */
+         nfields++;
+       }
+      TYPE_N_BASECLASSES (type) = n_baseclasses;
+    }
+
+  /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one.
+     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 `?' is a placeholder for one of '/2' (public visibility),
+     '/1' (protected visibility), '/0' (private visibility), or nothing
+     (C style symbol table, public visibility).  */
+
+  /* We better set p right now, in case there are no fields at all...    */
+  p = *pp;
+
+  while (**pp != ';')
+    {
+      /* Check for and handle cretinous dbx symbol name continuation!  */
+      if (**pp == '\\') *pp = next_symbol_text ();
+
+      /* Get space to record the next field's data.  */
+      new = (struct nextfield *) alloca (sizeof (struct nextfield));
+      new->next = list;
+      list = new;
+
+      /* Get the field name.  */
+      p = *pp;
+      if (*p == CPLUS_MARKER)
+       {
+         /* Special GNU C++ name.  */
+         if (*++p == 'v')
+           {
+             char *prefix, *name;      /* FIXME: NAME never set! */
+             struct type *context;
+
+             switch (*++p)
+               {
+               case 'f':
+                 prefix = vptr_name;
+                 break;
+               case 'b':
+                 prefix = vb_name;
+                 break;
+               default:
+                 error ("invalid abbreviation at symtab pos %d.", symnum);
+               }
+             *pp = p + 1;
+             context = read_type (pp);
+             if (type_name_no_tag (context) == 0)
+               {
+                 if (name == 0)
+                   error ("type name unknown at symtab pos %d.", symnum);
+                 TYPE_NAME (context) = obsavestring (name, p - name - 1);
+               }
+             list->field.name = obconcat (prefix, type_name_no_tag (context), "");
+             p = ++(*pp);
+             if (p[-1] != ':')
+               error ("invalid abbreviation at symtab pos %d.", symnum);
+             list->field.type = read_type (pp);
+             (*pp)++;                  /* Skip the comma.  */
+             list->field.bitpos = read_number (pp, ';');
+             /* This field is unpacked.  */
+             list->field.bitsize = 0;
+           }
+         else
+           error ("invalid abbreviation at symtab pos %d.", symnum);
+
+         nfields++;
+         continue;
+       }
+
+      while (*p != ':') p++;
+      list->field.name = obsavestring (*pp, p - *pp);
+
+      /* C++: Check to see if we have hit the methods yet.  */
+      if (p[1] == ':')
+       break;
+
+      *pp = p + 1;
+
+      /* This means we have a visibility for a field coming. */
+      if (**pp == '/')
+       {
+         switch (*++*pp)
+           {
+           case '0':
+             list->visibility = 0;     /* private */
+             *pp += 1;
+             break;
+
+           case '1':
+             list->visibility = 1;     /* protected */
+             *pp += 1;
+             break;
+
+           case '2':
+             list->visibility = 2;     /* public */
+             *pp += 1;
+             break;
+           }
+       }
+       else /* normal dbx-style format.  */
+       list->visibility = 2;           /* public */
+
+      list->field.type = read_type (pp);
+      if (**pp == ':')
+       {
+         /* Static class member.  */
+         list->field.bitpos = (long)-1;
+         p = ++(*pp);
+         while (*p != ';') p++;
+         list->field.bitsize = (long) savestring (*pp, p - *pp);
+         *pp = p + 1;
+         nfields++;
+         continue;
+       }
+       else if (**pp != ',')
+        /* Bad structure-type format.  */
+        return error_type (pp);
+
+      (*pp)++;                 /* Skip the comma.  */
+      list->field.bitpos = read_number (pp, ',');
+      list->field.bitsize = read_number (pp, ';');
+
+#if 0
+      /* FIXME tiemann: what is the story here?  What does the compiler
+       really do?  Also, patch gdb.texinfo for this case; I document
+       it as a possible problem there.  Search for "DBX-style".  */
+
+      /* This is wrong because this is identical to the symbols
+        produced for GCC 0-size arrays.  For example:
+         typedef union {
+          int num;
+          char str[0];
+        } foo;
+        The code which dumped core in such circumstances should be
+        fixed not to dump core.  */
+
+      /* g++ -g0 can put out bitpos & bitsize zero for a static
+        field.  This does not give us any way of getting its
+        class, so we can't know its name.  But we can just
+        ignore the field so we don't dump core and other nasty
+        stuff.  */
+      if (list->field.bitpos == 0
+         && list->field.bitsize == 0)
+       {
+         complain (&dbx_class_complaint, 0);
+         /* Ignore this field.  */
+         list = list->next;
+       }
+      else
+#endif /* 0 */
+       {
+         /* Detect an unpacked field and mark it as such.
+            dbx gives a bit size for all fields.
+            Note that forward refs cannot be packed,
+            and treat enums as if they had the width of ints.  */
+         if (TYPE_CODE (list->field.type) != TYPE_CODE_INT
+             && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM)
+           list->field.bitsize = 0;
+         if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type)
+              || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM
+                  && (list->field.bitsize
+                      == 8 * TYPE_LENGTH (builtin_type_int))
+                  )
+              )
+             &&
+             list->field.bitpos % 8 == 0)
+           list->field.bitsize = 0;
+         nfields++;
+       }
+    }
+
+  if (p[1] == ':')
+    /* chill the list of fields: the last entry (at the head)
+       is a partially constructed entry which we now scrub.  */
+    list = list->next;
+
+  /* Now create the vector of fields, and record how big it is.
+     We need this info to record proper virtual function table information
+     for this class's virtual functions.  */
+
+  TYPE_NFIELDS (type) = nfields;
+  TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack,
+                                              sizeof (struct field) * nfields);
+
+  TYPE_FIELD_PRIVATE_BITS (type) =
+    (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (nfields));
+  B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+
+  TYPE_FIELD_PROTECTED_BITS (type) =
+    (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (nfields));
+  B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+
+  /* Copy the saved-up fields into the field vector.  */
+
+  for (n = nfields; list; list = list->next)
+    {
+      n -= 1;
+      TYPE_FIELD (type, n) = list->field;
+      if (list->visibility == 0)
+       SET_TYPE_FIELD_PRIVATE (type, n);
+      else if (list->visibility == 1)
+       SET_TYPE_FIELD_PROTECTED (type, n);
+    }
+
+  /* Now come the method fields, as NAME::methods
+     where each method is of the form TYPENUM,ARGS,...:PHYSNAME;
+     At the end, we see a semicolon instead of a field.
+
+     For the case of overloaded operators, the format is
+     OPERATOR::*.methods, where OPERATOR is the string "operator",
+     `*' holds the place for an operator name (such as `+=')
+     and `.' marks the end of the operator name.  */
+  if (p[1] == ':')
+    {
+      /* Now, read in the methods.  To simplify matters, we
+        "unread" the name that has been read, so that we can
+        start from the top.  */
+
+      /* For each list of method lists... */
+      do
+       {
+         int i;
+         struct next_fnfield *sublist = 0;
+         int length = 0;
+         struct next_fnfieldlist *new_mainlist =
+           (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist));
+         char *main_fn_name;
+
+         p = *pp;
+
+         /* read in the name.  */
+         while (*p != ':') p++;
+         if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == CPLUS_MARKER)
+           {
+             /* This lets the user type "break operator+".
+                We could just put in "+" as the name, but that wouldn't
+                work for "*".  */
+             static char opname[32] = "operator";
+             char *o = opname + 8;
+
+             /* Skip past '::'.  */
+             p += 2;
+             while (*p != '.')
+               *o++ = *p++;
+            main_fn_name = savestring (opname, o - opname);
+             /* Skip past '.'  */
+             *pp = p + 1;
+           }
+         else
+           {
+             i = 0;
+             main_fn_name = savestring (*pp, p - *pp);
+             /* Skip past '::'.  */
+             *pp = p + 2;
+           }
+         new_mainlist->fn_fieldlist.name = main_fn_name;
+
+         do
+           {
+             struct next_fnfield *new_sublist =
+               (struct next_fnfield *)alloca (sizeof (struct next_fnfield));
+
+             /* Check for and handle cretinous dbx symbol name continuation!  */
+             if (**pp == '\\') *pp = next_symbol_text ();
+
+             new_sublist->fn_field.type = read_type (pp);
+             if (**pp != ':')
+               /* Invalid symtab info for method.  */
+               return error_type (pp);
+
+             *pp += 1;
+             p = *pp;
+             while (*p != ';') p++;
+             /* If this is just a stub, then we don't have the
+                real name here.  */
+             new_sublist->fn_field.physname = savestring (*pp, p - *pp);
+             *pp = p + 1;
+             new_sublist->visibility = *(*pp)++ - '0';
+             if (**pp == '\\') *pp = next_symbol_text ();
+             /* FIXME: tiemann needs to add const/volatile info
+                to the methods.  For now, just skip the char.
+                In future, here's what we need to implement:
+
+                A for normal functions.
+                B for `const' member functions.
+                C for `volatile' member functions.
+                D for `const volatile' member functions.  */
+             if (**pp == 'A' || **pp == 'B' || **pp == 'C' || **pp == 'D')
+               (*pp)++;
+             else
+               complain(&const_vol_complaint, **pp);
+
+             switch (*(*pp)++)
+               {
+               case '*':
+                 /* virtual member function, followed by index.  */
+                 /* The sign bit is set to distinguish pointers-to-methods
+                    from virtual function indicies.  Since the array is
+                    in words, the quantity must be shifted left by 1
+                    on 16 bit machine, and by 2 on 32 bit machine, forcing
+                    the sign bit out, and usable as a valid index into
+                    the array.  Remove the sign bit here.  */
+                 new_sublist->fn_field.voffset =
+                     (0x7fffffff & read_number (pp, ';')) + 1;
+
+                 /* Figure out from whence this virtual function came.
+                    It may belong to virtual function table of
+                    one of its baseclasses.  */
+                 new_sublist->fn_field.fcontext = read_type (pp);
+                 if (**pp != ';')
+                   error_type (pp);
+                 else
+                   ++*pp;
+                 break;
+
+               case '?':
+                 /* static member function.  */
+                 new_sublist->fn_field.voffset = VOFFSET_STATIC;
+                 break;
+               default:
+                 /* **pp == '.'.  */
+                 /* normal member function.  */
+                 new_sublist->fn_field.voffset = 0;
+                 break;
+               }
+
+             new_sublist->next = sublist;
+             sublist = new_sublist;
+             length++;
+           }
+         while (**pp != ';' && *pp != '\0');
+
+         *pp += 1;
+
+         new_mainlist->fn_fieldlist.fn_fields =
+           (struct fn_field *) obstack_alloc (symbol_obstack,
+                                              sizeof (struct fn_field) * length);
+         TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) =
+           (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (length));
+         B_CLRALL (TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist), length);
+
+         TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) =
+           (B_TYPE *) obstack_alloc (symbol_obstack, B_BYTES (length));
+         B_CLRALL (TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist), length);
+
+         for (i = length; (i--, sublist); sublist = sublist->next)
+           {
+             new_mainlist->fn_fieldlist.fn_fields[i] = sublist->fn_field;
+             if (sublist->visibility == 0)
+               B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i);
+             else if (sublist->visibility == 1)
+               B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i);
+           }
+
+         new_mainlist->fn_fieldlist.length = length;
+         new_mainlist->next = mainlist;
+         mainlist = new_mainlist;
+         nfn_fields++;
+         total_length += length;
+       }
+      while (**pp != ';');
+    }
+
+  *pp += 1;
+
+  TYPE_FN_FIELDLISTS (type) =
+    (struct fn_fieldlist *) obstack_alloc (symbol_obstack,
+                                  sizeof (struct fn_fieldlist) * nfn_fields);
+
+  TYPE_NFN_FIELDS (type) = nfn_fields;
+  TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+
+  {
+    int i;
+    for (i = 0; i < TYPE_N_BASECLASSES (type); ++i)
+      TYPE_NFN_FIELDS_TOTAL (type) +=
+       TYPE_NFN_FIELDS_TOTAL (TYPE_BASECLASS (type, i));
+  }
+
+  for (n = nfn_fields; mainlist; mainlist = mainlist->next)
+    TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist;
+
+  if (**pp == '~')
+    {
+      *pp += 1;
+
+      if (**pp == '=')
+       {
+         TYPE_FLAGS (type)
+           |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR;
+         *pp += 1;
+       }
+      else if (**pp == '+')
+       {
+         TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR;
+         *pp += 1;
+       }
+      else if (**pp == '-')
+       {
+         TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR;
+         *pp += 1;
+       }
+
+      /* Read either a '%' or the final ';'.  */
+      if (*(*pp)++ == '%')
+       {
+         /* Now we must record the virtual function table pointer's
+            field information.  */
+
+         struct type *t;
+         int i;
+
+         t = read_type (pp);
+         p = (*pp)++;
+         while (*p != '\0' && *p != ';')
+           p++;
+         if (*p == '\0')
+           /* Premature end of symbol.  */
+           return error_type (pp);
+         
+         TYPE_VPTR_BASETYPE (type) = t;
+         if (type == t)
+           {
+             if (TYPE_FIELD_NAME (t, TYPE_N_BASECLASSES (t)) == 0)
+               TYPE_VPTR_FIELDNO (type) = i = TYPE_N_BASECLASSES (t);
+             else for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); --i)
+               if (! strncmp (TYPE_FIELD_NAME (t, i), vptr_name, 
+                       sizeof (vptr_name) -1))
+                 {
+                   TYPE_VPTR_FIELDNO (type) = i;
+                   break;
+                 }
+             if (i < 0)
+               /* Virtual function table field not found.  */
+               return error_type (pp);
+           }
+         else
+           TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
+         *pp = p + 1;
+       }
+      else
+       {
+         TYPE_VPTR_BASETYPE (type) = 0;
+         TYPE_VPTR_FIELDNO (type) = -1;
+       }
+    }
+  else
+    {
+      TYPE_VPTR_BASETYPE (type) = 0;
+      TYPE_VPTR_FIELDNO (type) = -1;
+    }
+
+  return type;
+}
+
+/* Read a definition of an array type,
+   and create and return a suitable type object.
+   Also creates a range type which represents the bounds of that
+   array.  */
+static struct type *
+read_array_type (pp, type)
+     register char **pp;
+     register struct type *type;
+{
+  struct type *index_type, *element_type, *range_type;
+  int lower, upper;
+  int adjustable = 0;
+
+  /* Format of an array type:
+     "ar<index type>;lower;upper;<array_contents_type>".  Put code in
+     to handle this.
+
+     Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+     for these, produce a type like float[][].  */
+
+  index_type = read_type (pp);
+  if (**pp != ';')
+    /* Improper format of array type decl.  */
+    return error_type (pp);
+  ++*pp;
+
+  if (!(**pp >= '0' && **pp <= '9'))
+    {
+      *pp += 1;
+      adjustable = 1;
+    }
+  lower = read_number (pp, ';');
+
+  if (!(**pp >= '0' && **pp <= '9'))
+    {
+      *pp += 1;
+      adjustable = 1;
+    }
+  upper = read_number (pp, ';');
+  
+  element_type = read_type (pp);
+
+  if (adjustable)
+    {
+      lower = 0;
+      upper = -1;
+    }
+
+  {
+    /* Create range type.  */
+    range_type = (struct type *) obstack_alloc (symbol_obstack,
+                                               sizeof (struct type));
+    TYPE_CODE (range_type) = TYPE_CODE_RANGE;
+    TYPE_TARGET_TYPE (range_type) = index_type;
+
+    /* This should never be needed.  */
+    TYPE_LENGTH (range_type) = sizeof (int);
+
+    TYPE_NFIELDS (range_type) = 2;
+    TYPE_FIELDS (range_type) =
+      (struct field *) obstack_alloc (symbol_obstack,
+                                     2 * sizeof (struct field));
+    TYPE_FIELD_BITPOS (range_type, 0) = lower;
+    TYPE_FIELD_BITPOS (range_type, 1) = upper;
+  }
+
+  TYPE_CODE (type) = TYPE_CODE_ARRAY;
+  TYPE_TARGET_TYPE (type) = element_type;
+  TYPE_LENGTH (type) = (upper - lower + 1) * TYPE_LENGTH (element_type);
+  TYPE_NFIELDS (type) = 1;
+  TYPE_FIELDS (type) =
+    (struct field *) obstack_alloc (symbol_obstack,
+                                   sizeof (struct field));
+  TYPE_FIELD_TYPE (type, 0) = range_type;
+
+  return type;
+}
+
+
+/* Read a definition of an enumeration type,
+   and create and return a suitable type object.
+   Also defines the symbols that represent the values of the type.  */
+
+static struct type *
+read_enum_type (pp, type)
+     register char **pp;
+     register struct type *type;
+{
+  register char *p;
+  char *name;
+  register long n;
+  register struct symbol *sym;
+  int nsyms = 0;
+  struct pending **symlist;
+  struct pending *osyms, *syms;
+  int o_nsyms;
+
+  if (within_function)
+    symlist = &local_symbols;
+  else
+    symlist = &file_symbols;
+  osyms = *symlist;
+  o_nsyms = osyms ? osyms->nsyms : 0;
+
+  /* Read the value-names and their values.
+     The input syntax is NAME:VALUE,NAME:VALUE, and so on.
+     A semicolon or comman instead of a NAME means the end.  */
+  while (**pp && **pp != ';' && **pp != ',')
+    {
+      /* Check for and handle cretinous dbx symbol name continuation!  */
+      if (**pp == '\\')        *pp = next_symbol_text ();
+
+      p = *pp;
+      while (*p != ':') p++;
+      name = obsavestring (*pp, p - *pp);
+      *pp = p + 1;
+      n = read_number (pp, ',');
+
+      sym = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+      bzero (sym, sizeof (struct symbol));
+      SYMBOL_NAME (sym) = name;
+      SYMBOL_CLASS (sym) = LOC_CONST;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      SYMBOL_VALUE (sym) = n;
+      add_symbol_to_list (sym, symlist);
+      nsyms++;
+    }
+
+  if (**pp == ';')
+    (*pp)++;                   /* Skip the semicolon.  */
+
+  /* Now fill in the fields of the type-structure.  */
+
+  TYPE_LENGTH (type) = sizeof (int);
+  TYPE_CODE (type) = TYPE_CODE_ENUM;
+  TYPE_NFIELDS (type) = nsyms;
+  TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms);
+
+  /* Find the symbols for the values and put them into the type.
+     The symbols can be found in the symlist that we put them on
+     to cause them to be defined.  osyms contains the old value
+     of that symlist; everything up to there was defined by us.  */
+  /* Note that we preserve the order of the enum constants, so
+     that in something like "enum {FOO, LAST_THING=FOO}" we print
+     FOO, not LAST_THING.  */
+
+  for (syms = *symlist, n = 0; syms; syms = syms->next)
+    {
+      int j = 0;
+      if (syms == osyms)
+       j = o_nsyms;
+      for (; j < syms->nsyms; j++,n++)
+       {
+         struct symbol *sym = syms->symbol[j];
+         SYMBOL_TYPE (sym) = type;
+         TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (sym);
+         TYPE_FIELD_VALUE (type, n) = 0;
+         TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (sym);
+         TYPE_FIELD_BITSIZE (type, n) = 0;
+       }
+      if (syms == osyms)
+       break;
+    }
+
+  return type;
+}
+
+/* Read a number from the string pointed to by *PP.
+   The value of *PP is advanced over the number.
+   If END is nonzero, the character that ends the
+   number must match END, or an error happens;
+   and that character is skipped if it does match.
+   If END is zero, *PP is left pointing to that character.
+
+   If the number fits in a long, set *VALUE and set *BITS to 0.
+   If not, set *BITS to be the number of bits in the number.
+
+   If encounter garbage, set *BITS to -1.  */
+
+static void
+read_huge_number (pp, end, valu, bits)
+     char **pp;
+     int end;
+     long *valu;
+     int *bits;
+{
+  char *p = *pp;
+  int sign = 1;
+  long n = 0;
+  int radix = 10;
+  char overflow = 0;
+  int nbits = 0;
+  int c;
+  
+  if (*p == '-')
+    {
+      sign = -1;
+      p++;
+    }
+
+  /* Leading zero means octal.  GCC uses this to output values larger
+     than an int (because that would be hard in decimal).  */
+  if (*p == '0')
+    {
+      radix = 8;
+      p++;
+    }
+
+  while ((c = *p++) >= '0' && c <= ('0' + radix))
+    {
+      if (n <= LONG_MAX / radix)
+       {
+         n *= radix;
+         n += c - '0';         /* FIXME this overflows anyway */
+       }
+      else
+       overflow = 1;
+      
+      /* This depends on large values being output in octal, which is
+        what GCC does. */
+      if (radix == 8)
+       {
+         if (nbits == 0)
+           {
+             if (c == '0')
+               /* Ignore leading zeroes.  */
+               ;
+             else if (c == '1')
+               nbits = 1;
+             else if (c == '2' || c == '3')
+               nbits = 2;
+             else
+               nbits = 3;
+           }
+         else
+           nbits += 3;
+       }
+    }
+  if (end)
+    {
+      if (c && c != end)
+       {
+         if (bits != NULL)
+           *bits = -1;
+         return;
+       }
+    }
+  else
+    --p;
+
+  *pp = p;
+  if (overflow)
+    {
+      if (nbits == 0)
+       {
+         /* Large decimal constants are an error (because it is hard to
+            count how many bits are in them).  */
+         if (bits != NULL)
+           *bits = -1;
+         return;
+       }
+      
+      /* -0x7f is the same as 0x80.  So deal with it by adding one to
+        the number of bits.  */
+      if (sign == -1)
+       ++nbits;
+      if (bits)
+       *bits = nbits;
+    }
+  else
+    {
+      if (valu)
+       *valu = n * sign;
+      if (bits)
+       *bits = 0;
+    }
+}
+
+#define        MAX_OF_TYPE(t)  ((1 << (sizeof (t)*8 - 1)) - 1)
+#define MIN_OF_TYPE(t) (-(1 << (sizeof (t)*8 - 1)))
+
+static struct type *
+read_range_type (pp, typenums)
+     char **pp;
+     int typenums[2];
+{
+  int rangenums[2];
+  long n2, n3;
+  int n2bits, n3bits;
+  int self_subrange;
+  struct type *result_type;
+
+  /* First comes a type we are a subrange of.
+     In C it is usually 0, 1 or the type being defined.  */
+  read_type_number (pp, rangenums);
+  self_subrange = (rangenums[0] == typenums[0] &&
+                  rangenums[1] == typenums[1]);
+
+  /* A semicolon should now follow; skip it.  */
+  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.  */
+  read_huge_number (pp, ';', &n2, &n2bits);
+  read_huge_number (pp, ';', &n3, &n3bits);
+
+  if (n2bits == -1 || n3bits == -1)
+    return error_type (pp);
+  
+  /* If limits are huge, must be large integral type.  */
+  if (n2bits != 0 || n3bits != 0)
+    {
+      char got_signed = 0;
+      char got_unsigned = 0;
+      /* Number of bits in the type.  */
+      int nbits;
+
+      /* Range from 0 to <large number> is an unsigned large integral type.  */
+      if ((n2bits == 0 && n2 == 0) && n3bits != 0)
+       {
+         got_unsigned = 1;
+         nbits = n3bits;
+       }
+      /* Range from <large number> to <large number>-1 is a large signed
+        integral type.  */
+      else if (n2bits != 0 && n3bits != 0 && n2bits == n3bits + 1)
+       {
+         got_signed = 1;
+         nbits = n2bits;
+       }
+
+      if (got_signed || got_unsigned)
+       {
+         result_type = (struct type *) obstack_alloc (symbol_obstack,
+                                                      sizeof (struct type));
+         bzero (result_type, sizeof (struct type));
+         TYPE_LENGTH (result_type) = nbits / TARGET_CHAR_BIT;
+         TYPE_MAIN_VARIANT (result_type) = result_type;
+         TYPE_CODE (result_type) = TYPE_CODE_INT;
+         if (got_unsigned)
+           TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
+         return result_type;
+       }
+      else
+       return error_type (pp);
+    }
+
+  /* A type defined as a subrange of itself, with bounds both 0, is void.  */
+  if (self_subrange && n2 == 0 && n3 == 0)
+    return builtin_type_void;
+
+  /* If n3 is zero and n2 is not, we want a floating type,
+     and n2 is the width in bytes.
+
+     Fortran programs appear to use this for complex types also,
+     and they give no way to distinguish between double and single-complex!
+     We don't have complex types, so we would lose on all fortran files!
+     So return type `double' for all of those.  It won't work right
+     for the complex values, but at least it makes the file loadable.  */
+
+  if (n3 == 0 && n2 > 0)
+    {
+      if (n2 == sizeof (float))
+       return builtin_type_float;
+      return builtin_type_double;
+    }
+
+  /* If the upper bound is -1, it must really be an unsigned int.  */
+
+  else if (n2 == 0 && n3 == -1)
+    {
+      if (sizeof (int) == sizeof (long))
+       return builtin_type_unsigned_int;
+      else
+       return builtin_type_unsigned_long;
+    }
+
+  /* Special case: char is defined (Who knows why) as a subrange of
+     itself with range 0-127.  */
+  else if (self_subrange && n2 == 0 && n3 == 127)
+    return builtin_type_char;
+
+  /* Assumptions made here: Subrange of self is equivalent to subrange
+     of int.  */
+  else if (n2 == 0
+          && (self_subrange ||
+              *dbx_lookup_type (rangenums) == builtin_type_int))
+    {
+      /* an unsigned type */
+#ifdef LONG_LONG
+      if (n3 == - sizeof (long long))
+       return builtin_type_unsigned_long_long;
+#endif
+      if (n3 == (unsigned int)~0L)
+       return builtin_type_unsigned_int;
+      if (n3 == (unsigned long)~0L)
+       return builtin_type_unsigned_long;
+      if (n3 == (unsigned short)~0L)
+       return builtin_type_unsigned_short;
+      if (n3 == (unsigned char)~0L)
+       return builtin_type_unsigned_char;
+    }
+#ifdef LONG_LONG
+  else if (n3 == 0 && n2 == -sizeof (long long))
+    return builtin_type_long_long;
+#endif  
+  else if (n2 == -n3 -1)
+    {
+      /* a signed type */
+      if (n3 == (1 << (8 * sizeof (int) - 1)) - 1)
+       return builtin_type_int;
+      if (n3 == (1 << (8 * sizeof (long) - 1)) - 1)
+        return builtin_type_long;
+      if (n3 == (1 << (8 * sizeof (short) - 1)) - 1)
+       return builtin_type_short;
+      if (n3 == (1 << (8 * sizeof (char) - 1)) - 1)
+       return builtin_type_char;
+    }
+
+  /* We have a real range type on our hands.  Allocate space and
+     return a real pointer.  */
+
+  /* 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)
+    return error_type (pp);
+
+  result_type = (struct type *) obstack_alloc (symbol_obstack,
+                                              sizeof (struct type));
+  bzero (result_type, sizeof (struct type));
+
+  TYPE_TARGET_TYPE (result_type) = (self_subrange ?
+                                   builtin_type_int :
+                                   *dbx_lookup_type(rangenums));
+
+  /* We have to figure out how many bytes it takes to hold this
+     range type.  I'm going to assume that anything that is pushing
+     the bounds of a long was taken care of above.  */
+  if (n2 >= MIN_OF_TYPE(char) && n3 <= MAX_OF_TYPE(char))
+    TYPE_LENGTH (result_type) = 1;
+  else if (n2 >= MIN_OF_TYPE(short) && n3 <= MAX_OF_TYPE(short))
+    TYPE_LENGTH (result_type) = sizeof (short);
+  else if (n2 >= MIN_OF_TYPE(int) && n3 <= MAX_OF_TYPE(int))
+    TYPE_LENGTH (result_type) = sizeof (int);
+  else if (n2 >= MIN_OF_TYPE(long) && n3 <= MAX_OF_TYPE(long))
+    TYPE_LENGTH (result_type) = sizeof (long);
+  else
+    /* Ranged type doesn't fit within known sizes.  */
+    return error_type (pp);
+
+  TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type));
+  TYPE_CODE (result_type) = TYPE_CODE_RANGE;
+  TYPE_NFIELDS (result_type) = 2;
+  TYPE_FIELDS (result_type) =
+    (struct field *) obstack_alloc (symbol_obstack,
+                                   2 * sizeof (struct field));
+  bzero (TYPE_FIELDS (result_type), 2 * sizeof (struct field));
+  TYPE_FIELD_BITPOS (result_type, 0) = n2;
+  TYPE_FIELD_BITPOS (result_type, 1) = n3;
+
+  return result_type;
+}
+
+/* Read a number from the string pointed to by *PP.
+   The value of *PP is advanced over the number.
+   If END is nonzero, the character that ends the
+   number must match END, or an error happens;
+   and that character is skipped if it does match.
+   If END is zero, *PP is left pointing to that character.  */
+
+static long
+read_number (pp, end)
+     char **pp;
+     int end;
+{
+  register char *p = *pp;
+  register long n = 0;
+  register int c;
+  int sign = 1;
+
+  /* Handle an optional leading minus sign.  */
+
+  if (*p == '-')
+    {
+      sign = -1;
+      p++;
+    }
+
+  /* Read the digits, as far as they go.  */
+
+  while ((c = *p++) >= '0' && c <= '9')
+    {
+      n *= 10;
+      n += c - '0';
+    }
+  if (end)
+    {
+      if (c && c != end)
+       error ("Invalid symbol data: invalid character \\%03o at symbol pos %d.", c, symnum);
+    }
+  else
+    --p;
+
+  *pp = p;
+  return n * sign;
+}
+
+/* Read in an argument list.  This is a list of types, separated by commas
+   and terminated with END.  Return the list of types read in, or (struct type
+   **)-1 if there is an error.  */
+static struct type **
+read_args (pp, end)
+     char **pp;
+     int end;
+{
+  struct type *types[1024], **rval; /* allow for fns of 1023 parameters */
+  int n = 0;
+
+  while (**pp != end)
+    {
+      if (**pp != ',')
+       /* Invalid argument list: no ','.  */
+       return (struct type **)-1;
+      *pp += 1;
+
+      /* Check for and handle cretinous dbx symbol name continuation! */
+      if (**pp == '\\')
+       *pp = next_symbol_text ();
+
+      types[n++] = read_type (pp);
+    }
+  *pp += 1;                    /* get past `end' (the ':' character) */
+
+  if (n == 1)
+    {
+      rval = (struct type **) xmalloc (2 * sizeof (struct type *));
+    }
+  else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID)
+    {
+      rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *));
+      bzero (rval + n, sizeof (struct type *));
+    }
+  else
+    {
+      rval = (struct type **) xmalloc (n * sizeof (struct type *));
+    }
+  bcopy (types, rval, n * sizeof (struct type *));
+  return rval;
+}
+\f
+/* Copy a pending list, used to record the contents of a common
+   block for later fixup.  */
+static struct pending *
+copy_pending (beg, begi, end)
+    struct pending *beg, *end;
+    int begi;
+{
+  struct pending *new = 0;
+  struct pending *next;
+
+  for (next = beg; next != 0 && (next != end || begi < end->nsyms);
+       next = next->next, begi = 0)
+    {
+      register int j;
+      for (j = begi; j < next->nsyms; j++)
+       add_symbol_to_list (next->symbol[j], &new);
+    }
+  return new;
+}
+
+/* Add a common block's start address to the offset of each symbol
+   declared to be in it (by being between a BCOMM/ECOMM pair that uses
+   the common block name).  */
+
+static void
+fix_common_block (sym, valu)
+    struct symbol *sym;
+    int valu;
+{
+  struct pending *next = (struct pending *) SYMBOL_NAMESPACE (sym);
+  for ( ; next; next = next->next)
+    {
+      register int j;
+      for (j = next->nsyms - 1; j >= 0; j--)
+       SYMBOL_VALUE_ADDRESS (next->symbol[j]) += valu;
+    }
+}
+\f
+/* Register our willingness to decode symbols for SunOS and a.out and
+   b.out files handled by BFD... */
+static struct sym_fns sunos_sym_fns = {"sunOs", 6,
+              dbx_new_init, dbx_symfile_init,
+              dbx_symfile_read, dbx_symfile_discard};
+
+static struct sym_fns aout_sym_fns = {"a.out", 5,
+              dbx_new_init, dbx_symfile_init,
+              dbx_symfile_read, dbx_symfile_discard};
+
+static struct sym_fns bout_sym_fns = {"b.out", 5,
+              dbx_new_init, dbx_symfile_init,
+              dbx_symfile_read, dbx_symfile_discard};
+
+void
+_initialize_dbxread ()
+{
+  add_symtab_fns(&sunos_sym_fns);
+  add_symtab_fns(&aout_sym_fns);
+  add_symtab_fns(&bout_sym_fns);
+
+  undef_types_allocated = 20;
+  undef_types_length = 0;
+  undef_types = (struct type **) xmalloc (undef_types_allocated *
+                                         sizeof (struct type *));
+}
diff --git a/gdb/defs.h b/gdb/defs.h
new file mode 100644 (file)
index 0000000..51a46b4
--- /dev/null
@@ -0,0 +1,173 @@
+/* Basic definitions for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* An address in the program being debugged.  Host byte order.  */
+typedef unsigned int CORE_ADDR;
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/* The character C++ uses to build identifiers that must be unique from
+   the program's identifiers (such as $this and $$vptr).  */
+#define CPLUS_MARKER '$'       /* May be overridden to '.' for SysV */
+
+/*
+ * Allow things in gdb to be declared "const".  If compiling ANSI, it
+ * just works.  If compiling with gcc but non-ansi, redefine to __const__.
+ * If non-ansi, non-gcc, then eliminate "const" entirely, making those
+ * objects be read-write rather than read-only.
+ */
+#ifndef __STDC__
+# ifdef __GNUC__
+#  define const __const__
+#  define volatile __volatile__
+# else
+#  define const /*nothing*/
+#  define volatile /*nothing*/
+# endif /* GNUC */
+#endif /* STDC */
+
+extern char *savestring ();
+extern char *strsave ();
+extern char *concat ();
+#ifdef __STDC__
+extern void *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif
+extern void free ();
+extern int parse_escape ();
+extern char *reg_names[];
+/* Indicate that these routines do not return to the caller.  */
+extern volatile void error(), fatal();
+
+/* Various possibilities for alloca.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef sparc
+#  include <alloca.h>
+# endif
+  extern char *alloca ();
+# endif
+
+extern int errno;                      /* System call error return status */
+
+extern int quit_flag;
+extern int immediate_quit;
+extern void quit ();
+
+#define QUIT { if (quit_flag) quit (); }
+
+/* Notes on classes: class_alias is for alias commands which are not
+   abbreviations of the original command.  */
+
+enum command_class
+{
+  /* Special args to help_list */
+  all_classes = -2, all_commands = -1,
+  /* Classes of commands */
+  no_class = -1, class_run = 0, class_vars, class_stack,
+  class_files, class_support, class_info, class_breakpoint,
+  class_alias, class_obscure, class_user
+};
+
+/* the cleanup list records things that have to be undone
+   if an error happens (descriptors to be closed, memory to be freed, etc.)
+   Each link in the chain records a function to call and an
+   argument to give it.
+
+   Use make_cleanup to add an element to the cleanup chain.
+   Use do_cleanups to do all cleanup actions back to a given
+   point in the chain.  Use discard_cleanups to remove cleanups
+   from the chain back to a given point, not doing them.  */
+
+struct cleanup
+{
+  struct cleanup *next;
+  void (*function) ();
+  int arg;
+};
+
+/* From utils.c.  */
+extern void do_cleanups ();
+extern void discard_cleanups ();
+extern struct cleanup *make_cleanup ();
+extern struct cleanup *save_cleanups ();
+extern void restore_cleanups ();
+extern void free_current_contents ();
+extern int myread ();
+extern int query ();
+extern int lines_to_list ();
+extern void reinitialize_more_filter ();
+extern void fputs_filtered ();
+extern void puts_filtered ();
+extern void fprintf_filtered ();
+extern void printf_filtered ();
+extern void print_spaces ();
+extern void print_spaces_filtered ();
+extern char *n_spaces ();
+extern void printchar ();
+extern void fprint_symbol ();
+extern void fputs_demangled ();
+extern void perror_with_name ();
+extern void print_sys_errmsg ();
+
+/* From printcmd.c */
+extern void print_address_symbolic ();
+extern void print_address ();
+
+/* From readline (but not in any readline .h files).  */
+extern char *tilde_expand ();
+
+/* Structure for saved commands lines
+   (for breakpoints, defined commands, etc).  */
+
+struct command_line
+{
+  struct command_line *next;
+  char *line;
+};
+
+extern struct command_line *read_command_lines ();
+extern void free_command_lines ();
+
+/* String containing the current directory (what getwd would return).  */
+
+char *current_directory;
+
+/* Default radixes for input and output.  Only some values supported.  */
+extern unsigned input_radix;
+extern unsigned output_radix;
+
+/* Baud rate specified for communication with serial target systems.  */
+char *baud_rate;
+
+#if !defined (UINT_MAX)
+#define UINT_MAX 0xffffffff
+#endif
+
+#if !defined (LONG_MAX)
+#define LONG_MAX 0x7fffffff
+#endif
+
+/* Just like CHAR_BIT in <limits.h> but describes the target machine.  */
+#if !defined (TARGET_CHAR_BIT)
+#define TARGET_CHAR_BIT 8
+#endif
diff --git a/gdb/depend b/gdb/depend
new file mode 100755 (executable)
index 0000000..c78aa66
--- /dev/null
@@ -0,0 +1,195 @@
+altos-xdep.o : altos-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+am29k-pinsn.o : am29k-pinsn.c defs.h target.h am29k-opcode.h 
+am29k-tdep.o : am29k-tdep.c defs.h gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h \
+  param.h tm.h config.status param-no-tm.h xm.h config.status value.h symtab.h inferior.h breakpoint.h 
+arm-pinsn.o : arm-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  arm-opcode.h 
+arm-tdep.o : arm-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h arm-opcode.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+arm-xdep.o : arm-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h arm-opcode.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+blockframe.o : blockframe.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  frame.h gdbcore.h $(INCLUDE_DIR)/bfd.h value.h target.h 
+breakpoint.o : breakpoint.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  frame.h breakpoint.h value.h expression.h gdbcore.h $(INCLUDE_DIR)/bfd.h \
+  gdbcmd.h command.h inferior.h target.h 
+coffread.o : coffread.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  breakpoint.h value.h $(INCLUDE_DIR)/bfd.h $(BFD_DIR)/libcoff.h symfile.h 
+command.o : command.c defs.h command.h symtab.h value.h 
+convex-pinsn.o : convex-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  symtab.h convex-opcode.h 
+convex-tdep.o : convex-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  command.h symtab.h value.h frame.h inferior.h breakpoint.h \
+  $(INCLUDE_DIR)/wait.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h 
+convex-xdep.o : convex-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  command.h symtab.h value.h frame.h inferior.h breakpoint.h \
+  $(INCLUDE_DIR)/wait.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h 
+core.o : core.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h inferior.h \
+  breakpoint.h value.h symtab.h command.h $(INCLUDE_DIR)/bfd.h target.h \
+  gdbcore.h 
+coredep.o : coredep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+cplus-dem.o : cplus-dem.c 
+dbxread.o : dbxread.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  $(INCLUDE_DIR)/a.out.gnu.h $(INCLUDE_DIR)/target.h $(INCLUDE_DIR)/reloc.h \
+  $(INCLUDE_DIR)/stab.gnu.h $(INCLUDE_DIR)/stab.def symtab.h breakpoint.h value.h \
+  command.h target.h gdbcore.h $(INCLUDE_DIR)/bfd.h $(BFD_DIR)/liba.out.h \
+  symfile.h 
+environ.o : environ.c environ.h 
+eval.o : eval.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h value.h \
+  expression.h target.h 
+exec.o : exec.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h inferior.h \
+  breakpoint.h value.h symtab.h target.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+expprint.o : expprint.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  expression.h value.h 
+findvar.o : findvar.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  frame.h value.h gdbcore.h $(INCLUDE_DIR)/bfd.h inferior.h breakpoint.h \
+  target.h 
+gould-pinsn.o : gould-pinsn.c gdbcore.h $(INCLUDE_DIR)/bfd.h defs.h param.h \
+  tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h np1-opcode.h 
+gould-xdep.o : gould-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+hp300hpux-xdep.o : hp300hpux-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  frame.h inferior.h breakpoint.h value.h symtab.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+i386-pinsn.o : i386-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  frame.h inferior.h breakpoint.h value.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+i386-tdep.o : i386-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+i386-xdep.o : i386-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+i960-pinsn.o : i960-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h 
+i960-tdep.o : i960-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  value.h frame.h signame.h ieee-float.h 
+ieee-float.o : ieee-float.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  ieee-float.h 
+infcmd.o : infcmd.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h \
+  inferior.h breakpoint.h value.h environ.h gdbcmd.h command.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h target.h 
+inflow.o : inflow.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h command.h signals.h terminal.h \
+  target.h 
+infptrace.o : infptrace.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h target.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+infrun.o : infrun.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h \
+  inferior.h breakpoint.h value.h $(INCLUDE_DIR)/wait.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h signame.h command.h terminal.h target.h 
+inftarg.o : inftarg.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h target.h $(INCLUDE_DIR)/wait.h \
+  gdbcore.h $(INCLUDE_DIR)/bfd.h ieee-float.h 
+m68k-pinsn.o : m68k-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  m68k-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+m68k-tdep.o : m68k-tdep.c defs.h ieee-float.h 
+main.o : main.c defs.h gdbcmd.h command.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  symtab.h inferior.h breakpoint.h value.h frame.h signals.h target.h 
+mem-break.o : mem-break.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status 
+mips-pinsn.o : mips-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  mips-opcode.h 
+mips-tdep.o : mips-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcmd.h command.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+mips-xdep.o : mips-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+mipsread.o : mipsread.c param.h tm.h config.status param-no-tm.h xm.h config.status obstack.h defs.h \
+  symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h symfile.h $(INCLUDE_DIR)/intel-coff.h 
+news-xdep.o : news-xdep.c 
+Onindy.o : ${srcdir}/nindy-share/Onindy.c ${srcdir}/nindy-share/ttycntl.h \
+  ${srcdir}/nindy-share/block_io.h $(INCLUDE_DIR)/wait.h ${srcdir}/nindy-share/env.h \
+  /usr/include/string.h 
+nindy.o : ${srcdir}/nindy-share/nindy.c ${srcdir}/nindy-share/ttycntl.h ${srcdir}/nindy-share/block_io.h \
+  $(INCLUDE_DIR)/wait.h ${srcdir}/nindy-share/env.h /usr/include/string.h 
+ttybreak.o : ${srcdir}/nindy-share/ttybreak.c ${srcdir}/nindy-share/ttycntl.h 
+ttyflush.o : ${srcdir}/nindy-share/ttyflush.c ${srcdir}/nindy-share/ttycntl.h 
+nindy-tdep.o : nindy-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  frame.h 
+ns32k-pinsn.o : ns32k-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  symtab.h ns32k-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+printcmd.o : printcmd.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  symtab.h value.h expression.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h \
+  command.h target.h 
+pyr-pinsn.o : pyr-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  pyr-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+pyr-tdep.o : pyr-tdep.c 
+pyr-xdep.o : pyr-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+remote-eb.o : remote-eb.c defs.h tm-29k.h param-no-tm.h xm.h config.status inferior.h \
+  breakpoint.h value.h symtab.h frame.h param.h $(INCLUDE_DIR)/wait.h \
+  terminal.h target.h 
+remote-nindy.o : remote-nindy.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  frame.h inferior.h breakpoint.h value.h symtab.h target.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h command.h ieee-float.h $(INCLUDE_DIR)/wait.h \
+  ${srcdir}/nindy-share/ttycntl.h ${srcdir}/nindy-share/demux.h ${srcdir}/nindy-share/env.h \
+  ${srcdir}/nindy-share/stop.h 
+remote-vx.o : remote-vx.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h $(INCLUDE_DIR)/wait.h target.h \
+  gdbcore.h $(INCLUDE_DIR)/bfd.h command.h symfile.h ${srcdir}/vx-share/xdr_ptrace.h \
+  ${srcdir}/vx-share/xdr_regs.h ${srcdir}/vx-share/reg.h ${srcdir}/vx-share/xdr_ld.h \
+  ${srcdir}/vx-share/xdr_rdb.h ${srcdir}/vx-share/dbgRpcLib.h 
+remote.o : remote.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h target.h $(INCLUDE_DIR)/wait.h \
+  terminal.h 
+signame.o : signame.c signame.h 
+solib.o : solib.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h command.h 
+source.o : source.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  command.h frame.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+sparc-pinsn.o : sparc-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  symtab.h sparc-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h /usr/include/string.h \
+  target.h 
+sparc-tdep.o : sparc-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h obstack.h signame.h target.h \
+  ieee-float.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+sparc-xdep.o : sparc-xdep.c defs.h tm-sparc.h param-no-tm.h xm.h config.status inferior.h \
+  breakpoint.h value.h symtab.h frame.h param.h target.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+stack.o : stack.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h \
+  gdbcmd.h command.h value.h gdbcore.h $(INCLUDE_DIR)/bfd.h target.h \
+  breakpoint.h 
+sun3-xdep.o : sun3-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status inferior.h \
+  breakpoint.h value.h symtab.h frame.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+sun386-xdep.o : sun386-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  frame.h inferior.h breakpoint.h value.h symtab.h signame.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+symfile.o : symfile.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h target.h value.h symfile.h gdbcmd.h \
+  command.h breakpoint.h 
+symmetry-tdep.o : symmetry-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  frame.h inferior.h breakpoint.h value.h symtab.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+symmetry-xdep.o : symmetry-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  frame.h inferior.h breakpoint.h value.h symtab.h gdbcore.h \
+  $(INCLUDE_DIR)/bfd.h 
+symmisc.o : symmisc.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  breakpoint.h value.h command.h 
+symtab.o : symtab.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h target.h value.h symfile.h gdbcmd.h \
+  command.h 
+target.o : target.c defs.h target.h gdbcmd.h command.h symtab.h inferior.h \
+  breakpoint.h value.h frame.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+  $(INCLUDE_DIR)/bfd.h symfile.h 
+tdesc.o : tdesc.c 
+umax-xdep.o : umax-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+  inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h 
+utils.o : utils.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status signals.h gdbcmd.h \
+  command.h terminal.h $(INCLUDE_DIR)/bfd.h target.h 
+valarith.o : valarith.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status value.h \
+  symtab.h expression.h target.h 
+valops.o : valops.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h value.h \
+  frame.h inferior.h breakpoint.h gdbcore.h $(INCLUDE_DIR)/bfd.h target.h 
+valprint.o : valprint.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  value.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h command.h target.h obstack.h 
+values.o : values.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h value.h \
+  gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h command.h 
+vax-pinsn.o : vax-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+  vax-opcode.h 
+xdr_ld.o : ${srcdir}/vx-share/xdr_ld.c ${srcdir}/vx-share/vxWorks.h ${srcdir}/vx-share/vxTypes.h \
+  /usr/include/rpc/rpc.h ${srcdir}/vx-share/xdr_ld.h 
+xdr_ptrace.o : ${srcdir}/vx-share/xdr_ptrace.c 
+xdr_rdb.o : ${srcdir}/vx-share/xdr_rdb.c ${srcdir}/vx-share/vxWorks.h ${srcdir}/vx-share/vxTypes.h \
+  ${srcdir}/vx-share/xdr_rdb.h 
+xdr_regs.o : ${srcdir}/vx-share/xdr_regs.c 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
new file mode 100644 (file)
index 0000000..9882beb
--- /dev/null
@@ -0,0 +1,5361 @@
+\input texinfo
+@setfilename _GDBP__.info
+@c
+@c NOTE: this manual is marked up for preprocessing with a collection
+@c of m4 macros called "pretex.m4".  If you see <_if__> and <_fi__>
+@c scattered around the source, you have the full source before
+@c preprocessing; if you don't, you have the source configured for
+@c _HOST__ architectures (and you can of course get the full source,
+@c with all configurations, from wherever you got this).
+_if__(0)
+
+THIS IS THE FULL SOURCE.  The full source needs to be run through m4
+before either tex- or info- formatting: for example,
+_0__
+    m4 pretex.m4 none.m4 m680x0.m4 gdb.texinfo >gdb-680x0.texinfo
+_1__
+will produce (assuming your path finds either GNU or SysV m4; Berkeley
+won't do) a file suitable for formatting.  See the text in "pretex.m4"
+for a fuller explanation (and the macro definitions).
+    To permit maximum flexibility, the full source also does not contain
+any "info" markup that can be generated automatically; you should first
+preprocess it as above, then run it through C-u texinfo-master-menu,
+before actually info-formatting it.
+_fi__(0)
+@c
+@syncodeindex ky cp
+@c FOR UPDATES LEADING TO THIS DRAFT, GDB CHANGELOG CONSULTED BETWEEN:
+@c Tue Feb 26 01:47:07 1991  Cygnus John Gilmore  (cygnus at yuba)
+@c Sat Dec 22 02:51:40 1990  John Gilmore  (gnu at cygint)
+@ifinfo
+This file documents the GNU debugger _GDBN__.
+
+Copyright (C) 1988, 1989, 1990, 1991 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 also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and 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 the section entitled ``GNU General Public License'' may be
+included in a translation approved by the author instead of in the
+original English.
+@end ifinfo
+@smallbook
+@setchapternewpage odd
+_if__(_GENERIC__)
+@settitle Using _GDBN__ (v4.0)
+_fi__(_GENERIC__)
+_if__(!_GENERIC__)
+@settitle Using _GDBN__ v4.0 (_HOST__)
+_fi__(!_GENERIC__)
+@iftex
+@c @finalout
+@end iftex
+@titlepage
+@title{Using _GDBN__}
+@subtitle{A Guide to the GNU Source-Level Debugger}
+_if__(!_GENERIC__)
+@subtitle{On _HOST__ Systems}
+_fi__(!_GENERIC__)
+@sp 1
+@c Maybe crank this up to "Fourth Edition" when released at FSF
+@c @subtitle Third Edition---_GDBN__ version 4.0
+@subtitle _GDBN__ version 4.0
+@subtitle January 1991
+@author{Richard M. Stallman}
+@author{Roland H. Pesch (Cygnus Support)}
+@page
+
+@tex
+\def\$#1${{#1}}  % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision$}  % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill {\it Using _GDBN__}, \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988, 1989, 1990, 1991 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
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and 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 the section entitled ``GNU General Public License'' may be
+included in a translation approved by the author instead of in the
+original English.
+@end titlepage
+@page
+
+@node Top,,,
+@unnumbered Summary of _GDBN__
+
+The purpose of a debugger such as _GDBN__ is to allow you to see what is
+going on ``inside'' another program while it executes---or what another
+program was doing at the moment it crashed.  
+
+_GDBN__ can do four main kinds of things (plus other things in support of
+these) to help you catch bugs in the act:
+
+@enumerate
+@item
+Start your program, specifying anything that might affect its behavior.
+
+@item
+Make your program stop on specified conditions.
+
+@item
+Examine what has happened, when your program has stopped.
+
+@item
+Change things in your program, so you can experiment with correcting the
+effects of one bug and go on to learn about another.
+@end enumerate
+
+_GDBN__ can be used to debug programs written in C and C++.  Pascal support
+is being implemented, and Fortran support will be added when a GNU
+Fortran compiler is ready.
+
+@node Free Software,,,
+@unnumberedsec Free Software
+_GDBN__ is Free Software, protected by the GNU General Public License (GPL).
+The GPL gives you the freedom to copy or adapt a licensed
+program---but every person getting a copy also gets with it the
+freedom to modify that copy (which means that they must get access to
+the source code), and the freedom to distribute further copies.
+Typical software companies use copyrights to limit your freedoms; the
+Free Software Foundation uses the GPL to preserve these freedoms.
+
+Fundamentally, the General Public License is a license which says that
+you have these freedoms and that you can't take these freedoms away
+from anyone else.
+
+For full details, @pxref{License}.
+
+@node New Features,,,
+@unnumbered New Features in _GDBN__ version 4.0
+
+@itemize @bullet
+@item
+TARGETS: Using the new command @samp{target}, you can select at runtime
+whether you are debugging local files, local processes, standalone
+systems over the serial port, realtime systems over a TCP/IP
+connection, etc.  _GDBN__ now uses a function vector to mediate access to
+all the different possible targets, making it much easier to add
+support for new remote protocols.
+
+@item
+WATCHPOINTS: _GDBN__ now sports watchpoints as well as breakpoints.  You can
+use a watchpoint to stop execution whenever the value of an expression
+changes, without having to predict a particular place in the inferior
+process where this may happen. 
+
+@item
+OBJECT CODE FORMATS: _GDBN__ uses a new scheme called Binary File
+Descriptors (BFD) to permit it to switch dynamically, without
+reconfiguration or recompilation, between different object-file
+formats.  Formats currently supported are COFF, a.out, and the new
+Intel 960 b.out; files may be read as .o's, archive libraries, or core
+dumps.  BFD is available as a subroutine library so that other
+programs may take advantage of it, and the other GNU binary utilities
+are being converted to use it.
+
+@item
+CONFIGURATION: You must still choose a particular machine architecture
+and operating system for _GDBN__'s host and target systems when _GDBN__ is built.
+The script @samp{config.gdb} now handles specification of separate host
+and target configurations.
+
+@item
+INTERACTION: _GDBN__ now uses the GNU readline interface to read its
+input; this provides inline editing of commands, using the familiar
+Emacs or @code{vi} keymaps, and command-history support. The user interface
+to _GDBN__'s control variables has been simplified and consolidated in two
+commands, @samp{set} and @samp{show}.  Output lines are now broken at
+readable places, rather than overflowing onto the next line.
+
+@item
+SOURCE LANGUAGE: _GDBN__ now understands C++ source as well as C. Multiple
+inheritance is supported when used with G++ 2.0. There is also limited
+support for C++ exception handling: _GDBN__ can break when an exception is
+raised, before the stack is peeled back to the exception handler's
+context.  You can suppress output of machine-level addresses,
+displaying only source language information.
+
+@item
+PORTS: _GDBN__ has been ported to the following new architectures: 
+AT&T 3b1, Acorn RISC machine, HP300 running HPUX, big- and little-
+endian MIPS machines, Motorola 88k, Sun 386i, and Sun 3 running SunOS
+4.  In addition, the following are supported as targets only:  AMD
+29k, Intel 960, and Wind River's VxWorks.
+
+@item
+SHARED LIBRARIES: _GDBN__ 4.0 supports SunOS shared libraries.
+
+@item
+WORK IN PROGRESS: kernel debugging for BSD and Mach systems; Tahoe and
+HPPA architecture support.
+
+@end itemize
+
+@node Sample Session,,,
+@chapter A Sample _GDBN__ Session
+
+You can use this manual at your leisure to read all about _GDBN__.
+However, a handful of commands are enough to get started using the
+debugger.  This chapter illustrates these commands.
+
+In this sample session, we emphasize user input like this: @var{input},
+to make it easier to pick out from the surrounding output.
+
+@c FIXME: this example may not be appropriate for some configs, where
+@c FIXME...primary interest is in remote use.
+We'll be using _GDBN__ to inspect GNU @code{m4} (a generic macro
+processor).
+
+_0__@smallexample
+$ @var{cd gm4/common}
+
+$ @var{_GDBP__ m4}
+Reading symbol data from m4...done.
+(_GDBP__) set width 70
+@end smallexample
+
+@noindent
+_GDBN__ only reads enough symbol data to know where to find the rest
+when needed; as a result, the first prompt comes up very quickly.  We
+immediately told _GDBN__ to use a narrower display width than usual, so
+that examples will fit in this manual.
+
+@smallexample
+(_GDBP__) @var{break m4_changequote}
+Breakpoint 1 at 0x59d4: file builtin.c, line 812.
+@end smallexample
+
+@noindent 
+We've chosen to see how the @code{m4} builtin @samp{changequote} works.
+Having looked at the source, we knew the relevant subroutine is
+@samp{m4_changequote}.  We've set a breakpoint there with _GDBN__'s
+@code{break} command.
+
+@smallexample
+(_GDBP__) @var{run}
+Starting program: /s1/gnu/src/gm4/common/m4 
+@var{`usual' quotes <not these>}
+usual quotes <not these>
+@end smallexample
+
+@noindent
+Using the @samp{run} command, we've started @code{m4} running under
+_GDBN__ control; while we don't touch the @samp{m4_changequote}
+subroutine, the program runs as usual---it filters standard input. 
+
+@smallexample
+@var{changequote(<,>)}
+
+Breakpoint 1, m4_changequote (argc=3, argv=0x2b958) at builtin.c:812
+812         if (bad_argc(TOKEN_DATA_TEXT(argv[0]), argc, 1, 3))
+@end smallexample
+@noindent
+To trigger the breakpoint, we called @code{changequote}.  _GDBN__
+suspended execution of @code{m4}, displaying information about the
+context where it stopped.
+
+@smallexample
+(_GDBP__) @var{s}
+bad_argc (name=0xf851cfb4<Address 0xf851cfb4 out of bounds>, argc=3,
+    min=1, max=3) at builtin.c:230
+230         if (min > 0 && argc < min) @{
+@end smallexample
+@noindent
+We've used the command @samp{s} (@code{step}) to advance execution to
+the next source line; since there was a subroutine call, we've stopped
+in the first line of that subroutine, not in the next line of
+@code{m4_changequote}.
+
+The command @samp{next} would have taken us to the next line of
+@code{m4_changequote}.  To see where we are in the stack, we can use the
+@samp{backtrace} command (which can also be spelled @samp{bt}).
+
+@smallexample
+(_GDBP__) @var{bt}
+#0  bad_argc (name=0xf851cfb4<Address 0xf851cfb4 out of bounds>, 
+    argc=3, min=1, max=3) at builtin.c:230
+#1  0x59ec in m4_changequote (argc=3, argv=0x2b958) at builtin.c:812
+#2  0x6e38 in expand_macro (sym=0x2b060) at macro.c:242
+#3  0x6840 in expand_token (obs=0x0, t=176224, td=0xf7fffb08)
+    at macro.c:71
+#4  0x6794 in expand_input () at macro.c:40
+#5  0x28dc in main (argc=0, argv=0xf7fffbf8) at m4.c:174
+@end smallexample
+
+@noindent
+We'll tell _GDBN__ to finish execution of this subroutine, to get back
+to @code{m4_changequote}.
+
+@smallexample
+(_GDBP__) @var{finish}
+Run till exit from #0  bad_argc (name=0xf851cfb4<Address 0xf851cfb4 out
+ of bounds>, 
+    argc=3, min=1, max=3) at builtin.c:230
+0x59ec in m4_changequote (argc=3, argv=0x2b958) at builtin.c:812
+812         if (bad_argc(TOKEN_DATA_TEXT(argv[0]), argc, 1, 3))
+Value returned is $1 = false
+@end smallexample
+
+@noindent
+We're still in the middle of the first line of @code{m4_changequote};
+@samp{finish} just allowed the subroutine call to complete.
+The display beginning ``@code{0x59ec in}@dots'', preceding the
+display of line @code{812}, is a reminder of that situation from
+_GDBN__.
+
+Now that we're past the subroutine call, using the @code{step} command
+again will get us to the next line of @code{m4_changequote}.
+
+@smallexample
+(_GDBP__) @var{s}
+815         lquote = (argc >= 2) ? TOKEN_DATA_TEXT(argv[1])[0] : DEF_LQ
+UOTE;
+(_GDBP__) @var{whatis lquote}
+type = char
+(_GDBP__) @var{p lquote}
+$2 = 96 '`'
+@end smallexample
+
+@noindent
+When we stepped to another line, @code{m4} was about to set a variable
+@samp{lquote}; we inspected its type with @samp{whatis} and its value
+with @samp{p} (the @samp{print} command).  We can see some context by
+displaying the surrounding source code, with the @samp{l} (@code{list})
+command. 
+
+@smallexample
+(_GDBP__) @var{l}
+810         token_data **argv;
+811     @{
+812         if (bad_argc(TOKEN_DATA_TEXT(argv[0]), argc, 1, 3))
+813             return;
+814     
+815         lquote = (argc >= 2) ? TOKEN_DATA_TEXT(argv[1])[0] : DEF_LQ
+UOTE;
+816         rquote = (argc >= 3) ? TOKEN_DATA_TEXT(argv[2])[0] : DEF_RQ
+UOTE;
+817     @}
+818     
+819     /* 
+(_GDBP__) @var{s}
+816         rquote = (argc >= 3) ? TOKEN_DATA_TEXT(argv[2])[0] : DEF_RQ
+UOTE;
+(_GDBP__) @var{s}
+817     @}
+(_GDBP__) @var{p lquote}
+$3 = 60 '<'
+(_GDBP__) @var{p rquote}
+$4 = 62 '>'
+@end smallexample
+
+@noindent
+We proceeded past another line with @samp{s}, and inspected the new
+values of @code{m4}'s internal variables @code{rquote} and
+@code{lquote}.
+
+Since we're done with our inspection of this subroutine, we'll tell
+_GDBN__ to allow @code{m4} to continue running, with the @samp{c}
+(@code{continue}) command:
+
+@smallexample
+(_GDBP__) @var{c}
+Continuing.
+
+@var{`usual' quotes <not these>}
+`usual' quotes not these
+
+Program exited normally.
+(_GDBP__) @var{quit}
+
+$ 
+_1__@end smallexample
+
+@noindent 
+Finally, when we ended the @code{m4} run, _GDBN__ told us
+``@code{Program exited normally.}'' We ended our _GDBN__ session with
+the _GDBN__ @samp{quit} command.
+
+
+@node Invocation,,,
+@chapter Getting In and Out of _GDBN__
+
+@node Starting _GDBN__,,,
+@section Starting _GDBN__
+
+_GDBN__ is invoked with the shell command @samp{_GDBP__}.  Once started, it reads
+commands from the terminal until you tell it to exit.
+
+You can start by just calling @samp{_GDBP__} with no arguments or
+options; but the most usual way to start _GDBN__ is with one argument or
+two, specifying an executable program as the argument:
+@example
+_GDBP__ program
+@end example
+@noindent
+or you can start with both an executable program and a core file specified:
+@example
+_GDBP__ program core
+@end example
+
+You can get more detailed control over how _GDBN__ starts up using some of
+the command-line options.
+
+All the options and command line arguments given are processed
+in sequential order.  The order makes a difference when the
+@samp{-x} option is used.  
+
+@node File Options,,,
+@subsection Choosing Files
+
+As shown above, any arguments other than options specify an executable
+file and core file; that is, the first argument encountered with no
+associated option flag is equivalent to a @samp{-se} option, and the
+second, if any, is equivalent to a @samp{-c} option.
+
+@table @code
+@item -s @var{file}
+Read symbol table from file @var{file}.
+
+@item -e @var{file}
+Use file @var{file} as the executable file to execute when
+appropriate, and for examining pure data in conjunction with a core
+dump.
+
+@item -se @var{file}
+Read symbol table from file @var{file} and use it as the executable
+file.
+
+@item -c @var{file}
+Use file @var{file} as a core dump to examine.
+
+@item -x @var{file}
+Execute _GDBN__ commands from file @var{file}.  @xref{Command Files}.
+
+@item -d @var{directory}
+Add @var{directory} to the path to search for source files.
+@end table
+
+@node Mode Options,,, 
+@subsection Choosing Modes
+
+@table @code
+@item -nx
+Do not execute commands from the init files @file{_GDBINIT__}.
+Normally, the commands in these files are executed after all the
+command options and arguments have been processed.  @xref{Command
+Files}.
+
+@item -q
+``Quiet''.  Do not print the introductory and copyright messages.  These
+messages are also suppressed in batch mode, or if an executable file name is
+specified on the _GDBN__ command line.
+
+@item -batch
+Run in batch mode.  Exit with code @code{0} after processing all the command
+files specified with @samp{-x} (and @file{_GDBINIT__}, if not inhibited).
+Exit with nonzero status if an error occurs in executing the _GDBN__
+commands in the command files.  
+
+Batch mode may be useful for running _GDBN__ as a filter, for example to
+download and run a program on another computer; in order to make this
+more useful, the message 
+@example
+Program exited normally.
+@end example
+@noindent
+(which is ordinarily issued whenever a program running under _GDBN__ control
+terminates) is not issued when running in batch mode.
+
+@item -fullname
+This option is used when Emacs runs _GDBN__ as a subprocess.  It tells _GDBN__
+to output the full file name and line number in a standard,
+recognizable fashion each time a stack frame is displayed (which
+includes each time the program stops).  This recognizable format looks
+like two @samp{\032} characters, followed by the file name, line number
+and character position separated by colons, and a newline.  The
+Emacs-to-_GDBN__ interface program uses the two @samp{\032} characters as
+a signal to display the source code for the frame.
+
+@item -b @var{bps}
+Set the line speed (baud rate or bps) of any serial interface used by
+_GDBN__ for remote debugging.
+@end table
+
+_if__(_I960__)
+@node i960-Nindy Remote,,,
+@subsection _GDBN__ with a Remote i960 (Nindy)
+
+``Nindy'' is the name of a ROM Monitor program for Intel 960 target
+systems.  When _GDBN__ is configured to control a remote Intel 960 using
+Nindy, you can tell _GDBN__ how to connect to the 960 in several ways:
+
+@itemize @bullet
+@item
+Through command line options specifying device, baud rate, and protocol;
+
+@item
+By responding to a prompt on startup;
+
+@item
+By using the @samp{target} command at any point during your _GDBN__ session.
+@end itemize
+
+@node Nindy Startup,,,
+@subsubsection Startup with Nindy
+
+The command-line options for Nindy are detailed below.  If you simply
+start @code{_GDBP__} without using options to specify a serial port, you are
+prompted for it, @emph{before} you reach the ordinary _GDBN__ prompt:
+@example
+Attach /dev/ttyNN -- specify NN, or "quit" to quit:  
+@end example
+@noindent
+You can, if you choose, simply start up with no Nindy connection by
+responding to the prompt with an empty line.  If you do this, and later
+wish to attach to Nindy, use @samp{target} (@pxref{Target Commands}). 
+
+@node Nindy Options,,,
+@subsubsection Options for Nindy
+
+These are the startup options for beginning your _GDBN__ session with a
+Nindy-960 board attached:
+
+@table @code
+@item -r @var{port}
+Specify the serial port name of a serial interface to be used to connect
+to the target system.  This option is only available when _GDBN__ is
+configured for the Intel 960 target architecture.  You may specify
+@var{port} as any of: a full pathname (e.g. @samp{-r /dev/ttya}), a
+device name in @samp{/dev} (e.g. @samp{-r ttya}), or simply the unique
+suffix for a specific @code{tty} (e.g. @samp{-r a}).
+
+@item -O
+(An uppercase letter ``O'', not a zero.)  Specify that _GDBN__ should use
+the ``old'' Nindy monitor protocol to connect to the target system.
+This option is only available when _GDBN__ is configured for the Intel 960
+target architecture.
+
+@quotation
+@emph{Warning:} if you specify @samp{-O}, but are actually trying to
+connect to a target system using the current protocol, the connection
+will fail appearing to be a speed mismatch, and _GDBN__ will repeatedly
+attempt to reconnect at several different line speeds.  You can abort
+this process with an interrupt.
+@end quotation
+
+@item -brk
+Specify that _GDBN__ should first send a @samp{BREAK} signal to the target
+system, in an attempt to reset it, before connecting to a Nindy target.
+This option is only available when _GDBN__ is configured for the Intel 960
+target architecture.
+
+@quotation
+@emph{Warning:} Many target systems do not have the hardware that this
+requires; it only works with a few boards.
+@end quotation
+
+@end table
+
+The standard @samp{-b} option controls the line speed used on the serial
+port. 
+_fi__(_I960__)
+
+_if__(_AMD29K__)
+@node EB29K Remote,,,
+@subsection _GDBN__ with a Remote EB29K
+
+@cindex EB29K board
+@cindex running 29K programs
+@cindex 29K
+
+To use _GDBN__ from a Unix system to run programs on AMD's EB29K
+board in a PC, you must first connect a serial cable between the PC
+and a serial port on the Unix system.  In the following, we assume
+you've hooked the cable between the PC's @samp{COM1} port and
+@samp{/dev/ttya} on the Unix system.
+
+@node Comms (EB29K),,,
+@subsubsection Communications Setup
+The next step is to set up the PC's port, by doing something like the
+following in DOS on the PC:
+_0__@example
+C:\> MODE com1:9600,n,8,1,none
+_1__@end example
+@noindent
+This example---run on an MS DOS 4.0 system---sets the PC port to 9600
+bps, no parity, eight data bits, one stop bit, and no ``retry'' action;
+you must match the communications parameters when establishing the Unix
+end of the connection as well.
+@c FIXME: Who knows what this "no retry action" crud from the DOS manual may
+@c       mean?  It's optional; leave it out? ---pesch@cygnus.com, 25feb91 
+
+To give control of the PC to the Unix side of the serial line, type
+the following at the DOS console:
+_0__@example
+C:\> CTTY com1
+_1__@end example
+@noindent
+(Later, if you wish to return control to the DOS console, you can use
+the command @samp{CTTY con}---but you must send it over the device that
+had control, in our example over the @samp{com1} serial line).
+
+From the Unix host, use a communications program such as @code{tip} or
+@code{cu} to communicate with the PC; for example,
+@example
+cu -s 9600 -l /dev/ttya
+@end example
+@noindent
+The @code{cu} options shown specify, respectively, the linespeed and the
+serial port to use.  If you use @code{tip} instead, your command line
+may look something like the following instead:
+@example
+tip -9600 /dev/ttya
+@end example
+@noindent
+Your system may define a different name where our example uses
+@samp{/dev/ttya} (the argument to @code{tip}).  The communications
+parameters, including what port to use, are associated with the
+@code{tip} argument in the ``remote'' descriptions file---normally the
+system table @file{/etc/remote}.
+@c FIXME: What if anything needs doing to match the "n,8,1,none" part of
+@c the DOS side's comms setup?  cu can support -o (odd
+@c parity), -e (even parity)---apparently no settings for no parity or
+@c for character size.  Taken from stty maybe...?  John points out tip
+@c can set these as internal variables, eg ~s parity=none; man stty
+@c suggests that it *might* work to stty these options with stdin or
+@c stdout redirected... ---pesch@cygnus.com, 25feb91
+
+@kindex EBMON
+Using the @samp{tip} or @samp{cu} connection, change the DOS working
+directory to the directory containing a copy of your 29K program, then
+start the PC program @samp{EBMON} (an EB29K control program supplied
+with your board by AMD).  You should see an initial display from
+@code{EBMON} similar to the one in our example, ending with the
+@code{EBMON} prompt @samp{#}---
+_0__@example
+C:\> g:
+
+G:\> CD \usr\joe\work29k
+
+G:\USR\JOE\WORK29K> EBMON
+Am29000 PC Coprocessor Board Monitor, version 3.0-18
+Copyright 1990 Advanced Micro Devices, Inc.
+Written by Gibbons and Associates, Inc.
+
+Enter '?' or 'H' for help
+
+PC Coprocessor Type   = EB29K
+I/O Base              = 0x208
+Memory Base           = 0xd0000
+
+Data Memory Size      = 2048KB
+Available I-RAM Range = 0x8000 to 0x1fffff
+Available D-RAM Range = 0x80002000 to 0x801fffff
+
+PageSize              = 0x400
+Register Stack Size   = 0x800
+Memory Stack Size     = 0x1800
+
+CPU PRL               = 0x3
+Am29027 Available     = No
+Byte Write Available  = Yes
+
+# ~.
+_1__@end example
+
+Then exit the @code{cu} or @code{tip} program (done in the example by
+typing @code{~.} at the @code{EBMON} prompt).  @code{EBMON} will keep
+running, ready for _GDBN__ to take over.
+
+For this example, we've assumed what is probably the most convenient
+way to make sure the same 29K program is on both the PC and the Unix
+system: a PC/NFS connection that establishes ``drive @code{G:}'' on the
+PC as a file system on the Unix host.  If you don't have PC/NFS or
+something similar connecting the two systems, you must arrange some
+other way---perhaps floppy-disk transfer---of getting the 29K program
+from the Unix system to the PC; _GDBN__ will @emph{not} download it over the
+serial line.
+
+@node _GDBP__-EB29K,,,
+@subsubsection EB29K cross-debugging
+Finally, @code{cd} to the directory containing an image of your 29K
+program on the Unix system, and start _GDBN__---specifying as argument the
+name of your 29K program:
+@example
+cd /usr/joe/work29k
+_GDBP__ myfoo
+@end example
+Now you can use the @code{target} command:
+@example
+target amd-eb /dev/ttya 9600 MYFOO
+@end example
+@c FIXME: test above 'target amd-eb' as spelled, with caps!  caps are meant to
+@c emphasize that this is the name as seen by DOS (since I think DOS is
+@c single-minded about case of letters).  ---pesch@cygnus.com, 25feb91
+
+@noindent
+In this example, we've assumed your program is in a file called
+@samp{myfoo}.  Note that the filename given as the last argument to
+@samp{target amd-eb} should be the name of the program as it appears to DOS.
+In our example it is simply @samp{MYFOO}, but in general it can include
+a DOS path, and depending on your transfer mechanism may not resemble
+the name on the Unix side.
+
+At this point, you can set any breakpoints you wish; when you're ready
+to see your program run on the 29K board, use the _GDBN__ command
+@example
+run
+@end example
+
+To stop debugging the remote program, use the _GDBN__ @samp{detach}
+command.  
+
+To return control of the PC to its console, use @code{tip} or @code{cu}
+once again, after your _GDBN__ session has concluded, to attach to
+@code{EBMON}.  You can then type the command @samp{q} to shut down
+@code{EBMON}, returning control to the DOS command-line interpreter.
+Type @samp{CTTY con} to return command input to the main DOS console,
+and type @samp{~.} to leave @code{tip} or @code{cu}.
+
+@node Remote Log,,,
+@subsubsection Remote Log
+@kindex eb.log
+@cindex log file for EB29K
+The @samp{target amd-eb} command creates a file @file{eb.log} in the
+current working directory, to help debug problems with the connection.
+@file{eb.log} records all the output from @code{EBMON}, including echoes
+of the commands sent to it.  Running @samp{tail -f} on this file in
+another window often helps to debug trouble with @code{EBMON}, or
+unexpected events on the PC side of the connection.
+_fi__(_AMD29K__)
+
+_if__(_VXWORKS__)
+@node VxWorks Remote,,,
+@subsection _GDBN__ and VxWorks
+_GDBN__ enables developers to spawn and debug tasks running on networked
+VxWorks targets from a Unix host.  Already-running tasks spawned from
+the VxWorks shell can also be debugged.  _GDBN__ uses code that runs on
+both the UNIX host and on the VxWorks target.  The program
+@code{_GDBP__} is installed and executed on the UNIX host.  
+
+The remote debugging interface (RDB) routines are installed and executed
+on the VxWorks target.  These routines are included in the VxWorks library
+@code{rdb.a} and are incorporated into the system image when source-level
+debugging is enabled in the VxWorks configuration.
+
+Defining @code{INCLUDE_RDB} in the VxWorks configuration file
+@code{configAll.h} includes the RDB interface routines and spawns the
+source debugging task @code{tRdbTask} when VxWorks is booted.  For more
+information on configuring and remaking VxWorks, @cite{VxWorks
+Programmer's Guide}.
+
+Once you have included the RDB interface in your VxWorks system image
+and set your Unix execution search path to find _GDBN__, you are ready
+to run _GDBN__.  From your UNIX host, type:
+
+@smallexample
+% _GDBP__
+@end smallexample
+
+_GDBN__ will come up showing the prompt:
+
+@smallexample
+(_GDBP__)
+@end smallexample
+
+@node VxWorks connection,,,
+@subsubsection Connecting to VxWorks
+
+The _GDBN__ command @samp{target} lets you connect to a VxWorks target on the
+network.  To connect to a target whose host name is ``@code{tt}'', type:
+
+@smallexample
+(_GDBP__) target vxworks tt
+@end smallexample
+
+_GDBN__ will display a message similar to the following:
+
+@smallexample
+Attaching remote machine across net... Success!
+@end smallexample
+
+_GDBN__ will then attempt to read the symbol tables of any object
+modules loaded into the VxWorks target since it was last booted.
+_GDBN__ will locate the object files by searching the directories listed
+in the source path (@pxref{Source Path}); if it fails to find an object
+file, it will display a message such as:
+
+@smallexample
+prog.o: No such file or directory.
+@end smallexample
+
+This will cause the @samp{target} command to abort.  When this happens, you
+should add the appropriate directory to the source path and execute the
+@samp{target} command again.
+
+@node VxWorks download,,,
+@subsubsection Downloading to VxWorks
+
+If you have connected to the VxWorks target and you want to debug an
+object that has not yet been loaded, you can use the _GDBN__ @samp{load}
+command to download a file from UNIX to VxWorks incrementally.  The
+object file given as an argument to the @samp{load} command is actually
+opened twice: first by the VxWorks target in order to download the code,
+then by _GDBN__ in order to read the symbol table.  This can lead to
+problems if the current working directories on the two systems differ.
+It is simplest to set the working directory on both systems to the
+directory in which the object file resides, and then to reference the
+file by its name, without any path.  Thus, to load a program
+@samp{prog.o}, residing in @code{wherever/vw/demo/rdb}, on VxWorks type:
+
+@smallexample
+-> cd "wherever/vw/demo/rdb"
+@end smallexample
+
+On _GDBN__ type:
+
+@smallexample
+(_GDBP__) cd wherever/vw/demo/rdb 
+(_GDBP__) load prog.o
+@end smallexample
+
+_GDBN__ will display a response similar to the following:
+
+@smallexample
+Reading symbol data from wherever/vw/demo/rdb/prog.o... done.
+@end smallexample
+
+You can also use the @samp{load} command to reload an object module
+after editing and recompiling the corresponding source file.  Note that
+this will cause _GDBN__ to delete all currently-defined breakpoints,
+auto-displays, and convenience variables, and to clear the value
+history.  (This is necessary in order to preserve the integrity of
+debugger data structures that reference the target system's symbol
+table.)
+
+@node VxWorks attach,,,
+@subsubsection Running Tasks
+
+You can also attach to an existing task using the attach command as
+follows:
+
+@smallexample
+(_GDBP__) attach @var{taskId}
+@end smallexample
+
+where @var{taskId} is the VxWorks hexadecimal task ID.  The task can be running
+or suspended when you attach to it.  If running, it will be suspended at
+the time of attachment.
+
+_fi__(_VXWORKS__)
+
+@node Stopping _GDBN__,,,
+@section Stopping _GDBN__
+@cindex exiting _GDBN__
+@kindex quit
+To exit _GDBN__, use the @samp{quit} command (abbreviated @samp{q}), or type
+an end-of-file character (usually @kbd{C-d}).  
+
+@cindex interrupt
+An interrupt (often @kbd{C-c}) will not exit from _GDBN__, but rather
+will terminate the action of any _GDBN__ command that is in progress and
+return to _GDBN__ command level.  It is safe to type the interrupt
+character at any time because _GDBN__ does not allow it to take effect
+until a time when it is safe.
+
+If you've been using _GDBN__ to control an attached process or device,
+you can release it with the @samp{detach} command; @pxref{Attach}.
+
+@node Shell Commands,,,
+@section Shell Commands
+If you just need to execute occasional shell commands during your
+debugging session, there's no need to stop or suspend _GDBN__; you can
+just use the @samp{shell} command.
+
+@table @code
+@item shell @var{command string}
+@kindex shell
+@cindex shell escape
+Directs _GDBN__ to invoke an inferior shell to execute @var{command string}.
+The environment variable @code{SHELL} is used if it exists, otherwise _GDBN__
+uses @samp{/bin/sh}.
+@end table
+
+The utility @samp{make} is often needed in development environments.
+You don't have to use the @samp{shell} command for this purpose in _GDBN__:
+
+@table @code
+@item make @dots{}
+@kindex make
+@cindex calling make
+Causes _GDBN__ to execute an inferior @code{make} program with the specified
+arguments.  This is equivalent to @samp{shell make @dots{}}.
+@end table
+
+@node Commands,,,
+@chapter _GDBN__ Commands
+
+@node Command Syntax,,,
+@section Command Syntax
+A _GDBN__ command is a single line of input.  There is no limit on how long
+it can be.  It starts with a command name, which is followed by arguments
+whose meaning depends on the command name.  For example, the command
+@samp{step} accepts an argument which is the number of times to step,
+as in @samp{step 5}.  You can also use the @samp{step} command with
+no arguments.  Some command names do not allow any arguments.
+
+@cindex abbreviation
+_GDBN__ command names may always be truncated if that abbreviation is
+unambiguous.  Other possible command abbreviations are listed in the
+documentation of the individual commands.  Sometimes even ambiguous
+abbreviations are allowed; for example, @samp{s} is specially defined as
+equivalent to @samp{step} even though there are other commands whose
+names start with @samp{s}.
+
+@cindex repeating commands
+A blank line as input to _GDBN__ means to repeat the previous command.
+Certain commands will not repeat this way; these are commands for which
+unintentional repetition might cause trouble and which you are unlikely
+to want to repeat.  Certain others (@samp{list} and @samp{x}) act
+differently when repeated because that is more useful.
+
+@kindex #
+@cindex comment
+A line of input starting with @samp{#} is a comment; it does nothing.
+This is useful mainly in command files (@xref{Command Files}).
+
+@node Help,,,
+@section Getting Help
+@cindex online documentation
+@kindex help
+You can always ask _GDBN__ itself for information on its commands, using the
+command @samp{help}.  
+
+@table @code
+@item help
+Used with no arguments, @samp{help} displays a short list of named
+categories of commands:
+@smallexample
+(_GDBP__) help
+List of classes of commands:
+
+running -- Running the program
+stack -- Examining the stack
+data -- Examining data
+breakpoints -- Making program stop at certain points
+files -- Specifying and examining files
+status -- Status inquiries
+support -- Support facilities
+user-defined -- User-defined commands
+aliases -- Aliases of other commands
+obscure -- Obscure features
+
+Type "help" followed by a class name for a list of commands in that class.
+Type "help" followed by command name for full documentation.
+Command name abbreviations are allowed if unambiguous.
+(_GDBP__) 
+@end smallexample
+
+@item help @var{category}
+Using one of the general help categories as an argument, you can get a
+list of the individual commands in a category.  For example, here is the
+help display for category @samp{status}:
+@example
+(_GDBP__) help status
+Status inquiries.
+
+List of commands:
+
+show -- Generic command for showing things set with "set"
+info -- Generic command for printing status
+
+Type "help" followed by command name for full documentation.
+Command name abbreviations are allowed if unambiguous.
+(_GDBP__) 
+@end example
+
+@item help @var{command}
+With a command name as @samp{help} argument, _GDBN__ will display a
+short paragraph on how to use that command.  
+@end table
+
+In addition to @samp{help}, you can use the _GDBN__ commands @samp{info}
+and @samp{show} to inquire about the state of your program, or the state
+of _GDBN__ itself.  Both commands support many ``sub-commands'', or
+topics of inquiry; this manual introduces each of them in the
+appropriate context.  The listings under ``@code{info}'' and under
+``@code{show}'' in the Index point to all the sub-commands
+(@pxref{Index}).
+
+@table @code
+@kindex info
+@item info
+This command is for describing the state of your program; for example,
+it can list the arguments given to your program (@samp{info args}), the
+registers currently in use (@samp{info registers}), or the breakpoints
+you've set (@samp{info breakpoints}).  You can get a complete list of
+the @code{info} sub-commands with @samp{help info}.
+
+@kindex show
+@item show
+In contrast, @samp{show} is for describing the state of _GDBN__ itself.
+You can change most of the things you can @code{show}, by using the
+related command @samp{set}; for example, you can control what number
+system is used for displays with @samp{set radix}, or simply inquire
+which possibility is currently in use with @samp{show radix}.  
+
+@kindex info set
+To display all the settable parameters and their current
+values, you can use @samp{show} with no arguments; you may also use
+@samp{info set}.  Both commands produce the same display.
+@c FIXME: "info set" violates the rule that "info" is for state of
+@c FIXME...program.  Ck w/ GNU: "info set" to be called something else,
+@c FIXME...or change desc of rule---eg "state of prog and debugging session"?
+
+
+@kindex show version
+@item show version
+@c FIXME: chgd to "show version" from "info".  Verify John doing same to GDBv4.
+This @samp{show} subcommand is one of those with no corresponding
+@samp{set} subcommand.  As _GDBN__ evolves, new commands are introduced,
+and old ones may wither away.  If multiple versions of _GDBN__ are in
+use at your site, it may occasionally be useful to make sure what
+version of _GDBN__ you're running.  It is also useful to include this
+information in _GDBN__ bug-reports.  _GDBN__ announces its version
+number if you start it with no arguments; but you can make it give this
+information on request, with the @samp{show version} command.
+
+@end table
+
+@node Running,,,
+@chapter Running Programs Under _GDBN__
+
+@node Compilation,,,
+@section Compiling for Debugging
+
+In order to debug a program effectively, you need to ask for debugging
+information when you compile it.  This debugging information is stored
+in the object file; it describes the data type of each variable or
+function and the correspondence between source line numbers and
+addresses in the executable code.
+
+To request debugging information, specify the @samp{-g} option when you run
+the compiler.
+
+The Unix C compiler is unable to handle the @samp{-g} and @samp{-O} options
+together.  This means that you cannot ask for optimization if you ask for
+debugger information.
+
+The GNU C compiler supports @samp{-g} with or without @samp{-O}, making it
+possible to debug optimized code.  We recommend that you @emph{always} use
+@samp{-g} whenever you compile a program.  You may think the program is
+correct, but there's no sense in pushing your luck.
+
+Some things do not work as well with @samp{-g -O} as with just
+@samp{-g}, particularly on machines with instruction scheduling.  If in
+doubt, recompile with @samp{-g} alone, and if this fixes the problem,
+please report it as a bug (including a test case---@pxref{_GDBN__ Bugs}).
+
+Older versions of the GNU C compiler permitted a variant option
+@samp{-gg} for debugging information.  _GDBN__ no longer supports this
+format; if your GNU C compiler has this option, do not use it.
+
+@ignore
+@comment As far as I know, there are no cases in which _GDBN__ will
+@comment produce strange output in this case.  (but no promises).
+If your program includes archives made with the @code{ar} program, and
+if the object files used as input to @code{ar} were compiled without the
+@samp{-g} option and have names longer than 15 characters, _GDBN__ will get
+confused reading the program's symbol table.  No error message will be
+given, but _GDBN__ may behave strangely.  The reason for this problem is a
+deficiency in the Unix archive file format, which cannot represent file
+names longer than 15 characters.
+
+To avoid this problem, compile the archive members with the @samp{-g}
+option or use shorter file names.  Alternatively, use a version of GNU
+@code{ar} dated more recently than August 1989.
+@end ignore
+
+
+@node Starting,,,
+@section Starting your Program
+@cindex starting
+@cindex running
+@kindex run
+To start your program under _GDBN__, use the @samp{run} command.  
+_if__(_VXWORKS__)
+Except on VxWorks, the 
+_fi__(_VXWORKS__)
+_if__(!_VXWORKS__)
+The
+_fi__(!_VXWORKS__)
+program must already have been specified using the
+@samp{file} or @samp{exec-file} command, or with an argument to _GDBN__
+(@pxref{Files}).@refill
+
+On targets that support processes, @samp{run} creates an inferior
+process and makes that process run your program.  On other targets,
+@samp{run} jumps to the location it has recorded for the start of the
+program.
+
+The execution of a program is affected by certain information it
+receives from its superior.  _GDBN__ provides ways to specify this
+information, which you must do @i{before} starting the program.  (You
+can change it after starting the program, but such changes do not affect
+the program unless you start it over again.)  This information may be
+divided into four categories:
+
+@table @asis
+@item The @i{arguments.}
+You specify the arguments to give your program as the arguments of the
+@samp{run} command.  If a shell is available on your target, the shell
+is used to pass the arguments, so that you may use normal conventions
+(for example regular expression expansion or variable substitution) in
+describing the arguments.  In Unix systems, you can control which shell
+is used with the @code{SHELL} environment variable.
+
+@item The @i{environment.}
+Your program normally inherits its environment from _GDBN__, but you can
+use the _GDBN__ commands @samp{set environment} and @samp{unset
+environment} to change parts of the environment that will be given to
+the program.@refill
+
+@item The @i{working directory.}
+Your program inherits its working directory from _GDBN__.  You can set
+_GDBN__'s working directory with the @samp{cd} command in _GDBN__.
+
+@item The @i{standard input and output.}
+Your program normally uses the same device for standard input and
+standard output as _GDBN__ is using.  You can redirect input and output
+in the @code{run} command line, or you can use the @samp{tty} command to
+set a different device for your program.
+@end table
+
+When you issue the @samp{run} command, your program begins to execute
+immediately.  @xref{Stopping}, for discussion of how to arrange for your
+program to stop.
+
+Note that once your program has been started by the @samp{run} command,
+you may evaluate expressions that involve calls to functions in the
+inferior, using the @samp{print} or @samp{call} commands.  @xref{Data}.
+
+If the modification time of your symbol file has changed since the last
+time _GDBN__ read its symbols, _GDBN__ will discard its symbol table and re-read
+it.  In this process, it tries to retain your current breakpoints.
+
+@node Arguments,,,
+@section Your Program's Arguments
+
+@cindex arguments (to your program)
+The arguments to your program are specified by the arguments of the 
+@samp{run} command.  They are passed to a shell, which expands wildcard
+characters and performs redirection of I/O, and thence to the program.
+
+@samp{run} with no arguments uses the same arguments used by the previous
+@samp{run}.
+
+@kindex set args
+@table @code
+@item set args
+The command @samp{set args} can be used to specify the arguments to be used
+the next time the program is run.  If @samp{set args} has no arguments, it
+means to use no arguments the next time the program is run.  If you have
+run your program with arguments and want to run it again with no arguments,
+this is the only way to do so.
+
+@item show args
+@kindex show args
+Show the arguments to give your program when it is started.
+@end table
+
+@node Environment,,,
+@section Your Program's Environment
+
+@cindex environment (of your program)
+The @dfn{environment} consists of a set of @dfn{environment variables} and
+their values.  Environment variables conventionally record such things as
+your user name, your home directory, your terminal type, and your search
+path for programs to run.  Usually you set up environment variables with
+the shell and they are inherited by all the other programs you run.  When
+debugging, it can be useful to try running the program with different
+environments without having to start the debugger over again.
+
+@table @code
+@item show environment @var{varname}
+@kindex show environment
+Print the value of environment variable @var{varname} to be given to
+your program when it is started.
+
+@item show environment
+Print the names and values of all environment variables to be given to
+your program when it is started.
+
+@item set environment @var{varname} @var{value}
+@itemx set environment @var{varname} = @var{value}
+@kindex set environment
+Sets environment variable @var{varname} to @var{value}, for your program
+only, not for _GDBN__ itself.  @var{value} may be any string; the values of
+environment variables are just strings, and any interpretation is
+supplied by your program itself.  The @var{value} parameter is optional;
+if it is eliminated, the variable is set to a null value.
+
+For example, this command:
+
+@example
+set env USER = foo
+@end example
+
+@noindent
+tells the program, when subsequently run, to assume it is being run
+on behalf of the user named @samp{foo}.
+
+@item unset environment @var{varname}
+@kindex unset environment
+Remove variable @var{varname} from the environment to be passed to your
+program.  This is different from @samp{set env @var{varname}@ =};
+@samp{unset environment} removes the variable from the environment,
+rather than assigning it an empty value.  This command can be
+abbreviated @samp{d e}.
+@end table
+
+@node Working Directory,,,
+@section Your Program's Working Directory
+
+@cindex working directory (of your program)
+Each time you start your program with @samp{run}, it inherits its
+working directory from the current working directory of _GDBN__.  _GDBN__'s
+working directory is initially whatever it inherited from its parent
+process (typically the shell), but you can specify a new working
+directory in _GDBN__ with the @samp{cd} command.
+
+The _GDBN__ working directory also serves as a default for the commands
+that specify files for _GDBN__ to operate on.  @xref{Files}.
+
+@table @code
+@item cd @var{directory}
+@kindex cd
+Set _GDBN__'s working directory to @var{directory}.
+
+@item pwd
+@kindex pwd
+Print _GDBN__'s working directory.
+@end table
+
+@node Input/Output,,,
+@section Your Program's Input and Output
+
+@cindex redirection
+@cindex i/o
+@cindex terminal
+@cindex controlling terminal
+By default, the program you run under _GDBN__ does input and output to the same
+terminal that _GDBN__ uses.
+
+You can redirect the program's input and/or output using @samp{sh}-style
+redirection commands in the @samp{run} command.  For example,
+
+_0__@example
+run > outfile
+_1__@end example
+
+@noindent
+starts the program, diverting its output to the file @file{outfile}.
+
+@kindex tty
+Another way to specify where the program should do input and output is
+with the @samp{tty} command.  This command accepts a file name as
+argument, and causes this file to be the default for future @samp{run}
+commands.  It also resets the controlling terminal for the child
+process, for future @samp{run} commands.  For example,
+
+@example
+tty /dev/ttyb
+@end example
+
+@noindent
+directs that processes started with subsequent @samp{run} commands
+default to do input and output on the terminal @file{/dev/ttyb} and have
+that as their controlling terminal.
+
+An explicit redirection in @samp{run} overrides the @samp{tty} command's
+effect on input/output redirection, but not its effect on the
+controlling terminal.
+
+When you use the @samp{tty} command or redirect input in the @samp{run}
+command, only the @emph{input for your program} is affected.  The input
+for _GDBN__ still comes from your terminal.
+
+@node Attach,,,
+@section Debugging an Already-Running Process
+@kindex attach
+@cindex attach
+
+@table @code
+@item attach @var{process--id}
+This command attaches to a running process, if your currently selected
+target supports processes.  (@samp{info files} will show your active
+targets).  The command takes as argument a process ID.
+
+You specify a process ID to debug an already-running process that was
+started outside of _GDBN__.  (The usual way to find out the process-id of
+a Unix process is with the @code{ps} utility, or with the @code{jobs -l}
+shell command.)  In this case, you must have permission to send the
+process a signal, and it must have the same effective user ID as the
+_GDBN__ process.
+@end table
+
+When using @samp{attach}, you should first use the @samp{file} command
+to specify the program running in the process and load its symbol table.
+
+The first thing _GDBN__ does after arranging to debug the specified
+process is to stop it.  You can examine and modify an attached process
+with all the _GDBN__ commands that ordinarily available when you start
+processes with @samp{run}.  You can insert breakpoints; you can step and
+continue; you can modify storage.  If you would rather the process
+continue running, you may use the @samp{continue} command after
+attaching _GDBN__ to the process.
+
+@kindex detach
+When you have finished debugging the attached process, you can use the
+@samp{detach} command to release it from _GDBN__'s control.  Detaching
+the process continues its execution.  After the @samp{detach} command,
+that process and _GDBN__ become completely independent once more, and you
+are ready to @samp{attach} another process or start one with @samp{run}.
+
+If you exit _GDBN__ or use the @samp{run} command while you have an attached
+process, you kill that process.  By default, you will be asked for
+confirmation if you try to do either of these things; you can control
+whether or not this happens by using the @samp{set caution} command
+(@pxref{Messages/Warnings}).
+
+@node Kill Process,,,
+@section Killing the Child Process
+
+@table @code
+@item kill
+@kindex kill
+Kill the child process in which your program is running under _GDBN__.
+@end table
+
+This command is useful if you wish to debug a core dump instead of a
+running process.  _GDBN__ ignores any core dump file while your program
+is running.
+
+On some operating systems, you can't execute your program in another
+process while breakpoints are active inside _GDBN__.  You can use the
+@samp{kill} command in this situation to permit running the program
+outside the debugger.
+
+The @samp{kill} command is also useful if you wish to recompile and
+relink the program, since on many systems it is impossible to modify an
+executable file which is running in a process.  In this case, when you
+next type @samp{run}, _GDBN__ will notice that the file has changed, and
+will re-read the symbol table (while trying to preserve your current
+breakpoint settings).
+
+@node Stopping,,,
+@chapter Stopping and Continuing
+
+When you run a program normally, it runs until it terminates.  The
+principal purpose of using a debugger is so that you can stop it before
+that point; or so that if the program runs into trouble you can
+investigate and find out why.
+
+@node Breakpoints,,,
+@section Breakpoints
+
+@cindex breakpoints
+A @dfn{breakpoint} makes your program stop whenever a certain point in the
+program is reached.  You set breakpoints explicitly with _GDBN__ commands,
+specifying the place where the program should stop by line number, function
+name or exact address in the program.  You can add various other conditions
+to control whether the program will stop.
+
+Each breakpoint is assigned a number when it is created; these numbers are
+successive integers starting with 1.  In many of the commands for controlling
+various features of breakpoints you use the breakpoint number to say which
+breakpoint you want to change.  Each breakpoint may be @dfn{enabled} or
+@dfn{disabled}; if disabled, it has no effect on the program until you
+enable it again.
+
+@node Set Breaks,,,
+@subsection Setting Breakpoints
+
+@kindex break
+@kindex watch
+Breakpoints are set with the @samp{break} command (abbreviated @samp{b}).
+
+You have several ways to say where the breakpoint should go.
+
+@table @code
+@item break @var{function}
+Set a breakpoint at entry to function @var{function}.
+
+@item break @var{+offset}
+@itemx break @var{-offset}
+Set a breakpoint some number of lines forward or back from the position
+at which execution stopped in the currently selected frame.
+
+@item break @var{linenum}
+Set a breakpoint at line @var{linenum} in the current source file.
+That file is the last file whose source text was printed.  This
+breakpoint will stop the program just before it executes any of the
+code on that line.
+
+@item break @var{filename}:@var{linenum}
+Set a breakpoint at line @var{linenum} in source file @var{filename}.
+
+@item break @var{filename}:@var{function}
+Set a breakpoint at entry to function @var{function} found in file
+@var{filename}.  Specifying a file name as well as a function name is
+superfluous except when multiple files contain similarly named
+functions.
+
+@item break *@var{address}
+Set a breakpoint at address @var{address}.  You can use this to set
+breakpoints in parts of the program which do not have debugging
+information or source files.
+
+@item break
+Set a breakpoint at the next instruction to be executed in the selected
+stack frame (@pxref{Stack}).  In any selected frame but the innermost,
+this will cause the program to stop as soon as control returns to that
+frame.  This is equivalent to a @samp{finish} command in the frame
+inside the selected frame.  If this is done in the innermost frame, _GDBN__
+will stop the next time it reaches the current location; this may be
+useful inside of loops.
+
+_GDBN__ normally ignores breakpoints when it resumes execution, until at
+least one instruction has been executed.  If it did not do this, you
+would be unable to proceed past a breakpoint without first disabling the
+breakpoint.  This rule applies whether or not the breakpoint already
+existed when the program stopped.
+
+@item break @dots{} if @var{cond}
+Set a breakpoint with condition @var{cond}; evaluate the expression
+@var{cond} each time the breakpoint is reached, and stop only if the
+value is nonzero.  @samp{@dots{}} stands for one of the possible
+arguments described above (or no argument) specifying where to break.
+@xref{Conditions}, for more information on breakpoint conditions.
+
+@item tbreak @var{args}
+@kindex tbreak
+Set a breakpoint enabled only for one stop.  @var{args} are the
+same as in the @samp{break} command, and the breakpoint is set in the same
+way, but the breakpoint is automatically disabled the first time it
+is hit.  @xref{Disabling}.
+
+@item rbreak @var{regex}
+@kindex rbreak
+Set a breakpoint on all functions matching @var{regex}.  This is
+useful for setting breakpoints on overloaded functions that are not
+members of any special classes.  This command sets an unconditional
+breakpoint on all matches, printing a list of all breakpoints it set.
+Once these breakpoints are set, they are treated just like the
+breakpoints set with the @samp{break} command.  They can be deleted,
+disabled, made conditional, etc., in the standard ways.
+
+@kindex info breakpoints
+@kindex $_
+@item info breakpoints
+The command @samp{info breakpoints} prints a list of all breakpoints set
+and not deleted, showing their numbers, where in the program they are,
+and any special features in use for them.  Disabled breakpoints are
+included in the list, but marked as disabled.  @samp{info break} with a
+breakpoint number as argument lists only that breakpoint.  The
+convenience variable @code{$_} and the default examining-address for the
+@samp{x} command are set to the address of the last breakpoint listed
+(@pxref{Memory}).
+@end table
+
+_GDBN__ allows you to set any number of breakpoints at the same place in the
+program.  There is nothing silly or meaningless about this.  When the
+breakpoints are conditional, this is even useful (@pxref{Conditions}).
+
+@node Set Watchpoints,,,
+@subsection Setting Watchpoints
+@cindex watchpoints
+A @dfn{watchpoint} is a special breakpoint that stops your program when
+the value of an expression changes.  You can use a watchpoint to stop
+execution whenever the value of an expression changes, without having to
+predict a particular place in the inferior process where this may
+happen.  Aside from the different syntax in setting a watchpoint, it is
+managed exactly like any other breakpoint and is enabled, disabled, and
+deleted using exactly the same commands.
+
+Watchpoints currently execute two orders of magnitude more slowly than
+other breakpoints, but this can well be worth it to catch errors where
+you have no clue what part of your program is the culprit.  Some
+processors provide special hardware to implement this feature; future
+releases of _GDBN__ will use such hardware if it is available.
+
+@table @code
+@kindex watch 
+@item watch @var{expr}
+Set a watchpoint for an expression.
+
+@kindex info watch
+@item info watch
+This command prints a list of watchpoints. 
+@end table
+
+@node Exception Handling,,,
+@subsection Breakpoints and Exceptions
+@cindex exception handlers
+
+Some languages, such as GNU C++, implement exception handling.  _GDBN__
+can be used to examine what caused the program to raise an exception
+and to list the exceptions the program is prepared to handle at a
+given point in time.
+
+@table @code
+@item catch @var{exceptions}
+@kindex catch
+
+Breakpoints can be set at active exception handlers by using the
+@samp{catch} command.  @var{exceptions} is a list of names of exceptions
+to catch.
+@end table
+
+You can use @samp{info catch} to list active exception handlers;
+@pxref{Frame Info}.
+
+There are currently some limitations to exception handling in _GDBN__.
+These will be corrected in a future release.
+
+@itemize @bullet
+@item
+If you call a function interactively, _GDBN__ will normally return
+control to you when the function has finished executing.  If the call
+raises an exception, however, the call may bypass the mechanism that
+returns control to the user and cause the program to simply continue
+running until it hits a breakpoint, catches a signal that _GDBN__ is
+listening for, or exits.
+@item
+You cannot raise an exception interactively.
+@item
+You cannot interactively install an exception handler.
+@end itemize
+
+@cindex raise exceptions
+Sometimes @samp{catch} is not the best way to debug exception handling:
+if you need to know exactly where an exception is raised, it's better to
+stop @emph{before} the exception handler is called, since that way you
+can see the stack before any unwinding takes place.  
+
+To stop just before an exception handler is called, you need some
+knowledge of the implementation.  In the case of GNU C++ exception are
+raised by calling a library function named @code{__raise_exception}
+which has the following ANSI C interface:
+
+@example
+    /* ADDR is where the exception identifier is stored.
+       ID is the exception identifier.  */
+    void __raise_exception (void **addr, void *id);
+@end example
+
+@noindent
+To make the debugger catch all exceptions before any stack
+unwinding takes place, set a breakpoint on @code{__raise_exception}
+(@pxref{Breakpoints}).  If you set a breakpoint in an exception handler
+instead, it may not be easy to find out where the exception was raised.
+
+With a conditional breakpoint (@xref{Conditions}) that depends on the
+value of @code{id}, you can cause the debugger to stop only when a
+specific exception is raised.  Multiple conditional breakpoints can be
+used to stop the program when any of a number of exceptions are raised.
+
+@node Delete Breaks,,,
+@subsection Deleting Breakpoints
+
+@cindex clearing breakpoints, watchpoints
+@cindex deleting breakpoints, watchpoints
+It is often necessary to eliminate a breakpoint once it has done its job
+and you no longer want the program to stop there.  This is called
+@dfn{deleting} the breakpoint.  A breakpoint that has been deleted no
+longer exists in any sense; it is forgotten.
+
+With the @samp{clear} command you can delete breakpoints according to where
+they are in the program.  With the @samp{delete} command you can delete
+individual breakpoints by specifying their breakpoint numbers.
+
+It is not necessary to delete a breakpoint to proceed past it.  _GDBN__
+automatically ignores breakpoints on the first instruction to be executed
+when you continue execution without changing the execution address.
+
+@table @code
+@item clear
+@kindex clear
+Delete any breakpoints at the next instruction to be executed in the
+selected stack frame (@pxref{Selection}).  When the innermost frame
+is selected, this is a good way to delete a breakpoint that the program
+just stopped at.
+
+@item clear @var{function}
+@itemx clear @var{filename}:@var{function}
+Delete any breakpoints set at entry to the function @var{function}.
+
+@item clear @var{linenum}
+@itemx clear @var{filename}:@var{linenum}
+Delete any breakpoints set at or within the code of the specified line.
+
+@item delete breakpoints @var{bnums}@dots{}
+@itemx delete @var{bnums}@dots{}
+@itemx delete
+@kindex delete breakpoints
+@kindex delete
+Delete the breakpoints of the numbers specified as arguments.  If no
+argument is specified, delete all breakpoints.
+@end table
+
+@node Disabling,,,
+@subsection Disabling Breakpoints
+
+@cindex disabled breakpoints
+@cindex enabled breakpoints
+Rather than deleting a breakpoint, you might prefer to @dfn{disable} it.
+This makes the breakpoint inoperative as if it had been deleted, but
+remembers the information on the breakpoint so that you can @dfn{enable}
+it again later.
+
+You disable and enable breakpoints with the @samp{enable} and
+@samp{disable} commands, optionally specifying one or more breakpoint
+numbers as arguments.  Use @samp{info break} to print a list of
+breakpoints if you don't know which breakpoint numbers to use.
+
+A breakpoint can have any of four different states of enablement:
+
+@itemize @bullet
+@item
+Enabled.  The breakpoint will stop the program.  A breakpoint made
+with the @samp{break} command starts out in this state.
+@item
+Disabled.  The breakpoint has no effect on the program.
+@item
+Enabled once.  The breakpoint will stop the program, but
+when it does so it will become disabled.  A breakpoint made
+with the @samp{tbreak} command starts out in this state.
+@item
+Enabled for deletion.  The breakpoint will stop the program, but
+immediately after it does so it will be deleted permanently.
+@end itemize
+
+You can use the following commands to enable or disable a breakpoint:
+
+@table @code
+@item disable breakpoints @var{bnums}@dots{}
+@itemx disable @var{bnums}@dots{}
+@itemx disable
+@kindex disable breakpoints
+@kindex disable
+Disable the specified breakpoints---or all breakpoints, if none are
+listed.  A disabled breakpoint has no effect but is not forgotten.  All
+options such as ignore-counts, conditions and commands are remembered in
+case the breakpoint is enabled again later.
+
+@item enable breakpoints @var{bnums}@dots{}
+@itemx enable @var{bnums}@dots{}
+@itemx enable
+@kindex enable breakpoints
+@kindex enable
+Enable the specified breakpoints (or all defined breakpoints).  They
+become effective once again in stopping the program, until you specify
+otherwise.
+
+@item enable breakpoints once @var{bnums}@dots{}
+@itemx enable once @var{bnums}@dots{}
+Enable the specified breakpoints temporarily.  Each will be disabled
+again the next time it stops the program (unless you have used one of
+these commands to specify a different state before that time comes).
+
+@item enable breakpoints delete @var{bnums}@dots{}
+@itemx enable delete @var{bnums}@dots{}
+Enable the specified breakpoints to work once and then die.  Each of
+the breakpoints will be deleted the next time it stops the program
+(unless you have used one of these commands to specify a different
+state before that time comes).
+@end table
+
+Save for a breakpoint set with @samp{tbreak} (@pxref{Set Breaks}),
+breakpoints that you set initially enabled; subsequently, they become
+disabled or enabled only when you use one of the commands above.  (The
+command @samp{until} can set and delete a breakpoint of its own, but it
+will not change the state of your other breakpoints).
+
+@node Conditions,,,
+@subsection Break Conditions
+@cindex conditional breakpoints
+@cindex breakpoint conditions
+
+The simplest sort of breakpoint breaks every time the program reaches a
+specified place.  You can also specify a @dfn{condition} for a
+breakpoint.  A condition is just a boolean expression in your
+programming language.  (@xref{Expressions}).  A breakpoint with a
+condition evaluates the expression each time the program reaches it, and
+the program stops only if the condition is true.
+
+Break conditions may have side effects, and may even call functions in your
+program.  These may sound like strange things to do, but their effects are
+completely predictable unless there is another enabled breakpoint at the
+same address.  (In that case, _GDBN__ might see the other breakpoint first and
+stop the program without checking the condition of this one.)  Note that
+breakpoint commands are usually more convenient and flexible for the
+purpose of performing side effects when a breakpoint is reached
+(@pxref{Break Commands}).
+
+Break conditions can be specified when a breakpoint is set, by using
+@samp{if} in the arguments to the @samp{break} command.  @xref{Set Breaks}.
+They can also be changed at any time with the @samp{condition} command:
+
+@table @code
+@item condition @var{bnum} @var{expression}
+@kindex condition
+Specify @var{expression} as the break condition for breakpoint number
+@var{bnum}.  From now on, this breakpoint will stop the program only if
+the value of @var{expression} is true (nonzero, in C).  @var{expression}
+is not evaluated at the time the @samp{condition} command is given.
+When you call @samp{condition}, the expression you specify is checked
+immediately for syntactic correctness, and to determine whether symbols
+in it have referents in the context of your breakpoint.
+@xref{Expressions}.
+
+@item condition @var{bnum}
+Remove the condition from breakpoint number @var{bnum}.  It becomes
+an ordinary unconditional breakpoint.
+@end table
+
+@cindex ignore count (of breakpoint)
+A special case of a breakpoint condition is to stop only when the
+breakpoint has been reached a certain number of times.  This is so
+useful that there is a special way to do it, using the @dfn{ignore
+count} of the breakpoint.  Every breakpoint has an ignore count, which
+is an integer.  Most of the time, the ignore count is zero, and
+therefore has no effect.  But if the program reaches a breakpoint whose
+ignore count is positive, then instead of stopping, it just decrements
+the ignore count by one and continues.  As a result, if the ignore count
+value is @var{n}, the breakpoint will not stop the next @var{n} times it
+is reached.
+
+@table @code
+@item ignore @var{bnum} @var{count}
+@kindex ignore
+Set the ignore count of breakpoint number @var{bnum} to @var{count}.
+The next @var{count} times the breakpoint is reached, your program's
+execution will not stop; other than to decrement the ignore count, _GDBN__
+takes no action.
+
+To make the breakpoint stop the next time it is reached, specify
+a count of zero.
+
+@item continue @var{count}
+@itemx cont @var{count}
+@itemx c @var{count}
+@itemx fg @var{count}
+@kindex cont @var{count}
+@kindex continue @var{count}
+Continue execution of the program, setting the ignore count of the
+breakpoint that the program stopped at to @var{count} minus one.
+Thus, the program will not stop at this breakpoint until the
+@var{count}'th time it is reached.
+
+An argument to this command is meaningful only when the program stopped
+due to a breakpoint.  At other times, the argument to @samp{cont} is
+ignored.
+
+The synonym @samp{fg} is provided purely for convenience, and has
+exactly the same behavior as other forms of the command.
+@end table
+
+If a breakpoint has a positive ignore count and a condition, the condition
+is not checked.  Once the ignore count reaches zero, the condition will
+be checked.
+
+Note that you could achieve the effect of the ignore count with a
+condition such as _0__@w{@samp{$foo-- <= 0}}_1__ using a debugger convenience
+variable that is decremented each time.  @xref{Convenience Vars}.
+
+@node Break Commands,,,
+@subsection Commands Executed on Breaking
+
+@cindex breakpoint commands
+You can give any breakpoint a series of commands to execute when the
+program stops due to that breakpoint.  For example, you might want to
+print the values of certain expressions, or enable other breakpoints.
+
+@table @code
+@item commands @var{bnum}
+@kindex commands
+Specify a list of commands for breakpoint number @var{bnum}.  The commands
+themselves appear on the following lines.  Type a line containing just
+@samp{end} to terminate the commands.
+
+To remove all commands from a breakpoint, use the command
+@samp{commands} and follow it immediately by @samp{end}; that is, give
+no commands.
+
+With no arguments, @samp{commands} refers to the last breakpoint set
+(not to the breakpoint most recently encountered).
+@end table
+
+You can use breakpoint commands to start the program up again.  Simply
+use the @samp{cont} command, or @samp{step}, or any other command to
+resume execution.  However, if you do this, any further commands in the
+same breakpoint's command list are ignored.  When the program stops
+again, _GDBN__ will act according to the cause of that stop.
+
+@kindex silent
+If the first command specified is @samp{silent}, the usual message about
+stopping at a breakpoint is not printed.  This may be desirable for
+breakpoints that are to print a specific message and then continue.
+If the remaining commands too print nothing, you will see no sign that
+the breakpoint was reached at all.  @samp{silent} is not really a command;
+it is meaningful only at the beginning of the commands for a breakpoint.
+
+The commands @samp{echo} and @samp{output} that allow you to print precisely
+controlled output are often useful in silent breakpoints.  @xref{Output}.
+
+For example, here is how you could use breakpoint commands to print the
+value of @code{x} at entry to @code{foo} whenever @code{x} is positive.
+
+_0__@example
+break foo if x>0
+commands
+silent
+echo x is\040
+output x
+echo \n
+cont
+end
+_1__@end example
+
+One application for breakpoint commands is to correct one bug so you can
+test another.  Put a breakpoint just after the erroneous line of code, give
+it a condition to detect the case in which something erroneous has been
+done, and give it commands to assign correct values to any variables that
+need them.  End with the @samp{cont} command so that the program does not
+stop, and start with the @samp{silent} command so that no output is
+produced.  Here is an example:
+
+@example
+break 403
+commands
+silent
+set x = y + 4
+cont
+end
+@end example
+
+One deficiency in the operation of automatically continuing breakpoints
+under Unix appears when your program uses raw mode for the terminal.
+_GDBN__ switches back to its own terminal modes (not raw) before executing
+commands, and then must switch back to raw mode when your program is
+continued.  This causes any pending terminal input to be lost. 
+In the GNU system, this will be fixed by changing the behavior of
+terminal modes.
+
+Under Unix, when you have this problem, you might be able to get around
+it by putting your actions into the breakpoint condition instead of
+commands.  For example
+
+@example
+condition 5  (x = y + 4), 0
+@end example
+
+@noindent
+specifies a condition expression (@xref{Expressions}) that will change
+@code{x} as needed, then always have the value 0 so the program will not
+stop.  Loss of input is avoided here because break conditions are
+evaluated without changing the terminal modes.  When you want to have
+nontrivial conditions for performing the side effects, the operators
+@samp{&&}, @samp{||} and @samp{?@dots{}:} may be useful.
+
+@node Error in Breakpoints,,,
+@subsection ``Cannot Insert Breakpoints''
+
+@c FIXME: "cannot insert breakpoints" error, v unclear.  
+@c        Q in pending mail to Gilmore. ---pesch@cygnus.com, 26mar91
+Under some operating systems, breakpoints cannot be used in a program if
+any other process is running that program.  In this situation,
+attempting to run or continue a program with a breakpoint will cause _GDBN__
+to stop the other process.
+
+When this happens, you have three ways to proceed:
+
+@enumerate
+@item
+Remove or disable the breakpoints, then continue.
+
+@item
+Suspend _GDBN__, and copy the file containing the program to a new name.
+Resume _GDBN__ and use the @samp{exec-file} command to specify that _GDBN__
+should run the program under that name.  Then start the program again.
+
+@item
+Relink the program so that the text segment is nonsharable, using the
+linker option @samp{-N}.  The operating system limitation may not apply
+to nonsharable executables.
+@end enumerate
+
+@node Stepping,,,
+@section Stepping
+
+@cindex stepping
+@dfn{Stepping} means setting your program in motion for a limited time, so
+that control will return automatically to _GDBN__ after one line of
+code or one machine instruction.  Breakpoints are active during stepping
+and the program will stop for them even if it has not gone as far as the
+stepping command specifies.
+
+@table @code
+@item step
+@kindex step
+Continue running the program until control reaches a different source
+line, then stop it and return control to the debugger.  This command is
+abbreviated @samp{s}.
+
+This command may be given when control is within a function for which
+there is no debugging information.  In that case, execution will proceed
+until control reaches a different function, or is about to return from
+this function.  
+
+@item step @var{count}
+Continue running as in @samp{step}, but do so @var{count} times.  If a
+breakpoint is reached or a signal not related to stepping occurs before
+@var{count} steps, stepping stops right away.
+
+@item next
+@kindex next
+Continue to the next source line in the current stack frame.  Similar to
+@samp{step}, but any function calls appearing within the line of code
+are executed without stopping.  Execution stops when control reaches a
+different line of code at the stack level which was executing when the
+@samp{next} command was given.  This command is abbreviated @samp{n}.
+
+An argument is a repeat count, as in @samp{step}.
+
+@samp{next} within a function that lacks debugging information acts as does
+@samp{step}, but any function calls appearing within the code of the
+function are executed without stopping.
+
+@item finish
+@kindex finish
+Continue running until just after the selected stack frame returns (or
+until there is some other reason to stop, such as a fatal signal or a
+breakpoint).  Print value returned by the selected stack frame (if any).
+
+Contrast this with the @samp{return} command (@pxref{Returning}).
+
+@item until
+@kindex until
+Continue running until a source line past the current line, in the
+current stack frame, is reached.  This command is used to avoid single
+stepping through a loop more than once.  It is like the @samp{next}
+command, except that when @samp{until} encounters a jump, it
+automatically continues execution until the program counter is greater
+than the address of the jump.
+
+This means that when you reach the end of a loop after single stepping
+though it, @samp{until} will cause the program to continue execution
+until the loop is exited.  In contrast, a @samp{next} command at the end
+of a loop will simply step back to the beginning of the loop, which
+would force you to step through the next iteration.
+
+@samp{until} always stops the program if it attempts to exit the current
+stack frame.
+
+@samp{until} may produce somewhat counterintuitive results if the order
+of the source lines does not match the actual order of execution.  For
+example, in a typical C @code{for}-loop, the third expression in the
+@code{for}-statement (the loop-step expression) is executed after the
+statements in the body of the loop, but is written before them.
+Therefore, the @samp{until} command would appear to step back to the
+beginning of the loop when it advances to this expression.  However, it
+has not really done so, not in terms of the actual machine code.
+
+@samp{until} with no argument works by means of single
+instruction stepping, and hence is slower than @samp{until} with an
+argument.
+
+@item until @var{location}
+Continue running the program until either the specified location is
+reached, or the current (innermost) stack frame returns.  @var{location}
+is any of the forms of argument acceptable to @samp{break} (@pxref{Set
+Breaks}).  This form of the command uses breakpoints, and hence is
+quicker than @samp{until} without an argument.
+
+@item stepi
+@itemx si
+@kindex stepi
+@kindex si
+Execute one machine instruction, then stop and return to the debugger.
+
+It is often useful to do @samp{display/i $pc} when stepping by machine
+instructions.  This will cause the next instruction to be executed to
+be displayed automatically at each stop.  @xref{Auto Display}.
+
+An argument is a repeat count, as in @samp{step}.
+
+@item nexti
+@itemx ni
+@kindex nexti
+@kindex ni
+Execute one machine instruction, but if it is a function call,
+proceed until the function returns.
+
+An argument is a repeat count, as in @samp{next}.
+@end table
+
+A typical technique for using stepping is to put a breakpoint
+(@pxref{Breakpoints}) at the beginning of the function or the section of
+the program in which a problem is believed to lie, run the program until
+it stops at that breakpoint, and then step through the suspect area,
+examining the variables that are interesting, until you see the problem
+happen.
+
+The @samp{cont} command can be used after stepping to resume execution
+until the next breakpoint or signal.
+
+@node Continuing,,,
+@section Continuing
+
+After your program stops, most likely you will want it to run some more if
+the bug you are looking for has not happened yet.
+
+@table @code
+@item continue
+@item cont
+@kindex cont
+@kindex continue
+Continue running the program at the place where it stopped.
+@end table
+
+If the program stopped at a breakpoint, the place to continue running
+is the address of the breakpoint.  You might expect that continuing would
+just stop at the same breakpoint immediately.  In fact, @samp{cont}
+takes special care to prevent that from happening.  You do not need
+to delete the breakpoint to proceed through it after stopping at it.
+You can, however, specify an ignore-count for the breakpoint that the
+program stopped at, by means of an argument to the @samp{cont} command.
+@xref{Conditions}.
+
+If the program stopped because of a signal other than @code{SIGINT} or
+@code{SIGTRAP}, continuing will cause the program to see that signal.
+You may not want this to happen.  For example, if the program stopped
+due to some sort of memory reference error, you might store correct
+values into the erroneous variables and continue, hoping to see more
+execution; but the program would probably terminate immediately as
+a result of the fatal signal once it sees the signal.  To prevent this,
+you can continue with @samp{signal 0}.  @xref{Signaling}.  You can
+also act in advance to control what signals your program will see, using
+the @samp{handle} command (@pxref{Signals}). 
+
+@node Signals,,,
+@section Signals
+@cindex signals
+
+A signal is an asynchronous event that can happen in a program.  The
+operating system defines the possible kinds of signals, and gives each
+kind a name and a number.  For example, in Unix @code{SIGINT} is the
+signal a program gets when you type @kbd{Ctrl-c}; @code{SIGSEGV} is the
+signal a program gets from referencing a place in memory far away from
+all the areas in use; @code{SIGALRM} occurs when the alarm clock timer
+goes off (which happens only if the program has requested an alarm).
+
+@cindex fatal signals
+Some signals, including @code{SIGALRM}, are a normal part of the
+functioning of the program.  Others, such as @code{SIGSEGV}, indicate
+errors; these signals are @dfn{fatal} (kill the program immediately) if the
+program has not specified in advance some other way to handle the signal.
+@code{SIGINT} does not indicate an error in the program, but it is normally
+fatal so it can carry out the purpose of @kbd{Ctrl-c}: to kill the program.
+
+_GDBN__ has the ability to detect any occurrence of a signal in the program
+running under _GDBN__'s control.  You can tell _GDBN__ in advance what to do for
+each kind of signal.
+
+@cindex handling signals
+Normally, _GDBN__ is set up to ignore non-erroneous signals like @code{SIGALRM}
+(so as not to interfere with their role in the functioning of the program)
+but to stop the program immediately whenever an error signal happens.
+You can change these settings with the @samp{handle} command.
+
+@table @code
+@item info signal
+@kindex info signal
+Print a table of all the kinds of signals and how _GDBN__ has been told to
+handle each one.  You can use this to see the signal numbers of all
+the defined types of signals.
+
+@item handle @var{signal} @var{keywords}@dots{}
+@kindex handle
+Change the way _GDBN__ handles signal @var{signal}.  @var{signal} can be the
+number of a signal or its name (with or without the @samp{SIG} at the
+beginning).  The @var{keywords} say what change to make.
+@end table
+
+@group
+The keywords allowed by the @samp{handle} command can be abbreviated.
+Their full names are:
+
+@table @code
+@item nostop
+_GDBN__ should not stop the program when this signal happens.  It may
+still print a message telling you that the signal has come in.
+
+@item stop
+_GDBN__ should stop the program when this signal happens.  This implies
+the @samp{print} keyword as well.
+
+@item print
+_GDBN__ should print a message when this signal happens.
+
+@item noprint
+_GDBN__ should not mention the occurrence of the signal at all.  This
+implies the @samp{nostop} keyword as well.
+
+@item pass
+_GDBN__ should allow the program to see this signal; the program will be
+able to handle the signal, or may be terminated if the signal is fatal
+and not handled.
+
+@item nopass
+_GDBN__ should not allow the program to see this signal.
+@end table
+@end group
+
+When a signal has been set to stop the program, the program cannot see the
+signal until you continue.  It will see the signal then, if @samp{pass} is
+in effect for the signal in question @i{at that time}.  In other words,
+after _GDBN__ reports a signal, you can use the @samp{handle} command with
+@samp{pass} or @samp{nopass} to control whether that signal will be seen by
+the program when you later continue it.
+
+You can also use the @samp{signal} command to prevent the program from
+seeing a signal, or cause it to see a signal it normally would not see,
+or to give it any signal at any time.  @xref{Signaling}.
+
+
+@node Stack,,,
+@chapter Examining the Stack
+
+When your program has stopped, the first thing you need to know is where it
+stopped and how it got there.
+
+@cindex call stack
+Each time your program performs a function call, the information about
+where in the program the call was made from is saved in a block of data
+called a @dfn{stack frame}.  The frame also contains the arguments of the
+call and the local variables of the function that was called.  All the
+stack frames are allocated in a region of memory called the @dfn{call
+stack}.
+
+When your program stops, the _GDBN__ commands for examining the stack allow you
+to see all of this information.
+
+One of the stack frames is @dfn{selected} by _GDBN__ and many _GDBN__ commands
+refer implicitly to the selected frame.  In particular, whenever you ask
+_GDBN__ for the value of a variable in the program, the value is found in the
+selected frame.  There are special _GDBN__ commands to select whichever frame
+you are interested in.
+
+When the program stops, _GDBN__ automatically selects the currently executing
+frame and describes it briefly as the @samp{frame} command does
+(@pxref{Frame Info, Info}).
+
+@node Frames,,,
+@section Stack Frames
+
+@cindex frame
+@cindex stack frame
+The call stack is divided up into contiguous pieces called @dfn{stack
+frames}, or @dfn{frames} for short; each frame is the data associated
+with one call to one function.  The frame contains the arguments given
+to the function, the function's local variables, and the address at
+which the function is executing.
+
+@cindex initial frame
+@cindex outermost frame
+@cindex innermost frame
+When your program is started, the stack has only one frame, that of the
+function @code{main}.  This is called the @dfn{initial} frame or the
+@dfn{outermost} frame.  Each time a function is called, a new frame is
+made.  Each time a function returns, the frame for that function invocation
+is eliminated.  If a function is recursive, there can be many frames for
+the same function.  The frame for the function in which execution is
+actually occurring is called the @dfn{innermost} frame.  This is the most
+recently created of all the stack frames that still exist.
+
+@cindex frame pointer
+Inside your program, stack frames are identified by their addresses.  A
+stack frame consists of many bytes, each of which has its own address; each
+kind of computer has a convention for choosing one of those bytes whose
+address serves as the address of the frame.  Usually this address is kept
+in a register called the @dfn{frame pointer register} while execution is
+going on in that frame.
+
+@cindex frame number
+_GDBN__ assigns numbers to all existing stack frames, starting with
+@code{0} for the innermost frame, @code{1} for the frame that called it,
+and so on upward.  These numbers do not really exist in your program;
+they are assigned by _GDBN__ to give you a way of designating stack
+frames in _GDBN__ commands.
+
+@cindex selected frame
+Many _GDBN__ commands refer implicitly to one stack frame, called the
+@dfn{selected} stack frame.  You can select any frame using one set of
+_GDBN__ commands, and then other commands will operate on that frame.  When
+your program stops, _GDBN__ automatically selects the innermost frame.
+
+@cindex frameless execution
+Some compilers allow functions to be compiled so that they operate
+without stack frames.  (For example, the _GCC__ option
+@samp{-fomit-frame-pointer} will generate functions without a frame.)
+This is occasionally done with heavily used library functions to save
+the frame setup time.  _GDBN__ has limited facilities for dealing with
+these function invocations; if the innermost function invocation has no
+stack frame, _GDBN__ will give it a virtual stack frame of 0 and
+correctly allow tracing of the function call chain.  Results are
+undefined if a function invocation besides the innermost one is
+frameless.
+
+@node Backtrace,,,
+@section Backtraces
+
+A backtrace is a summary of how the program got where it is.  It shows one
+line per frame, for many frames, starting with the currently executing
+frame (frame zero), followed by its caller (frame one), and on up the
+stack.
+
+@table @code
+@item backtrace
+@itemx bt
+@kindex backtrace
+@kindex bt
+Print a backtrace of the entire stack: one line per frame for all
+frames in the stack.
+
+You can stop the backtrace at any time by typing the system interrupt
+character, normally @kbd{Control-C}.
+
+@item backtrace @var{n}
+@itemx bt @var{n}
+Similar, but print only the innermost @var{n} frames.
+
+@item backtrace -@var{n}
+@itemx bt -@var{n}
+Similar, but print only the outermost @var{n} frames.
+@end table
+
+@kindex where
+@kindex info stack
+The names @samp{where} and @samp{info stack} are additional aliases
+for @samp{backtrace}.
+
+Each line in the backtrace shows the frame number and the function
+name.  The program counter value is also shown---unless you use
+@samp{set addressprint off}.
+
+If the function is in a source file whose symbol table data has been
+fully read, the backtrace shows the source file name and line number, as
+well as the arguments to the function.  When the line number is shown,
+the program counter value is omitted if it is at the beginning of the
+code for that line number.
+
+Here is an example of a backtrace.  It was made with the command
+@samp{bt 3}, so it shows the innermost three frames.
+
+@example
+#0  rtx_equal_p (x=(rtx) 0x8e58c, y=(rtx) 0x1086c4) \
+(/gp/rms/cc/rtlanal.c line 337)
+#1  0x246b0 in expand_call (...) (...)
+#2  0x21cfc in expand_expr (...) (...)
+(More stack frames follow...)
+@end example
+
+@noindent
+_GDBN__ displayed the functions @code{expand_call} and @code{expand_expr}
+with place-holders in place of their argument values and line numbers,
+because each is in a file whose symbol details have not been fully read.
+Full detail is available for the function @code{rtx_equal_p}, which is
+in the file @file{rtlanal.c}.  Its arguments, named @code{x} and
+@code{y}, are shown with their typed values.
+
+@node Selection,,,
+@section Selecting a Frame
+
+Most commands for examining the stack and other data in the program work on
+whichever stack frame is selected at the moment.  Here are the commands for
+selecting a stack frame; all of them finish by printing a brief description
+of the stack frame just selected.
+
+@table @code
+@item frame @var{n}
+@kindex frame
+Select frame number @var{n}.  Recall that frame zero is the innermost
+(currently executing) frame, frame one is the frame that called the
+innermost one, and so on.  The highest-numbered frame is @code{main}'s
+frame.
+
+@item frame @var{addr}
+Select the frame at address @var{addr}.  This is useful mainly if the
+chaining of stack frames has been damaged by a bug, making it
+impossible for _GDBN__ to assign numbers properly to all frames.  In
+addition, this can be useful when the program has multiple stacks and
+switches between them.
+
+@item up @var{n}
+@kindex up
+Move @var{n} frames up the stack.  For positive numbers @var{n}, this
+advances toward the outermost frame, to higher frame numbers, to frames
+that have existed longer.  @var{n} defaults to one.
+
+@item down @var{n}
+@kindex down
+Move @var{n} frames down the stack.  For positive numbers @var{n}, this
+advances toward the innermost frame, to lower frame numbers, to frames
+that were created more recently.  @var{n} defaults to one.
+@end table
+
+All of these commands end by printing some information on the frame that
+has been selected: the frame number, the function name, the arguments, the
+source file and line number of execution in that frame, and the text of
+that source line.  For example:
+
+@smallexample
+(_GDBP__) up
+#1  0x22f0 in main (argc=1, argv=0xf7fffbf4, env=0xf7fffbfc) at env.c:10
+10             read_input_file (argv[i]);
+@end smallexample
+
+After such a printout, the @samp{list} command with no arguments will print
+ten lines centered on the point of execution in the frame.  @xref{List}.
+
+@table @code
+@item up-silently @var{n}
+@itemx down-silently @var{n}
+@kindex down-silently
+@kindex up-silently
+These two commands are variants of @samp{up} and @samp{down},
+respectively; they differ in that they do their work silently, without
+causing display of the new frame.  They are intended primarily for use
+in _GDBN__ command scripts, where the output might be unnecessary and
+distracting. 
+
+@end table
+
+@node Frame Info,,,
+@section Information on a Frame
+
+There are several other commands to print information about the selected
+stack frame.
+
+@table @code
+@item frame
+When used without any argument, this command does not change which frame
+is selected, but prints a brief description of the currently
+selected stack frame.  It can be abbreviated @samp{f}.  With an
+argument, this command is used to select a stack frame (@pxref{Selection}).
+
+@item info frame
+@kindex info frame
+This command prints a verbose description of the selected stack frame,
+including the address of the frame, the addresses of the next frame down
+(called by this frame) and the next frame up (caller of this frame),
+the address of the frame's arguments, the program counter saved in it
+(the address of execution in the caller frame), and which registers
+were saved in the frame.  The verbose description is useful when
+something has gone wrong that has made the stack format fail to fit
+the usual conventions.
+
+@item info frame @var{addr}
+Print a verbose description of the frame at address @var{addr},
+without selecting that frame.  The selected frame remains unchanged by
+this command.
+
+@item info args
+@kindex info args
+Print the arguments of the selected frame, each on a separate line.
+
+@item info locals
+@kindex info locals
+Print the local variables of the selected frame, each on a separate
+line.  These are all variables declared static or automatic within all
+program blocks that execution in this frame is currently inside of.
+
+@item info catch
+@kindex info catch
+@cindex catch exceptions
+@cindex exception handlers
+Print a list of all the exception handlers that are active in the
+current stack frame at the current point of execution.  To see other
+exception handlers, visit the associated frame (using the @samp{up},
+@samp{down}, or @samp{frame} commands); then type @samp{info catch}.
+@xref{Exception Handling}.
+@end table
+
+@node Source,,,
+@chapter Examining Source Files
+
+_GDBN__ knows which source files your program was compiled from, and
+can print parts of their text.  When your program stops, _GDBN__
+spontaneously prints the line it stopped in.  Likewise, when you
+select a stack frame (@pxref{Selection}), _GDBN__ prints the line
+which execution in that frame has stopped in.  You can also
+print parts of source files by explicit command.
+
+@node List,,,
+@section Printing Source Lines
+
+@kindex list
+@kindex l
+To print lines from a source file, use the @samp{list} command
+(abbreviated @samp{l}).  There are several ways to specify what part
+of the file you want to print.
+
+Here are the forms of the @samp{list} command most commonly used:
+
+@table @code
+@item list @var{linenum}
+Print ten lines centered around line number @var{linenum} in the
+current source file.
+
+@item list @var{function}
+Print ten lines centered around the beginning of function
+@var{function}.
+
+@item list
+Print ten more lines.  If the last lines printed were printed with a
+@samp{list} command, this prints ten lines following the last lines
+printed; however, if the last line printed was a solitary line printed
+as part of displaying a stack frame (@pxref{Stack}), this prints ten
+lines centered around that line.
+
+@item list -
+Print ten lines just before the lines last printed.
+@end table
+
+Repeating a @samp{list} command with @key{RET} discards the argument,
+so it is equivalent to typing just @samp{list}.  This is more useful
+than listing the same lines again.  An exception is made for an
+argument of @samp{-}; that argument is preserved in repetition so that
+each repetition moves up in the source file.
+
+@cindex linespec
+In general, the @samp{list} command expects you to supply zero, one or two
+@dfn{linespecs}.  Linespecs specify source lines; there are several ways
+of writing them but the effect is always to specify some source line.
+Here is a complete description of the possible arguments for @samp{list}:
+
+@table @code
+@item list @var{linespec}
+Print ten lines centered around the line specified by @var{linespec}.
+
+@item list @var{first},@var{last}
+Print lines from @var{first} to @var{last}.  Both arguments are
+linespecs.
+
+@item list ,@var{last}
+Print ten lines ending with @var{last}.
+
+@item list @var{first},
+Print ten lines starting with @var{first}.
+
+@item list +
+Print ten lines just after the lines last printed.
+
+@item list -
+Print ten lines just before the lines last printed.
+
+@item list
+As described in the preceding table.
+@end table
+
+Here are the ways of specifying a single source line---all the
+kinds of linespec.
+
+@table @code
+@item @var{linenum}
+Specifies line @var{linenum} of the current source file.
+When a @samp{list} command has two linespecs, this refers to
+the same source file as the first linespec.
+
+@item +@var{offset}
+Specifies the line @var{offset} lines after the last line printed.
+When used as the second linespec in a @samp{list} command that has
+two, this specifies the line @var{offset} lines down from the
+first linespec.
+
+@item -@var{offset}
+Specifies the line @var{offset} lines before the last line printed.
+
+@item @var{filename}:@var{linenum}
+Specifies line @var{linenum} in the source file @var{filename}.
+
+@item @var{function}
+Specifies the line of the open-brace that begins the body of the
+function @var{function}.
+
+@item @var{filename}:@var{function}
+Specifies the line of the open-brace that begins the body of the
+function @var{function} in the file @var{filename}.  The file name is
+needed with a function name only for disambiguation of identically
+named functions in different source files.
+
+@item *@var{address}
+Specifies the line containing the program address @var{address}.
+@var{address} may be any expression.
+@end table
+
+@node Search,,,
+@section Searching Source Files
+@cindex searching
+@kindex search
+@kindex forward-search
+@kindex reverse-search
+
+There are two commands for searching through the current source file for a
+regular expression.
+
+The command @samp{forward-search @var{regexp}} checks each line, starting
+with the one following the last line listed, for a match for @var{regexp}.
+It lists the line that is found.  You can abbreviate the command name
+as @samp{fo}.  The synonym @samp{search @var{regexp}} is also supported.
+
+The command @samp{reverse-search @var{regexp}} checks each line, starting
+with the one before the last line listed and going backward, for a match
+for @var{regexp}.  It lists the line that is found.  You can abbreviate
+this command with as little as @samp{rev}.
+
+@node Source Path,,,
+@section Specifying Source Directories
+
+@cindex source path
+@cindex directories for source files
+Executable programs sometimes do not record the directories of the source
+files from which they were compiled, just the names.  Even when they do,
+the directories could be moved between the compilation and your debugging
+session.  _GDBN__ remembers a list of directories to search for source files;
+this is called the @dfn{source path}.  Each time _GDBN__ wants a source file,
+it tries all the directories in the list, in the order they are present
+in the list, until it finds a file with the desired name.  Note that
+the executable search path is @emph{not} used for this purpose.  Neither is
+the current working directory, unless it happens to be in the source
+path.
+
+If it can't find a source file in the source path, and the object program
+records what directory it was compiled in, _GDBN__ tries that directory too.
+If the source path is empty, and there is no record of the compilation
+directory, _GDBN__ will, as a last resort, look in the current directory.
+
+Whenever you reset or rearrange the source path, _GDBN__ will clear out
+any information it has cached about where source files are found, where
+each line is in the file, etc.
+
+@kindex directory
+When you start _GDBN__, its source path is empty.
+To add other directories, use the @samp{directory} command.
+
+@table @code
+@item directory @var{dirnames...}
+Add directory @var{dirname} to the front of the source path.  Several
+directory names may be given to this command, separated by whitespace or
+@samp{:}.  If a name is already in the source path, it is moved to the
+front of the path, so it will be searched sooner.
+
+@item directory
+Reset the source path to empty again.  This requires confirmation.
+
+@item info directories
+@kindex info directories
+Print the source path: show which directories it contains.
+@end table
+
+If your source path is cluttered with directories that are no longer of
+interest, _GDBN__ may sometimes cause confusion by finding the wrong
+versions of source.  You can correct the situation as follows:
+
+@enumerate
+@item
+Use @samp{directory} with no argument to reset the source path to empty.
+
+@item
+Use @samp{directory} with suitable arguments to add any other
+directories you want in the source path.  You can add all the directories
+in one command.
+@end enumerate
+
+@node Machine Code,,,
+@section Source and Machine Code
+You can use the command @samp{info line} to map source lines to program
+addresses, and the command @samp{disassemble} or its synonym
+@samp{disasm} to display a range of addresses as machine instructions.
+
+@table @code
+@item info line @var{linespec}
+@kindex info line
+Print the starting and ending addresses of the compiled code for
+source line @var{linespec}.
+
+@kindex $_
+The default examine address for the @samp{x} command is changed to the
+starting address of the line, so that @samp{x/i} is sufficient to
+begin examining the machine code (@pxref{Memory}).  Also, this address
+is saved as the value of the convenience variable @code{$_}
+(@pxref{Convenience Vars}).
+
+@kindex disassemble
+@kindex disasm
+@item disassemble
+@itemx disasm
+This specialized command is provided to dump a range of memory as
+machine instructions.  The default memory range is the function
+surrounding the program counter of the selected frame.  A single
+argument to this command is a program counter value; the function
+surrounding this value will be dumped.  Two arguments (separated by one
+or more spaces) specify a range of addresses (first inclusive, second
+exclusive) to be dumped.  The two spellings, @samp{disasm} and
+@samp{disassemble}, are equivalent.
+@end table
+
+@node Data,,,
+@chapter Examining Data
+
+@cindex printing data
+@cindex examining data
+@kindex print
+@kindex inspect
+@c "inspect" isn't quite a synonym if you're using Epoch, which we don't
+@c document because it's nonstandard...  Under Epoch it displays in a
+@c different window or something like that.
+The usual way to examine data in your program is with the @samp{print}
+command (abbreviated @samp{p}), or its synonym @samp{inspect}.  It
+evaluates and prints the value of any valid expression of the language
+the program is written in (for now, C or C++).  You type
+
+@example
+print @var{exp}
+@end example
+
+@noindent
+where @var{exp} is any valid expression (in the source language), and
+the value of @var{exp} is printed in a format appropriate to its data
+type.
+
+A more low-level way of examining data is with the @samp{x} command.
+It examines data in memory at a specified address and prints it in a
+specified format.
+
+@node Expressions,,,
+@section Expressions
+
+@cindex expressions
+Many different _GDBN__ commands accept an expression and compute its value.
+Any kind of constant, variable or operator defined by the programming
+language you are using is legal in an expression in _GDBN__.  This includes
+conditional expressions, function calls, casts and string constants.  It
+unfortunately does not include symbols defined by preprocessor
+@code{#define} commands, or C++ expressions involving @samp{::}, the
+name resolution operator.
+@c FIXME: actually C++ a::b works except in obscure circumstances where it
+@c FIXME...can conflict with GDB's own name scope resolution.
+
+Casts are supported in all languages, not just in C, because it is so
+useful to cast a number into a pointer so as to examine a structure
+at that address in memory.
+
+_GDBN__ supports three kinds of operator in addition to those of programming
+languages:
+
+@table @code
+@item @@
+@samp{@@} is a binary operator for treating parts of memory as arrays.
+@xref{Arrays}, for more information.
+
+@item ::
+@samp{::} allows you to specify a variable in terms of the file or
+function it is defined in.  @xref{Variables}.
+
+@item @{@var{type}@} @var{addr}
+Refers to an object of type @var{type} stored at address @var{addr} in
+memory.  @var{addr} may be any expression whose value is an integer or
+pointer (but parentheses are required around nonunary operators, just as in
+a cast).  This construct is allowed regardless of what kind of data is
+officially supposed to reside at @var{addr}.@refill
+@end table
+
+@node Variables,,,
+@section Program Variables
+
+The most common kind of expression to use is the name of a variable
+in your program.
+
+Variables in expressions are understood in the selected stack frame
+(@pxref{Selection}); they must either be global (or static) or be visible
+according to the scope rules of the programming language from the point of
+execution in that frame.  This means that in the function
+
+@example
+foo (a)
+     int a;
+@{
+  bar (a);
+  @{
+    int b = test ();
+    bar (b);
+  @}
+@}
+@end example
+
+@noindent
+the variable @code{a} is usable whenever the program is executing
+within the function @code{foo}, but the variable @code{b} is visible
+only while the program is executing inside the block in which @code{b}
+is declared.
+
+As a special exception, you can refer to a variable or function whose
+scope is a single source file even if the current execution point is not
+in this file.  But it is possible to have more than one such variable or
+function with the same name (in different source files).  In such a
+case, it is not defined which one you will get.  If you wish, you can
+specify any one of them using the colon-colon construct:
+
+@cindex colon-colon
+@cindex scope
+@kindex ::
+@example
+@var{block}::@var{variable}
+@end example
+
+@noindent
+Here @var{block} is the name of the source file whose variable you want.
+
+@cindex name resolution (C++)
+Unfortunately, this use of @samp{::} conflicts with the very similar use
+of the same notation in C++; accordingly, _GDBN__ does not support use of
+the C++ name resolution operator in _GDBN__ expressions.
+
+@node Arrays,,,
+@section Artificial Arrays
+
+@cindex artificial array
+@kindex @@
+It is often useful to print out several successive objects of the
+same type in memory; a section of an array, or an array of
+dynamically determined size for which only a pointer exists in the
+program.
+
+This can be done by constructing an @dfn{artificial array} with the
+binary operator @samp{@@}.  The left operand of @samp{@@} should be
+the first element of the desired array, as an individual object.
+The right operand should be the length of the array.  The result is
+an array value whose elements are all of the type of the left argument.
+The first element is actually the left argument; the second element
+comes from bytes of memory immediately following those that hold the
+first element, and so on.  Here is an example.  If a program says
+
+@example
+int *array = (int *) malloc (len * sizeof (int));
+@end example
+
+@noindent
+you can print the contents of @code{array} with
+
+@example
+p *array@@len
+@end example
+
+The left operand of @samp{@@} must reside in memory.  Array values made
+with @samp{@@} in this way behave just like other arrays in terms of
+subscripting, and are coerced to pointers when used in expressions.
+(It would probably appear in an expression via the value history,
+after you had printed it out.)
+
+@node Output formats,,,
+@section Output formats
+
+@cindex formatted output
+@cindex output formats
+_GDBN__ normally prints all values according to their data types.  Sometimes
+this is not what you want.  For example, you might want to print a number
+in hex, or a pointer in decimal.  Or you might want to view data in memory
+at a certain address as a character string or an instruction.  To do
+these things, specify an @dfn{output format} when you print a value.
+
+The simplest use of output formats is to say how to print a value
+already computed.  This is done by starting the arguments of the
+@samp{print} command with a slash and a format letter.  The format
+letters supported are:
+
+@table @samp
+@item x
+Regard the bits of the value as an integer, and print the integer in
+hexadecimal.
+
+@item d
+Print as integer in signed decimal.
+
+@item u
+Print as integer in unsigned decimal.
+
+@item o
+Print as integer in octal.
+
+@item a
+Print as an address, both absolute in hex and as an offset from the
+nearest preceding symbol.  This format can be used to discover where (in
+what function) an unknown address is located:
+@example
+(_GDBP__) p/a 0x54320
+_0__$3 = 0x54320 <_initialize_vx+396>_1__
+@end example
+
+
+@item c
+Regard as an integer and print it as a character constant.
+
+@item f
+Regard the bits of the value as a floating point number and print
+using typical floating point syntax.
+@end table
+
+For example, to print the program counter in hex (@pxref{Registers}), type
+
+@example
+p/x $pc
+@end example
+
+@noindent
+Note that no space is required before the slash; this is because command
+names in _GDBN__ cannot contain a slash.
+
+To reprint the last value in the value history with a different format,
+you can use the @samp{print} command with just a format and no
+expression.  For example, @samp{p/x} reprints the last value in hex.
+
+@node Memory,,,
+@section Examining Memory
+
+@cindex examining memory
+@table @code
+@kindex x
+@item x
+The command @samp{x} (for `examine') can be used to examine memory
+without reference to the program's data types.  The format in which you
+wish to examine memory is instead explicitly specified.  The allowable
+formats are a superset of the formats described in the previous section.
+@end table
+
+@samp{x} is followed by a slash and an output format specification,
+followed by an expression for an address.  The expression need not have
+a pointer value (though it may); it is used as an integer, as the
+address of a byte of memory.  @xref{Expressions} for more information on
+expressions.  For example, @samp{x/4xw $sp} prints the four words of
+memory above the stack pointer in hexadecimal.
+
+The output format in this case specifies both how big a unit of memory
+to examine and how to print the contents of that unit.  This is done
+with one or two of the following letters:
+
+These letters specify the size of unit to examine:
+
+@table @samp
+@item b
+Examine individual bytes.
+
+@item h
+Examine halfwords (two bytes each).
+
+@item w
+Examine words (four bytes each).
+
+@cindex word
+Many assemblers and cpu designers still use `word' for a 16-bit quantity,
+as a holdover from specific predecessor machines of the 1970's that really
+did use two-byte words.  But more generally the term `word' has always
+referred to the size of quantity that a machine normally operates on and
+stores in its registers.  This is 32 bits for all the machines that _GDBN__
+runs on.
+
+@item g
+Examine giant words (8 bytes).
+@end table
+
+These letters specify the way to print the contents:
+
+@table @samp
+@item x
+Print as integers in unsigned hexadecimal.
+
+@item d
+Print as integers in signed decimal.
+
+@item u
+Print as integers in unsigned decimal.
+
+@item o
+Print as integers in unsigned octal.
+
+@item a
+Print as an address, both absolute in hex and then relative
+to a symbol defined as an address below it.
+
+@item c
+Print as character constants.
+
+@item f
+Print as floating point.  This works only with sizes @samp{w} and
+@samp{g}.
+@end table
+
+These letters specify both the unit size and the output format:
+@table @samp
+@item s
+Print a null-terminated string of characters.  Any explicitly specified
+unit size is ignored; instead, the unit is however many bytes it takes
+to reach a null character (including the null character).
+
+@item i
+Print a machine instruction in assembler syntax (or nearly).  Any
+specified unit size is ignored; the number of bytes in an instruction
+varies depending on the type of machine, the opcode and the addressing
+modes used.  The command @samp{disassemble} gives an alternative way of
+inspecting machine instructions.  @xref{Machine Code}.
+@end table
+
+If either the manner of printing or the size of unit fails to be specified,
+the default is to use the same one that was used last.  If you don't want
+to use any letters after the slash, you can omit the slash as well.
+
+You can also omit the address to examine.  Then the address used is just
+after the last unit examined.  This is why string and instruction
+formats actually compute a unit-size based on the data: so that the next
+string or instruction examined will start in the right place.  
+
+When the @samp{print} command shows a value that resides in memory,
+@samp{print} also sets the default address for the @samp{x} command.
+@samp{info line} also sets the default for @samp{x}, to the address of
+the start of the machine code for the specified line (@pxref{Machine
+Code}), and @samp{info breakpoints} sets it to the address of the last
+breakpoint listed (@pxref{Set Breaks}).
+
+When you use @key{RET} to repeat an @samp{x} command, the address
+specified previously (if any) is ignored, so that the repeated command
+examines the successive locations in memory rather than the same ones.
+
+You can examine several consecutive units of memory with one command by
+writing a repeat-count after the slash (before the format letters, if any).
+The repeat count must be a decimal integer.  It has the same effect as
+repeating the @samp{x} command that many times except that the output may
+be more compact with several units per line.  For example,
+
+@example
+x/10i $pc
+@end example
+
+@noindent
+prints ten instructions starting with the one to be executed next in the
+selected frame.  After doing this, you could print another seven following
+instructions with
+
+@example
+x/7
+@end example
+
+@noindent
+in which the format and address are allowed to default.
+
+@kindex $_
+@kindex $__
+The addresses and contents printed by the @samp{x} command are not put
+in the value history because there is often too much of them and they
+would get in the way.  Instead, _GDBN__ makes these values available for
+subsequent use in expressions as values of the convenience variables
+@code{$_} and @code{$__}.  After an @samp{x} command, the last address
+examined is available for use in expressions in the convenience variable
+@code{$_}.  The contents of that address, as examined, are available in
+the convenience variable @code{$__}.
+
+If the @samp{x} command has a repeat count, the address and contents saved
+are from the last memory unit printed; this is not the same as the last
+address printed if several units were printed on the last line of output.
+
+@node Auto Display,,,
+@section Automatic Display
+@cindex automatic display
+@cindex display of expressions
+
+If you find that you want to print the value of an expression frequently
+(to see how it changes), you might want to add it to the @dfn{automatic
+display list} so that _GDBN__ will print its value each time the program stops.
+Each expression added to the list is given a number to identify it;
+to remove an expression from the list, you specify that number.
+The automatic display looks like this:
+
+@example
+2: foo = 38
+3: bar[5] = (struct hack *) 0x3804
+@end example
+
+@noindent
+showing item numbers, expressions and their current values.
+
+@table @code
+@item display @var{exp}
+@kindex display
+Add the expression @var{exp} to the list of expressions to display
+each time the program stops.  @xref{Expressions}.
+
+@item display/@var{fmt} @var{exp}
+For @var{fmt} specifying only a display format and not a size or
+count, add the expression @var{exp} to the auto-display list but
+arranges to display it each time in the specified format @var{fmt}.
+
+@item display/@var{fmt} @var{addr}
+For @var{fmt} @samp{i} or @samp{s}, or including a unit-size or a
+number of units, add the expression @var{addr} as a memory address to
+be examined each time the program stops.  Examining means in effect
+doing @samp{x/@var{fmt} @var{addr}}.  @xref{Memory}.
+@end table
+
+For example, @samp{display/i $pc} can be helpful, to see the machine
+instruction about to be executed each time execution stops (@samp{$pc}
+is a common name for the program counter; @pxref{Registers}).
+
+@table @code
+@item undisplay @var{dnums}@dots{}
+@itemx delete display @var{dnums}@dots{}
+@kindex delete display
+@kindex undisplay
+Remove item numbers @var{dnums} from the list of expressions to display.
+
+@item disable display @var{dnums}@dots{}
+@kindex disable display
+Disable the display of item numbers @var{dnums}.  A disabled display
+item is not printed automatically, but is not forgotten.  It may be
+enabled again later.
+
+@item enable display @var{dnums}@dots{}
+@kindex enable display
+Enable display of item numbers @var{dnums}.  It becomes effective once
+again in auto display of its expression, until you specify otherwise.
+
+@item display
+Display the current values of the expressions on the list, just as is
+done when the program stops.
+
+@item info display
+@kindex info display
+Print the list of expressions previously set up to display
+automatically, each one with its item number, but without showing the
+values.  This includes disabled expressions, which are marked as such.
+It also includes expressions which would not be displayed right now
+because they refer to automatic variables not currently available.
+@end table
+
+If a display expression refers to local variables, then it does not make
+sense outside the lexical context for which it was set up.  Such an
+expression is disabled when execution enters a context where one of its
+variables is not defined.  For example, if you give the command
+@samp{display name} while inside a function with an argument
+@code{name}, then this argument will be displayed while the program
+continues to stop inside that function.  When it stops elsewhere---where
+there is no variable @samp{name}---display is disabled.  The next time
+your program stops where @samp{name} is meaningful, you can enable the
+display expression once again.
+
+@node Print Settings,,,
+@section Print Settings
+
+@cindex format options
+@cindex print settings
+_GDBN__ provides a few ways to control how arrays, structures, and symbols are
+printed.  
+
+@table @code
+@item set array-max @var{number-of-elements}
+@kindex set array-max
+If _GDBN__ is printing a large array, it will stop printing after it has
+printed the number of elements set by the @samp{set array-max} command.
+This limit also applies to the display of strings.
+
+@item show array-max
+@kindex show array-max
+Display the number of elements of a large array that _GDBN__ will print
+before losing patience.
+
+@item set arrayprint
+@itemx set arrayprint on
+@kindex set arrayprint
+_GDBN__ will pretty print arrays.  This format is more convenient to read,
+but uses more space.  The default is off.
+
+@item set arrayprint off.
+Return to compressed format for arrays.
+
+@item show arrayprint
+@kindex show arrayprint
+Show whether compressed or pretty format is selected for displaying
+arrays. 
+
+@item set demangle 
+@itemx set demangle on 
+@kindex set demangle
+Print C++ names in their source form rather than in the mangled form
+in which they are passed to the assembler and linker for type-safe linkage.
+The default is on.
+
+@item show demangle
+@kindex show demangle
+Show whether C++ names will be printed in mangled or demangled form.
+
+@item set asm-demangle 
+@itemx set asm-demangle on 
+@kindex set asm-demangle
+Print C++ names in their source form rather than their mangled form, even
+in assembler code printouts such as instruction disassemblies.
+The default is off.
+
+@item show asm-demangle
+@kindex show asm-demangle
+Show whether C++ names in assembly listings will be printed in mangled
+or demangled form.
+
+@item set vtblprint 
+@itemx set vtblprint on 
+@kindex set vtblprint
+Pretty print C++ virtual function tables.  The default is off.
+
+@item set vtblprint off
+Do not pretty print C++ virtual function tables.
+
+@item show vtblprint
+@kindex show vtblprint
+Show whether C++ virtual function tables are pretty printed, or not.
+
+@item set addressprint
+@item set addressprint on
+@kindex set addressprint
+_GDBN__ will print memory addresses in stack traces, structure values, pointer
+values, breakpoints, etc.  The default is on.
+
+@item set addressprint off
+Do not print addresses.
+
+@item show addressprint
+@kindex show addressprint
+Show whether or not addresses are to be printed.
+
+@item set prettyprint on
+@kindex set prettyprint
+Cause _GDBN__ to print structures in an indented format with one member per
+line, like this:
+
+@example
+$1 = @{
+  next = 0x0,
+  flags = @{
+    sweet = 1,
+    sour = 1
+  @},
+  meat = 0x54 "Pork"
+@}
+@end example
+
+@item set prettyprint off
+Cause _GDBN__ to print structures in a compact format, like this:
+
+@smallexample
+$1 = @{next = 0x0, flags = @{sweet = 1, sour = 1@}, meat \
+= 0x54 "Pork"@}
+@end smallexample
+
+@noindent
+This is the default format.
+
+@item show prettyprint
+@kindex show prettyprint
+Show which format _GDBN__ will use to print structures.
+
+@item set unionprint on
+@kindex set unionprint
+Tell _GDBN__ to print unions which are contained in structures.  This is the
+default setting.
+
+@item set unionprint off
+Tell _GDBN__ not to print unions which are contained in structures.
+
+@item show unionprint
+@kindex show unionprint
+Ask _GDBN__ whether or not it will print unions which are contained in
+structures. 
+
+For example, given the declarations
+
+@smallexample
+typedef enum @{Tree, Bug@} Species;
+typedef enum @{Big_tree, Acorn, Seedling@} Tree_forms;
+typedef enum @{Caterpillar, Cocoon, Butterfly@} Bug_forms;
+
+struct thing @{
+  Species it;
+  union @{
+    Tree_forms tree;
+    Bug_forms bug;
+  @} form;
+@};
+
+struct thing foo = @{Tree, @{Acorn@}@};
+@end smallexample
+
+@noindent
+with @samp{set unionprint on} in effect @samp{p foo} would print
+
+@smallexample
+$1 = @{it = Tree, form = @{tree = Acorn, bug = Cocoon@}@}
+@end smallexample
+
+@noindent
+and with @samp{set unionprint off} in effect it would print
+
+@example
+$1 = @{it = Tree, form = @{...@}@}
+@end example
+@end table
+
+@node Value History,,,
+@section Value History
+
+@cindex value history
+Values printed by the @samp{print} command are saved in _GDBN__'s @dfn{value
+history} so that you can refer to them in other expressions.  Values are
+kept until the symbol table is re-read or discarded (for example with
+the @samp{file} or @samp{symbol-file} commands).  When the symbol table
+changes, the value history is discarded, since the values may contain
+pointers back to the types defined in the symbol table.
+
+@cindex @code{$}
+@cindex @code{$$}
+@cindex history number
+The values printed are given @dfn{history numbers} for you to refer to them
+by.  These are successive integers starting with 1.  @samp{print} shows you
+the history number assigned to a value by printing @samp{$@var{num} = }
+before the value; here @var{num} is the history number.
+
+To refer to any previous value, use @samp{$} followed by the value's
+history number.  The output printed by @samp{print} is designed to
+remind you of this.  Just @code{$} refers to the most recent value in
+the history, and @code{$$} refers to the value before that.
+@code{$$@var{n}} refers to the @var{n}th value from the end; @code{$$2}
+is the value just prior to @code{$$}, @code{$$1} is equivalent to
+@code{$$}, and @code{$$0} is equivalent to @code{$}.
+
+For example, suppose you have just printed a pointer to a structure and
+want to see the contents of the structure.  It suffices to type
+
+@example
+p *$
+@end example
+
+If you have a chain of structures where the component @samp{next} points
+to the next one, you can print the contents of the next one with this:
+
+@example
+p *$.next
+@end example
+
+@noindent
+You can print successive links in the chain by repeating this
+command---which you can do by just typing @key{RET}.
+
+Note that the history records values, not expressions.  If the value of
+@code{x} is 4 and you type these commands:
+
+@example
+print x
+set x=5
+@end example
+
+@noindent
+then the value recorded in the value history by the @samp{print} command
+remains 4 even though the value of @code{x} has changed.
+
+@table @code
+@kindex info values
+@item info values
+@itemx info history
+@kindex info history
+These two commands are synonymous.  Either form will print the last ten
+values in the value history, with their item numbers.  This is like
+@samp{p@ $$9} repeated ten times, except that @samp{info values} does
+not change the history.
+
+@item info values @var{n}
+Print ten history values centered on history item number @var{n}.
+
+@item info values +
+Print ten history values just after the values last printed.
+@end table
+
+@node Convenience Vars,,,
+@section Convenience Variables
+
+@cindex convenience variables
+_GDBN__ provides @dfn{convenience variables} that you can use within
+_GDBN__ to hold on to a value and refer to it later.  These variables
+exist entirely within _GDBN__; they are not part of your program, and
+setting a convenience variable has no direct effect on further execution
+of your program.  That's why you can use them freely.
+
+Convenience variables have names starting with @samp{$}.  Any name starting
+with @samp{$} can be used for a convenience variable, unless it is one of
+the predefined machine-specific register names (@pxref{Registers}).
+
+You can save a value in a convenience variable with an assignment
+expression, just as you would set a variable in your program.  Example:
+
+@example
+set $foo = *object_ptr
+@end example
+
+@noindent
+would save in @code{$foo} the value contained in the object pointed to by
+@code{object_ptr}.
+
+Using a convenience variable for the first time creates it; but its value
+is @code{void} until you assign a new value.  You can alter the value with
+another assignment at any time.
+
+Convenience variables have no fixed types.  You can assign a convenience
+variable any type of value, including structures and arrays, even if
+that variable already has a value of a different type.  The convenience
+variable, when used as an expression, has the type of its current value.
+
+@table @code
+@item info convenience
+@kindex info convenience
+Print a list of convenience variables used so far, and their values.
+Abbreviated @samp{i con}.
+@end table
+
+One of the ways to use a convenience variable is as a counter to be
+incremented or a pointer to be advanced.  For example, to print
+a field from successive elements of an array of structures:
+
+_0__@example
+set $i = 0
+print bar[$i++]->contents
+@i{@dots{}repeat that command by typing @key{RET}.}
+_1__@end example
+
+Some convenience variables are created automatically by _GDBN__ and given
+values likely to be useful.
+
+@table @code
+@item $_
+The variable @code{$_} is automatically set by the @samp{x} command to
+the last address examined (@pxref{Memory}).  Other commands which
+provide a default address for @samp{x} to examine also set @code{$_}
+to that address; these commands include @samp{info line} and @samp{info
+breakpoint}.
+
+@item $__
+The variable @code{$__} is automatically set by the @samp{x} command
+to the value found in the last address examined.
+@end table
+
+@node Registers,,,
+@section Registers
+
+@cindex registers
+Machine register contents can be referred to in expressions as variables
+with names starting with @samp{$}.  The names of registers are different
+for each machine; use @samp{info registers} to see the names used on
+your machine.  The names @code{$pc} and @code{$sp} are used on most
+machines for the program counter register and the stack pointer.  Often
+@code{$fp} is used for a register that contains a pointer to the current
+stack frame, and @code{$ps} is sometimes used for a register that
+contains the processor status.  These standard register names may be
+available on your machine even though the @code{info registers} command
+shows other names.  For example, on the SPARC, @code{info registers}
+displays the processor status register as @code{$psr} but you can also
+refer to it as @code{$ps}.
+
+_GDBN__ always considers the contents of an ordinary register as an
+integer when the register is examined in this way.  Some machines have
+special registers which can hold nothing but floating point; these
+registers are considered to have floating point values.  There is no way
+to refer to the contents of an ordinary register as floating point value
+(although you can @emph{print} it as a floating point value with
+@samp{print/f $@var{regname}}).
+
+Some registers have distinct ``raw'' and ``virtual'' data formats.  This
+means that the data format in which the register contents are saved by
+the operating system is not the same one that your program normally
+sees.  For example, the registers of the 68881 floating point
+coprocessor are always saved in ``extended'' (raw) format, but all C
+programs expect to work with ``double'' (virtual) format.  In such
+cases, _GDBN__ normally works with the virtual format only (the format that
+makes sense for your program), but the @samp{info registers} command
+prints the data in both formats.
+
+Normally, register values are relative to the selected stack frame
+(@pxref{Selection}).  This means that you get the value that the register
+would contain if all stack frames farther in were exited and their saved
+registers restored.  In order to see the contents of hardware registers,
+you must select the innermost frame (with @samp{frame 0}).
+
+However, _GDBN__ must deduce where registers are saved, from the machine
+code generated by your compiler.  If some registers are not saved, or if
+_GDBN__ is unable to locate the saved registers, the selected stack
+frame will make no difference.
+
+@table @code
+@item info registers
+@kindex info registers
+Print the names and relativized values of all registers.
+
+@item info registers @var{regname}
+Print the relativized value of register @var{regname}.  @var{regname}
+may be any register name valid on the machine you are using, with
+or without the initial @samp{$}.
+@end table
+
+For example, you could print the program counter in hex with
+
+@example
+p/x $pc
+@end example
+
+@noindent
+or print the instruction to be executed next with
+
+@example
+x/i $pc
+@end example
+
+@noindent
+or add four to the stack pointer with
+
+@example
+set $sp += 4
+@end example
+
+@noindent
+The last is a way of removing one word from the stack, on machines where
+stacks grow downward in memory (most machines, nowadays).  This assumes
+that the innermost stack frame is selected.  Setting @code{$sp} is
+not allowed when other stack frames are selected.  (To pop entire frames
+off the stack, regardless of machine architecture, use @samp{return};
+@pxref{Returning}.)
+
+@node Symbols,,,
+@chapter Examining the Symbol Table
+
+The commands described in this section allow you to inquire about the
+symbols (names of variables, functions and types) defined in your
+program.  This information is found by _GDBN__ in the symbol table loaded by
+the @samp{symbol-file} command; it is inherent in the text of your
+program and does not change as the program executes.
+
+@table @code
+@item info address @var{symbol}
+@kindex info address
+Describe where the data for @var{symbol} is stored.  For a register
+variable, this says which register it is kept in.  For a non-register
+local variable, this prints the stack-frame offset at which the variable
+is always stored.
+
+Note the contrast with @samp{print &@var{symbol}}, which does not work
+at all for a register variables, and for a stack local variable prints
+the exact address of the current instantiation of the variable.
+
+@item whatis @var{exp}
+@kindex whatis
+Print the data type of expression @var{exp}.  @var{exp} is not
+actually evaluated, and any side-effecting operations (such as
+assignments or function calls) inside it do not take place.
+@xref{Expressions}.
+
+@item whatis
+Print the data type of @code{$}, the last value in the value history.
+
+@item ptype @var{typename}
+@kindex ptype
+Print a description of data type @var{typename}.  @var{typename} may be
+the name of a type, or for C code it may have the form
+@samp{struct @var{struct-tag}}, @samp{union @var{union-tag}} or
+@samp{enum @var{enum-tag}}.@refill
+
+@item ptype @var{exp}
+Print a description of the type of expression @var{exp}.  This is like
+@samp{whatis} except it prints a detailed description, instead of just
+the name of the type.  For example, if the type of a variable is
+@samp{struct complex @{double real; double imag;@}}, @samp{whatis} will
+print @samp{struct complex} and @samp{ptype} will print @samp{struct
+complex @{double real; double imag;@}}
+
+@item info sources
+@kindex info sources
+Print the names of all source files in the program for which there
+is debugging information.
+
+@item info functions
+@kindex info functions
+Print the names and data types of all defined functions.
+
+@item info functions @var{regexp}
+Print the names and data types of all defined functions
+whose names contain a match for regular expression @var{regexp}.
+Thus, @samp{info fun step} finds all functions whose names
+include @samp{step}; @samp{info fun ^step} finds those whose names
+start with @samp{step}.
+
+@item info variables
+@kindex info variables
+Print the names and data types of all variables that are declared
+outside of functions (i.e., excluding local variables).
+
+@item info variables @var{regexp}
+Print the names and data types of all variables (except for local
+variables) whose names contain a match for regular expression
+@var{regexp}.
+
+
+@ignore
+This was never implemented.
+@item info methods
+@itemx info methods @var{regexp}
+@kindex info methods
+The @samp{info-methods} command permits the user to examine all defined
+methods within C++ program, or (with the @var{regexp} argument) a
+specific set of methods found in the various C++ classes.  Many
+C++ classes provide a large number of methods.  Thus, the output
+from the @samp{ptype} command can be overwhelming and hard to use.  The
+@samp{info-methods} command filters the methods, printing only those
+which match the regular-expression @var{regexp}.
+@end ignore
+
+@item printsyms @var{filename}
+@kindex printsyms
+Write a complete dump of the debugger's symbol data into the
+file @var{filename}.
+@end table
+
+@node Altering,,,
+@chapter Altering Execution
+
+Once you think you have found an error in the program, you might want to
+find out for certain whether correcting the apparent error would lead to
+correct results in the rest of the run.  You can find the answer by
+experiment, using the _GDBN__ features for altering execution of the
+program.
+
+For example, you can store new values into variables or memory
+locations, give the program a signal, restart it at a different address,
+or even return prematurely from a function to its caller.
+
+@node Assignment,,,
+@section Assignment to Variables
+
+@cindex assignment
+@cindex setting variables
+To alter the value of a variable, evaluate an assignment expression.
+@xref{Expressions}.  For example,
+
+@example
+print x=4
+@end example
+
+@noindent
+would store the value 4 into the variable @code{x}, and then print the
+value of the assignment expression (which is 4).  All the assignment
+operators of C are supported, including the increment operators
+@samp{++} and @samp{--}, and combining assignments such as @samp{+=} and
+_0__@samp{<<=}_1__.
+
+@kindex set
+@kindex set variable
+@cindex variables, setting
+If you are not interested in seeing the value of the assignment, use the
+@samp{set} command instead of the @samp{print} command.  @samp{set} is
+really the same as @samp{print} except that the expression's value is not
+printed and is not put in the value history (@pxref{Value History}).  The
+expression is evaluated only for side effects.
+
+If the beginning of the argument string of the @samp{set} command
+appears identical to a @samp{set} subcommand, use the @samp{set
+variable} command instead of just @samp{set}.  This command is identical
+to @samp{set} except for its lack of subcommands.
+
+_GDBN__ allows more implicit conversions in assignments than C does; you can
+freely store an integer value into a pointer variable or vice versa, and
+any structure can be converted to any other structure that is the same
+length or shorter.
+@comment FIXME: how do structs align/pad in these conversions? 
+@comment        /pesch@cygnus.com 18dec1990
+
+To store values into arbitrary places in memory, use the @samp{@{@dots{}@}}
+construct to generate a value of specified type at a specified address
+(@pxref{Expressions}).  For example, @code{@{int@}0x83040} refers
+to memory location @code{0x83040} as an integer (which implies a certain size
+and representation in memory), and
+
+@example
+set @{int@}0x83040 = 4
+@end example
+
+@noindent
+stores the value 4 into that memory location.
+
+@node Jumping,,,
+@section Continuing at a Different Address
+
+Ordinarily, when you continue the program, you do so at the place where
+it stopped, with the @samp{cont} command.  You can instead continue at
+an address of your own choosing, with the following commands:
+
+@table @code
+@item jump @var{linenum}
+@kindex jump
+Resume execution at line number @var{linenum}.  Execution may stop
+immediately if there is a breakpoint there.
+
+The @samp{jump} command does not change the current stack frame, or
+the stack pointer, or the contents of any memory location or any
+register other than the program counter.  If line @var{linenum} is in
+a different function from the one currently executing, the results may
+be bizarre if the two functions expect different patterns of arguments or
+of local variables.  For this reason, the @samp{jump} command requests
+confirmation if the specified line is not in the function currently
+executing.  However, even bizarre results are predictable based on
+careful study of the machine-language code of the program.
+
+@item jump *@var{address}
+Resume execution at the instruction at address @var{address}.
+@end table
+
+You can get much the same effect as the @code{jump} command by storing a
+new value into the register @code{$pc}.  The difference is that this
+does not start the program running; it only changes the address where it
+@emph{will} run when it is continued.  For example,
+
+@example
+set $pc = 0x485
+@end example
+
+@noindent
+causes the next @samp{cont} command or stepping command to execute at
+address 0x485, rather than at the address where the program stopped.
+@xref{Stepping}.
+
+The most common occasion to use the @samp{jump} command is to back up,
+perhaps with more breakpoints set, over a portion of a program that has
+already executed.
+
+@node Signaling,,,
+@section Giving the Program a Signal
+
+@table @code
+@item signal @var{signalnum}
+@kindex signal
+Resume execution where the program stopped, but give it immediately the
+signal number @var{signalnum}.
+
+Alternatively, if @var{signalnum} is zero, continue execution without
+giving a signal.  This is useful when the program stopped on account of
+a signal and would ordinary see the signal when resumed with the
+@samp{cont} command; @samp{signal 0} causes it to resume without a
+signal.
+@end table
+
+@node Returning,,,
+@section Returning from a Function
+
+@table @code
+@item return
+@cindex returning from a function
+@kindex return
+You can cancel execution of a function call with the @samp{return}
+command.
+@end table
+
+This command abandons execution of a function.  When you use
+@code{return}, _GDBN__ discards the selected stack frame (and all frames
+within it).  You can think of this as making the discarded frame return
+prematurely.  If you wish to specify a value to be returned, give that
+value as the argument to @code{return}.
+
+This pops the selected stack frame (@pxref{Selection}), and any other
+frames inside of it, leaving its caller as the innermost remaining
+frame.  That frame becomes selected.  The specified value is stored in
+the registers used for returning values of functions.
+
+The @samp{return} command does not resume execution; it leaves the
+program stopped in the state that would exist if the function had just
+returned.  In contrast, the @samp{finish} command (@pxref{Stepping})
+resumes execution until the selected stack frame returns naturally.
+
+@node     Calling,,,
+@section Calling your Program's Functions
+
+@cindex calling functions
+@kindex call
+@table @code
+@item call @var{expr}
+Evaluate the expression @var{expr} without displaying @code{void}
+returned values.
+@end table
+
+You can use this variant of the @samp{print} command if you want to
+execute a function from your program, but without cluttering the output
+with @code{void} returned values.  The result is printed and saved in
+the value history, if it is not void.
+
+@node Files,,,
+@chapter _GDBN__'s Files
+
+@section Commands to Specify Files
+@cindex core dump file
+@cindex symbol table
+_GDBN__ needs to know the file name of the program to be debugged, both in
+order to read its symbol table and in order to start the program.  To
+debug a core dump of a previous run, _GDBN__ must be told the file name of
+the core dump.
+
+The usual way to specify the executable and core dump file names is with
+the command arguments given when you start _GDBN__, as discussed in
+@pxref{Invocation}.
+
+Occasionally it is necessary to change to a different file during a
+_GDBN__ session.  Or you may run _GDBN__ and forget to specify the files you
+want to use.  In these situations the _GDBN__ commands to specify new files
+are useful.
+
+@table @code
+@item file @var{filename}
+@cindex executable file
+@kindex file
+Use @var{filename} as the program to be debugged.  It is read for its
+symbols and for the contents of pure memory.  It is also the program
+executed when you use the @samp{run} command.  If you do not specify a
+directory and the file is not found in _GDBN__'s working directory,
+_GDBN__ will use the environment variable @code{PATH} as a list of
+directories to search, just as the shell does when looking for a program
+to run.
+
+@samp{file} with no argument makes _GDBN__ discard any information it
+has on both executable file and the symbol table.
+
+@item exec-file @var{filename}
+@kindex exec-file
+Specify that the program to be run (but not the symbol table) is found
+in @var{filename}.  _GDBN__ will search the environment variable @code{PATH}
+if necessary to locate the program.
+
+@item symbol-file @var{filename}
+@kindex symbol-file
+Read symbol table information from file @var{filename}.  @code{PATH} is
+searched when necessary.  Use the @samp{file} command to get both symbol
+table and program to run from the same file.
+
+@samp{symbol-file} with no argument clears out _GDBN__'s information on your
+program's symbol table.
+
+The @samp{symbol-file} command causes _GDBN__ to forget the contents of its
+convenience variables, the value history, and all breakpoints and
+auto-display expressions.  This is because they may contain pointers to
+the internal data recording symbols and data types, which are part of
+the old symbol table data being discarded inside _GDBN__.
+
+On some kinds of object files, the @samp{symbol-file} command does not
+actually read the symbol table in full right away.  Instead, it scans
+the symbol table quickly to find which source files and which symbols
+are present.  The details are read later, one source file at a time,
+when they are needed.
+
+The purpose of this two-stage reading strategy is to make _GDBN__ start up
+faster.  For the most part, it is invisible except for occasional pauses
+while the symbol table details for a particular source file are being
+read.  (The @samp{set verbose} command can turn these pauses into
+messages if desired. @xref{Messages/Warnings}).
+
+When the symbol table is stored in COFF format, @samp{symbol-file} does
+read the symbol table data in full right away.  We haven't implemented
+the two-stage strategy for COFF yet.
+
+When _GDBN__ is configured for a particular environment, it will understand
+debugging information in whatever format is the standard generated for
+that environment; you may use either the GNU compiler _GCC__, or other
+compilers that adhere to the local conventions.  Best results are
+usually obtained from _GCC__; for example, using _GCC__ you can generate
+debugging information for optimized code.
+
+@item core-file @var{filename}
+@itemx core @var{filename}
+@kindex core
+@kindex core-file
+Specify the whereabouts of a core dump file to be used as the ``contents
+of memory''.  Traditionally, core files contain only some parts of the
+address space of the process that generated them; _GDBN__ can access the
+executable file itself for other parts.
+
+@samp{core-file} with no argument specifies that no core file is
+to be used.
+
+Note that the core file is ignored when your program is actually running
+under _GDBN__.  So, if you have been running the program and you wish to
+debug a core file instead, you must kill the subprocess in which the
+program is running.  To do this, use the @samp{kill} command
+(@pxref{Kill Process}).
+
+@item load @var{filename}
+@kindex load
+This command will dynamically link @var{filename} on the current target,
+performing any necessary downloads, then add @var{filename}'s symbol
+table in the same way as the @samp{add-syms} command.
+
+@item add-syms @var{filename} @var{address}
+@kindex add-syms
+@cindex dynamic linking
+The @samp{add-syms} command reads additional symbol table information
+from the file @var{filename}.  You would use this command when that file
+has been dynamically loaded (by some other means) into the program that
+is running.  @var{address} should be the memory address at which the
+file has been loaded; _GDBN__ cannot figure this out for itself.
+
+The symbol table of the file @var{filename} is added to the symbol table
+originally read with the @samp{symbol-file} command.  You can use the
+@samp{add-syms} command any number of times; the new symbol data thus
+read keeps adding to the old.  The @samp{symbol-file} command forgets
+all the symbol data _GDBN__ has read.
+
+@item info files
+@itemx info target
+@kindex info files
+@kindex info target
+@samp{info files} and @samp{info target} are synonymous; both print the
+current targets (@pxref{Targets}), including the names of the
+executable and core dump files currently in use by _GDBN__, and the files
+from which symbols were loaded.
+
+Beware: the similar command @samp{info targets} lists all possible
+targets rather than current ones.
+
+@end table
+
+All file-specifying commands allow both absolute and relative file names
+as arguments.  _GDBN__ always converts the file name to an absolute path
+name and remembers it that way.
+
+@kindex sharedlibrary
+@kindex share
+@cindex shared libraries
+
+_GDBN__ supports the SunOS shared library format.  Symbols from a shared
+library cannot be referenced before the shared library has been linked
+with the program.  (That is to say, after you type @samp{run} and 
+the function @code{main} has been entered; or when examining core
+files.)  Once the shared library has been linked in, you can use the
+following commands:
+
+@table @code
+@item sharedlibrary @var{regex}
+@itemx share @var{regex}
+Load shared object library symbols for files matching a UNIX regular
+expression.
+
+@item share
+@itemx sharedlibrary
+Load symbols for all shared libraries.
+
+@item info share
+@itemx info sharedlibrary
+@kindex info sharedlibrary
+@kindex info share
+Print the names of the shared libraries which are currently loaded.
+@end table
+
+@section Errors Reading Symbols
+While a symbol file is being read, _GDBN__ will occasionally encounter
+problems, such as symbol types it does not recognize, or known bugs in
+compiler output.  By default, it prints one message about each such
+type of problem, no matter how many times the problem occurs.  You can
+ask it to print more messages, to see how many times the problems occur,
+or can shut the messages off entirely, with the @samp{set 
+complaints} command (@xref{Messages/Warnings}).
+
+The messages currently printed, and their meanings, are:
+
+@table @code
+@item inner block not inside outer block in @var{symbol}
+
+The symbol information shows where symbol scopes begin and end
+(such as at the start of a function or a block of statements).  This
+error indicates that an inner scope block is not fully contained
+in its outer scope blocks.  _GDBN__ circumvents the problem by treating
+the inner block as if it had the same scope as the outer block.
+@var{symbol} may be ``(don't know)'' if the outer block is not
+a function.
+
+@item block at @var{address} out of order
+
+The symbol information for symbol scope blocks should occur in 
+order of increasing addresses.  This error indicates that it does not
+do so.  _GDBN__ does not circumvent this problem, and will have trouble
+locating symbols in the source file whose symbols being read.  (You
+can often determine what source file is affected by specifying
+@samp{set verbose on}.  @xref{Messages/Warnings}.)
+
+@item bad block start address patched
+
+The symbol information for a symbol scope block has a start address
+smaller than the address of the preceding source line.  This is known
+to occur in the SunOS 4.1.1 (and earlier) C compiler.  _GDBN__ circumvents
+the problem by treating the symbol scope block as starting on the
+previous source line.
+
+@comment @item{encountered DBX-style class variable debugging information.
+@comment You seem to have compiled your program with "g++ -g0" instead of "g++ -g".
+@comment Therefore _GDBN__ will not know about your class variables}
+@comment 
+@comment This error indicates that the symbol information produced for a C++
+@comment program includes zero-size fields, which indicated static fields in
+@comment a previous release of the G++ compiler.  This message is probably
+@comment obsolete.
+@comment
+@item bad string table offset in symbol @var{n}
+
+@cindex foo
+Symbol number @var{n} contains a pointer into the string table which is
+larger than the size of the string table.  _GDBN__ circumvents the problem
+by considering the symbol to have the name @code{foo}, which may cause
+other problems if many symbols end up with this name.  
+
+@item unknown symbol type @code{0xNN}
+
+The symbol information contains new data types that _GDBN__ does not yet
+know how to read.  @code{0xNN} is the symbol type of the misunderstood
+information, in hexadecimal.  _GDBN__ circumvents the error by ignoring
+this symbol information.  This will usually allow the program to be
+debugged, though certain symbols will not be accessible.  If you
+encounter such a problem and feel like debugging it, you can debug _GDBP__
+with itself, breakpoint on "complain", then go "up" to
+read_dbx_symtab() and examine *bufp to see the symbol.
+
+@c @item stub type has NULL name
+@c 
+@c FIXME, Mike Tiemann needs to write about what this means.
+
+@item const/volatile indicator missing, got 'X'
+
+The symbol information for a C++ type is missing some information that
+the compiler should have output for it.
+
+@item C++ type mismatch between compiler and debugger
+
+The debugger could not parse a type specification output by the compiler
+for some C++ object.
+
+@end table
+
+@node     Targets,,,
+@chapter Specifying a Debugging Target 
+@cindex debugging target
+@kindex target
+A @dfn{target} is an interface between the debugger and a particular 
+kind of file or process.  
+
+Often, you will be able to run _GDBN__ in the same host environment as the
+program you are debugging; in that case, the debugging target can just be
+specified as a side effect of the @samp{file} or @samp{core} commands.
+When you need more flexibility---for example, running _GDBN__ on a
+physically separate host, controlling standalone systems over a
+serial port, or realtime systems over a TCP/IP connection---you can use
+the @samp{target} command.
+
+@node Active Targets,,,
+@section Active Targets
+@cindex stacking targets
+@cindex active targets
+@cindex multiple targets
+
+Targets are managed in three @dfn{strata} that correspond to different
+classes of target: processes, core files, and executable files.  This
+allows you to (for example) start a process and inspect its activity
+without abandoning your work on a core file.
+
+More than one target can potentially respond to a request.  In
+particular, when you access memory _GDBN__ will walk down the three strata of
+targets until it finds a target that can handle that particular address.
+
+Strata are always examined in a fixed order: first a process if there is
+one, then a core file if there is one, and finally an executable file if
+there is one of those.
+
+When you specify a new target in a given stratum, it replaces any target
+previously in that stratum.
+
+To get rid of a target without replacing it, use the @samp{detach}
+command.  The related command @samp{attach} provides you with a way of
+choosing a particular running process as a new target. @xref{Attach}.
+
+@node Target Commands,,,
+@section Commands for Managing Targets
+
+@table @code
+@item target @var{type} @var{parameters}
+Connects the _GDBN__ host environment to a target machine or process.  A
+target is typically a protocol for talking to debugging facilities.  You
+use the argument @var{type} to specify the type or protocol of the
+target machine; for example, @samp{target vxworks} for a TCP/IP link to
+a VxWorks system.
+
+Further @var{parameters} are interpreted by the target protocol, but
+typically include things like device names or host names to connect
+with, process numbers, and baud rates.  Executing 
+@example
+   target @var{type}
+@end example
+
+@noindent
+(without any parameters) will issue a message about what
+parameters are required for that target type.
+
+@item info targets
+@kindex info targets
+Displays the names of all targets available.  Beware: the similar
+command @samp{info target} displays targets currently in use rather than
+all available ones.  @samp{info files} gives the same information as
+@samp{info target} (@pxref{Files}).
+@end table
+
+Here are some common targets (available, or not, depending on _GDBN__
+configuration):
+
+@table @code
+@item target exec @var{prog}
+@kindex target exec
+An executable file.  @samp{target exec @var{prog}} is the same as
+@samp{exec-file @var{prog}}.
+
+@item target core @var{filename}
+@kindex target core
+A core dump file.  @samp{target core @var{filename}} is the same as
+@samp{core-file @var{filename}}.
+
+@item target remote @var{dev}
+@kindex target remote
+Remote serial target in _GDBP__-specific protocol.  The argument @var{dev}
+specifies what serial device to use for the connection (e.g.
+@code{/dev/ttya}).
+
+_if__(_AMD29K__)
+@item target amd-eb @var{dev} @var{speed} @var{PROG}
+@kindex target amd-eb
+@cindex AMD EB29K
+Remote PC-resident AMD EB29K board, attached over serial lines.
+@var{dev} is the serial device, as for @samp{target remote};
+@samp{speed} allows you to specify the linespeed; and @var{PROG} is the
+name of the program to be debugged, as it appears to DOS on the PC.
+@xref{EB29K Remote}.
+
+_fi__(_AMD29K__)
+_if__(_I960__)
+@item target nindy @var{devicename}
+@kindex target nindy
+An Intel 960 board controlled by a Nindy Monitor.  @var{devicename} is
+the name of the serial device to use for the connection, e.g.
+@samp{/dev/ttya}.  
+
+_fi__(_I960__)
+_if__(_VXWORKS__)
+@item target vxworks @var{machinename}
+@kindex target vxworks
+A VxWorks system, attached via TCP/IP.  The argument @var{machinename}
+is the target system's machine name or IP address.
+
+_fi__(_VXWORKS__)
+@end table
+
+_if__(_GENERIC__)
+Different targets are available on different configurations of _GDBN__; your
+configuration may have more or fewer targets.
+_fi__(_GENERIC__)
+
+@node Remote,,,
+@section Remote Debugging
+@cindex remote debugging
+
+If you are trying to debug a program running on a machine that can't run
+_GDBN__ in the usual way, it is often useful to use remote debugging.  For
+example, you might be debugging an operating system kernel, or debugging
+a small system which does not have a general purpose operating system
+powerful enough to run a full-featured debugger.  Currently _GDBN__ supports
+remote debugging over a serial connection, and (using Sun RPC) over a
+TCP/IP connection.
+
+The program to be debugged on the remote machine needs to contain a
+debugging device driver which talks to _GDBN__ over the serial line.  The
+same version of _GDBN__ that is used ordinarily can be used for this.
+Several sample remote debugging drivers are distributed with _GDBN__; see
+the @file{README} file in the _GDBN__ distribution for more information.
+
+For details of the communication protocol, see the comments in the _GDBN__
+source file @file{remote.c}.
+
+To start remote debugging, first run _GDBN__ and specify as an executable file
+the program that is running in the remote machine.  This tells _GDBN__ how
+to find the program's symbols and the contents of its pure text.  Then
+establish communication using the @samp{target remote} command with a device
+name as an argument.  For example:
+
+@example
+target remote /dev/ttyb
+@end example
+
+@noindent
+if the serial line is connected to the device named @file{/dev/ttyb}.  This
+will stop the remote machine if it is not already stopped.
+
+Now you can use all the usual commands to examine and change data and to
+step and continue the remote program.
+
+To resume the remote program and stop debugging it, use the @samp{detach}
+command.
+
+Other remote targets be available in your
+configuration of _GDBN__; use @samp{info targets} to list them.  
+
+@table @code
+@item reset
+@kindex reset
+For a target attached through a serial line, this command sends a
+``break'' to the remote target system; this is only useful if the target
+has been equipped with a circuit to perform a hard reset (or some other
+interesting action) when a break is detected.
+@end table
+
+@node Controlling _GDBN__,,,
+@chapter Controlling _GDBN__
+
+You can alter many aspects of _GDBN__'s interaction with you by using
+the @samp{set} command.
+
+@node Prompt,,,
+@section Prompt
+@cindex prompt
+_GDBN__ indicates its readiness to read a command by printing a string
+called the @dfn{prompt}.  This string is normally @samp{(_GDBP__)}.  You can
+change the prompt string with the @samp{set prompt} command.  For
+instance, when debugging _GDBN__ with _GDBN__, it is useful to change the prompt
+in one of the _GDBN__<>s so that you tell which one you are talking to.
+
+@table @code
+@item set prompt @var{newprompt}
+@kindex set prompt
+Directs _GDBN__ to use @var{newprompt} as its prompt string henceforth.
+@kindex show prompt
+@item show prompt
+Prints a line of the form: @samp{Gdb's prompt is: @var{your-prompt}}
+@end table
+
+@node Editing,,,
+@section Command Editing
+@cindex readline
+@cindex command line editing
+_GDBN__ reads its input commands via the @dfn{readline} interface.  This
+GNU library provides consistent behavior for programs which provide a
+command line interface to the user.  Advantages are @samp{emacs}-style
+or @samp{vi}-style inline editing of commands, @samp{csh}-like history
+substitution, and a storage and recall of command history across
+debugging sessions.
+
+You may control the behavior of command line editing in _GDBN__ with the
+command @samp{set}.  You may check the status of any of these settings
+with the command @samp{show}.
+
+@table @code
+@kindex set editing
+@cindex editing
+@item set editing
+@itemx set editing on
+Enable command line editing (enabled by default).
+
+@item set editing off
+Disable command line editing.
+
+@kindex show editing
+@item show editing
+Show whether command line editing is enabled.
+
+@node History,,,
+@section Command History
+@cindex history substitution
+@cindex history file
+@kindex set history file
+@item set history file @var{filename}
+Set the name of the _GDBN__ command history file to @var{filename}.  This is
+the file from which _GDBN__ will read an initial command history
+list or to which it will write this list when it exits.  This list is
+accessed through history expansion or through the history
+command editing characters listed below.  This file defaults to the
+value of the environmental variable @code{GDBHISTFILE}, or to
+@file{./.gdb_history} if this variable is not set.
+
+@cindex history write
+@kindex set history write
+@item set history write
+@itemx set history write on
+Record command history in a file, whose name may be specified with the
+@samp{set history file} command.  By default, this option is disabled.
+
+@item set history write off
+Stop recording command history in a file.
+
+@cindex history size
+@kindex set history size
+@item set history size @var{size}
+Set the number of commands which _GDBN__ will keep in its history list.
+This defaults to the value of the environmental variable
+@code{HISTSIZE}, or to 256 if this variable is not set.
+@end table
+
+@cindex history expansion
+History expansion assigns special meaning to the character @samp{!}.
+@iftex
+(@xref{Event Designators}.)
+@end iftex
+Since @samp{!} is also the logical not operator in C, history expansion
+is off by default. If you decide to enable history expansion with the
+@samp{set history expansion on} command, you may sometimes need to
+follow @samp{!} (when it is used as logical not, in an expression) with
+a space or a tab to prevent it from being expanded.  The readline
+history facilities will not attempt substitution on the strings
+@samp{!=} and @samp{!(}, even when history expansion is enabled.
+
+The commands to control history expansion are:
+
+@table @code
+
+@kindex set history expansion
+@item set history expansion on
+@itemx set history expansion
+Enable history expansion.  History expansion is off by default.
+
+@item set history expansion off
+Disable history expansion.
+
+The readline code comes with more complete documentation of
+editing and history expansion features.  Users unfamiliar with @samp{emacs}
+or @samp{vi} may wish to read it. 
+@iftex
+@xref{Command Line Editing}.
+@end iftex
+
+@kindex show history
+@item show history
+@itemx show history file
+@itemx show history write
+@itemx show history size
+@itemx show history expansion
+These commands display the state of the _GDBN__ history parameters.
+@samp{show history} by itself displays all four states.
+
+@end table
+
+@table @code
+@kindex info editing
+@item info editing
+Display the last ten commands in the command history.
+
+@item info editing @var{n}
+Print ten commands centered on command number @var{n}.
+
+@item info editing +
+Print ten commands just after the commands last printed.
+
+@end table
+
+@node Screen Size,,,
+@section Screen Size
+@cindex size of screen
+@cindex pauses in output
+Certain commands to _GDBN__ may produce large amounts of information output
+to the screen.  To help you read all of it, _GDBN__ pauses and asks you for
+input at the end of each page of output.  Type @key{RET} when you want
+to continue the output.  Normally _GDBN__ knows the size of the screen from
+the termcap data base together with the value of the @code{TERM}
+environment variable and the @code{stty rows} and @code{stty cols}
+settings. If this is not correct, you can override it with
+the @samp{set screen-height} and @samp{set screen-width} commands:
+
+_GDBN__ also uses the screen width setting to determine when to wrap lines
+of output.  Depending what is being printed, it tries to break the
+line at a readable place, rather than simply letting it overflow onto
+the following line.
+
+@table @code
+@item set screen-height @var{lpp}
+@itemx show screen-height
+@itemx set screen-width @var{cpl}
+@itemx show screen-width
+@kindex set screen-height
+@kindex set screen-width
+@kindex show screen-width
+@kindex show screen-height
+These @samp{set} commands specify a screen height of @var{lpp} lines and
+a screen width of @var{cpl} characters.  The associated @samp{show}
+commands display the current settings.
+
+If you specify a height of zero lines, _GDBN__ will not pause during output
+no matter how long the output is.  This is useful if output is to a file
+or to an editor buffer.
+@end table
+
+@node Numbers,,,
+@section Numbers
+@cindex number representation
+@cindex entering numbers
+You can always enter numbers in octal, decimal, or hexadecimal in _GDBN__ by
+the usual conventions: octal numbers begin with @samp{0}, decimal
+numbers end with @samp{.}, and hexadecimal numbers begin with @samp{0x}.
+Numbers that begin with none of these are, by default, entered in base
+10; likewise, the default display for numbers---when no particular
+format is specified---is base 10.  You can change the default base for
+both input and output with the @samp{set radix} command.
+
+@table @code
+@kindex set radix
+@item set radix @var{base}
+Set the default base for numeric input and display.  Supported choices
+for @var{base} are decimal 8, 10, 16.  @var{base} must itself be
+specified either unambiguously or using the current default radix; for
+example, any of
+
+@example
+set radix 012
+set radix 10.
+set radix 0xa
+@end example
+
+@noindent
+will set the base to decimal.  On the other hand, @samp{set radix 10}
+will leave the radix unchanged no matter what it was.
+
+@kindex show radix
+@item show radix
+Display the current default base for numeric input and display.
+
+@end table
+
+@node Messages/Warnings,,,
+@section Optional Warnings and Messages
+By default, _GDBN__ is silent about its inner workings.  If you are running
+on a slow machine, you may want to use the @samp{set verbose} command.
+It will make _GDBN__ tell you when it does a lengthy internal operation, so
+you won't think it has crashed.
+
+Currently, the messages controlled by @samp{set verbose} are those which
+announce that the symbol table for a source file is being read
+(@pxref{Files}, in the description of the command
+@samp{symbol-file}).
+@c The following is the right way to do it, but emacs 18.55 doesn't support
+@c @ref, and neither the emacs lisp manual version of texinfmt or makeinfo
+@c is released.  
+@ignore
+see @samp{symbol-file} in @ref{Files}).
+@end ignore
+
+@table @code
+@kindex set verbose
+@item set verbose on
+Enables _GDBN__'s output of certain informational messages.
+
+@item set verbose off
+Disables _GDBN__'s output of certain informational messages.
+
+@kindex show verbose
+@item show verbose
+Displays whether @samp{set verbose} is on or off.
+@end table
+
+By default, if _GDBN__ encounters bugs in the symbol table of an object file,
+it prints a single message about each type of problem it finds, then 
+shuts up.  You can suppress these messages, or allow more than one such
+message to be printed if you want to see how frequent the problems are.
+@xref{Files}.
+
+@table @code
+@kindex set complaints
+@item set complaints @var{limit}
+Permits _GDBN__ to output @var{limit} complaints about each type of unusual
+symbols before becoming silent about the problem.  Set @var{limit} to
+zero to suppress all complaints; set it to a large number to prevent
+complaints from being suppressed.
+
+@kindex show complaints
+@item show complaints
+Displays how many symbol complaints _GDBN__ is permitted to produce.
+@end table
+
+By default, _GDBN__ is cautious, and asks what sometimes seem to be a lot of
+stupid questions.  For example, if you try to run a program which is
+already running:
+@example
+
+(_GDBP__) run
+The program being debugged has been started already.
+Start it from the beginning? (y or n) 
+@end example
+
+If you're willing to unflinchingly face the consequences of your own
+commands, you can disable this ``feature'':
+
+@table @code
+@kindex set caution
+@cindex flinching
+@cindex stupid questions
+@item set caution off
+Disables cautious questions.
+
+@item set caution on
+Enables cautious questions (the default).
+
+@item show caution
+@kindex show caution
+Displays state of cautious questions.
+@end table
+
+@node Sequences,,,
+@chapter Canned Sequences of Commands
+
+Aside from breakpoint commands (@pxref{Break Commands}),_GDBN__ provides two
+ways to store sequences of commands for execution as a unit:
+user-defined commands and command files.
+
+@node Define,,,
+@section User-Defined Commands
+
+@cindex user-defined command
+A @dfn{user-defined command} is a sequence of _GDBN__ commands to which you
+assign a new name as a command.  This is done with the @samp{define}
+command.
+
+@table @code
+@item define @var{commandname}
+@kindex define
+Define a command named @var{commandname}.  If there is already a command
+by that name, you are asked to confirm that you want to redefine it.
+
+The definition of the command is made up of other _GDBN__ command lines,
+which are given following the @samp{define} command.  The end of these
+commands is marked by a line containing @samp{end}.
+
+@item document @var{commandname}
+@kindex document
+Give documentation to the user-defined command @var{commandname}.  The
+command @var{commandname} must already be defined.  This command reads
+lines of documentation just as @samp{define} reads the lines of the
+command definition, ending with @samp{end}.  After the @samp{document}
+command is finished, @samp{help} on command @var{commandname} will print
+the documentation you have specified.
+
+You may use the @samp{document} command again to change the
+documentation of a command.  Redefining the command with @samp{define}
+does not change the documentation.
+@end table
+
+User-defined commands do not take arguments.  When they are executed, the
+commands of the definition are not printed.  An error in any command
+stops execution of the user-defined command.
+
+Commands that would ask for confirmation if used interactively proceed
+without asking when used inside a user-defined command.  Many _GDBN__ commands
+that normally print messages to say what they are doing omit the messages
+when used in a user-defined command.
+
+@node Command Files,,,
+@section Command Files
+
+@cindex command files
+A command file for _GDBN__ is a file of lines that are _GDBN__ commands.  Comments
+(lines starting with @samp{#}) may also be included.  An empty line in a
+command file does nothing; it does not mean to repeat the last command, as
+it would from the terminal.
+
+@cindex init file
+@cindex @file{_GDBINIT__}
+When you start _GDBN__, it automatically executes commands from its
+@dfn{init files}.  These are files named @file{_GDBINIT__}.  _GDBN__
+reads the init file (if any) in your home directory and then the init
+file (if any) in the current working directory.  (The init files are not
+executed if the @samp{-nx} option is given.)  You can also request the
+execution of a command file with the @samp{source} command:
+
+@table @code
+@item source @var{filename}
+@kindex source
+Execute the command file @var{filename}.
+@end table
+
+The lines in a command file are executed sequentially.  They are not
+printed as they are executed.  An error in any command terminates execution
+of the command file.
+
+Commands that would ask for confirmation if used interactively proceed
+without asking when used in a command file.  Many _GDBN__ commands that
+normally print messages to say what they are doing omit the messages
+when called from command files.
+
+@node Output,,,
+@section Commands for Controlled Output
+
+During the execution of a command file or a user-defined command, the only
+output that appears is what is explicitly printed by the commands of the
+definition.  This section describes three commands useful for generating
+exactly the output you want.
+
+@table @code
+@item echo @var{text}
+@kindex echo
+@comment I don't consider backslash-space a standard C escape sequence
+@comment because it's not in ANSI.
+Print @var{text}.  Nonprinting characters can be included in @var{text}
+using C escape sequences, such as @samp{\n} to print a newline.  @b{No
+newline will be printed unless you specify one.} In addition to the
+standard C escape sequences a backslash followed by a space stands for a
+space.  This is useful for outputting a string with spaces at the
+beginning or the end, since leading and trailing spaces are otherwise
+trimmed from all arguments.  Thus, to print @samp{@ and foo =@ }, use the
+command @samp{echo \@ and foo = \@ }.
+@comment FIXME: verify hard copy actually issues enspaces for '@ '!  Will this
+@comment        confuse texinfo?
+
+A backslash at the end of @var{text} can be used, as in C, to continue
+the command onto subsequent lines.  For example,
+
+@example
+echo This is some text\n\
+which is continued\n\
+onto several lines.\n
+@end example
+
+produces the same output as
+
+@example
+echo This is some text\n
+echo which is continued\n
+echo onto several lines.\n
+@end example
+
+@item output @var{expression}
+@kindex output
+Print the value of @var{expression} and nothing but that value: no
+newlines, no @samp{$@var{nn} = }.  The value is not entered in the
+value history either.  @xref{Expressions} for more information on
+expressions. 
+
+@item output/@var{fmt} @var{expression}
+Print the value of @var{expression} in format @var{fmt}.
+@xref{Output formats}, for more information.
+
+@item printf @var{string}, @var{expressions}@dots{}
+@kindex printf
+Print the values of the @var{expressions} under the control of
+@var{string}.  The @var{expressions} are separated by commas and may
+be either numbers or pointers.  Their values are printed as specified
+by @var{string}, exactly as if the program were to execute
+
+@example
+printf (@var{string}, @var{expressions}@dots{});
+@end example
+
+For example, you can print two values in hex like this:
+
+@example
+printf "foo, bar-foo = 0x%x, 0x%x\n", foo, bar-foo
+@end example
+
+The only backslash-escape sequences that you can use in the format
+string are the simple ones that consist of backslash followed by a
+letter.
+@end table
+
+@node Emacs,,,
+@chapter Using _GDBN__ under GNU Emacs
+
+@cindex emacs
+A special interface allows you to use GNU Emacs to view (and
+edit) the source files for the program you are debugging with
+_GDBN__.
+
+To use this interface, use the command @kbd{M-x gdb} in Emacs.  Give the
+executable file you want to debug as an argument.  This command starts
+_GDBN__ as a subprocess of Emacs, with input and output through a newly
+created Emacs buffer.
+
+Using _GDBN__ under Emacs is just like using _GDBN__ normally except for two
+things:
+
+@itemize @bullet
+@item
+All ``terminal'' input and output goes through the Emacs buffer.  This
+applies both to _GDBN__ commands and their output, and to the input and
+output done by the program you are debugging.
+
+This is useful because it means that you can copy the text of previous
+commands and input them again; you can even use parts of the output
+in this way.
+
+All the facilities of Emacs' Shell mode are available for this purpose.
+
+@item
+_GDBN__ displays source code through Emacs.  Each time _GDBN__ displays a
+stack frame, Emacs automatically finds the source file for that frame
+and puts an arrow (_0__@samp{=>}_1__) at the left margin of the current line.
+Emacs uses a separate buffer for source display, and splits the window
+to show both your _GDBN__ session and the source.
+
+Explicit _GDBN__ @samp{list} or search commands still produce output as
+usual, but you probably will have no reason to use them.
+@end itemize
+
+@quotation
+@emph{Warning:} If the directory where your program resides is not your
+current directory, it can be easy to confuse Emacs about the location of
+the source files, in which case the auxiliary display buffer will not
+appear to show your source.  _GDBN__ can find programs by searching your
+environment's @samp{PATH} variable, so the _GDBN__ I/O session will proceed
+normally; but Emacs doesn't get enough information back from _GDBN__ to
+locate the source files in this situation.  To avoid this problem,
+either start _GDBN__ mode from the directory where your program resides, or
+specify a full path name when prompted for the @kbd{M-x gdb} argument.
+
+A similar confusion can result if you use the _GDBN__ @samp{file} command to
+switch to debugging a program in some other location, from an existing
+_GDBN__ I/O buffer in Emacs.
+@end quotation
+
+By default, @kbd{M-x gdb} calls the program called ``@code{gdb}''.  If
+you need to call _GDBN__ by a different name (for example, if you keep
+several configurations around, with different names) you can set the
+Emacs variable @code{gdb-command-name}; for example,
+@example
+(setq gdb-command-name "mygdb")
+@end example
+@noindent
+(preceded by @kbd{ESC ESC}, or typed in the @code{*scratch*} buffer, or
+in your @samp{.emacs} file) will make Emacs call the program named
+``@code{mygdb}'' instead.
+
+In the _GDBN__ I/O buffer, you can use these special Emacs commands in
+addition to the standard Shell mode commands:
+
+@table @kbd
+@item C-h m
+Describe the features of Emacs' _GDBN__ Mode.
+
+@item M-s
+Execute to another source line, like the _GDBN__ @samp{step} command; also
+update the display window to show the current file and location.
+
+@item M-n
+Execute to next source line in this function, skipping all function
+calls, like the _GDBN__ @samp{next} command.  Then update the display window
+to show the current file and location.
+
+@item M-i
+Execute one instruction, like the _GDBN__ @samp{stepi} command; update
+display window accordingly.
+
+@item M-x gdb-nexti
+Execute to next instruction, using the _GDBN__ @samp{nexti} command; update
+display window accordingly.
+
+@item C-c C-f
+Execute until exit from the selected stack frame, like the _GDBN__
+@samp{finish} command.
+
+@item M-c
+@comment C-c C-p in emacs 19
+Continue execution of the program, like the _GDBN__ @samp{cont} command.
+
+@item M-u
+@comment C-c C-u in emacs 19
+Go up the number of frames indicated by the numeric argument
+(@pxref{Arguments, , Numeric Arguments, emacs, The GNU Emacs Manual}),
+like the _GDBN__ @samp{up} command.@refill
+
+@item M-d
+@comment C-c C-d in emacs 19
+Go down the number of frames indicated by the numeric argument, like the
+_GDBN__ @samp{down} command.
+
+@item C-x &
+Read the number where the cursor is positioned, and insert it at the end
+of the _GDBN__ I/O buffer.  For example, if you wish to disassemble code
+around an address that was displayed earlier, type @kbd{disassemble};
+then move the cursor to the address display, and pick up the
+argument for @samp{disassemble} by typing @kbd{C-x &}.  
+
+You can customize this further on the fly by defining elements of the list
+@samp{gdb-print-command}; once it is defined, you can format or
+otherwise process numbers picked up by @kbd{C-x &} before they are
+inserted.  A numeric argument to @kbd{C-x &} will both flag that you
+wish special formatting, and act as an index to pick an element of the
+list.  If the list element is a string, the number to be inserted is
+formatted using the Emacs function @samp{format}; otherwise the number
+is passed as an argument to the corresponding list element.
+
+@item M-x gdb-display-frame
+Explicitly request display of the source code surrounding the current
+frame location, in another window.  _GDBN__ does this display automatically;
+but if, for example, you accidentally kill the buffer where it is
+displayed, this command is a way of getting it back.
+@end table
+
+In any source file, the Emacs command @kbd{C-x SPC} (@code{gdb-break})
+tells _GDBN__ to set a breakpoint on the source line point is on.
+
+The source files displayed in Emacs are in ordinary Emacs buffers
+which are visiting the source files in the usual way.  You can edit
+the files with these buffers if you wish; but keep in mind that _GDBN__
+communicates with Emacs in terms of line numbers.  If you add or
+delete lines from the text, the line numbers that _GDBN__ knows will cease
+to correspond properly to the code.
+
+@comment The following dropped because Epoch is nonstandard.  Reactivate
+@comment if/when v19 does something similar. ---pesch@cygnus.com 19dec1990
+@ignore
+@kindex emacs epoch environment  
+@kindex epoch
+@kindex inspect
+
+Version 18 of Emacs has a built-in window system called the @samp{epoch}
+environment.  Users of this environment can use a new command,
+@samp{inspect} which performs identically to @samp{print} except that
+each value is printed in its own window.
+@end ignore
+
+@node _GDBN__ Bugs,,,
+@comment  node-name,  next,  previous,  up
+@chapter Reporting Bugs in _GDBN__
+@cindex Bugs in _GDBN__
+@cindex Reporting Bugs in _GDBN__
+
+Your bug reports play an essential role in making _GDBN__ 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 _GDBN__ work better.  Bug
+reports are your contribution to the maintenance of _GDBN__.
+
+In order for a bug report to serve its purpose, you must include the
+information that enables us to fix the bug.
+
+@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
+@item
+@cindex Fatal Signal
+@cindex Core Dump
+If the debugger gets a fatal signal, for any input whatever, that is a
+_GDBN__ bug.  Reliable debuggers never crash.
+
+@item
+@cindex error on Valid Input
+If _GDBN__ produces an error message for valid input, that is a bug.
+
+@item
+@cindex Invalid Input
+If _GDBN__ does not produce an error message for invalid input,
+that is a bug.  However, you should note that your idea of
+``invalid input'' might be our idea of ``an extension'' or ``support
+for traditional practice''.
+
+@item
+If you are an experienced user of debugging tools, your suggestions
+for improvement of _GDBN__ are welcome in any case.
+@end itemize
+
+@node Bug Reporting,,,
+@section How to Report Bugs
+@cindex Bug Reports
+@cindex Compiler Bugs, Reporting
+
+A number of companies and individuals offer support for GNU products.
+If you obtained _GDBN__ from a support organization, we recommend you
+contact that organization first. 
+
+Contact information for many support companies and individuals is
+available in the file @samp{etc/SERVICE} in the GNU Emacs distribution.
+
+In any event, we also recommend that you send bug reports for _GDBN__ to one
+of these addresses:
+
+@example
+bug-gdb@@prep.ai.mit.edu
+@{ucbvax|mit-eddie|uunet@}!prep.ai.mit.edu!bug-gdb
+@end example
+
+@strong{Do not send bug reports to @samp{info-gdb}, or to
+@samp{help-gdb}, or to any newsgroups.} Most users of _GDBN__ do not want to
+receive bug reports.  Those that do, have arranged to receive @samp{bug-gdb}.
+
+The mailing list @samp{bug-gdb} has a newsgroup which serves as a
+repeater.  The mailing list and the newsgroup carry exactly the same
+messages.  Often people think of posting bug reports to the newsgroup
+instead of mailing them.  This appears to work, but it has one problem
+which can be crucial: a newsgroup posting does not contain a mail path
+back to the sender.  Thus, if we need to ask for more information, we
+may be unable to reach you.  For this reason, it is better to send bug
+reports to the mailing list.
+
+As a last resort, send bug reports on paper to:
+
+@example
+GNU Debugger Bugs
+545 Tech Square
+Cambridge, MA 02139
+@end example
+
+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 don't matter.  Thus, you might
+assume that the name of the variable you use in an example does not matter.
+Well, probably it doesn't, but one cannot be sure.  Perhaps the bug is a
+stray memory reference which happens to fetch from the location where that
+name is stored in memory; perhaps, if the name were different, the contents
+of that location would fool the debugger 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.  It isn't very important what happens if
+the bug is already known.  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 _GDBN__.  _GDBN__ announces it if you start with no
+arguments; you can also print it at any time using @samp{show version}.
+
+Without this, we won't know whether there is any point in looking for
+the bug in the current version of _GDBN__.
+
+@item
+A complete input script, and all necessary source files, that will
+reproduce the bug.  
+
+@item
+What compiler (and its version) was used to compile _GDBN__---e.g.
+``_GCC__-1.37.1''.
+
+@item
+What compiler (and its version) was used to compile _GDBN__.
+
+@item
+The command arguments you gave the compiler to compile that example and
+observe the bug.  For example, did you use @samp{-O}?  To guarantee
+you won't omit something important, list them all.
+
+If we were to try to guess the arguments, we would probably guess wrong
+and then we would not encounter the bug.
+
+@item
+The type of machine you are using, and the operating system name and
+version number.
+
+@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 _GDBN__ 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.
+
+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 _GDBN__ 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 @i{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 _GDBN__ source, send us context
+diffs.  If you even discuss something in the _GDBN__ source, refer to
+it by context, not by line number.
+
+The line numbers in our development sources don't 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, etc. 
+
+However, simplification is not vital; if you don't 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 don't 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 a program as complicated as _GDBN__ it is very hard to
+construct an example that will make the program follow a certain path
+through the code.  If you don't send us the example, we won't be able
+to construct one, so we won't be able to verify that the bug is fixed.
+
+And if we can't understand what bug you are trying to fix, or why your
+patch should be an improvement, we won't 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 can't guess right about such
+things without first using the debugger to find the facts.
+@end itemize
+
+@iftex
+@include readline/inc-readline.texinfo
+@include readline/inc-history.texinfo
+@end iftex
+
+@node Installing _GDBN__,,,
+@appendix Installing _GDBN__
+@cindex configuring _GDBN__
+@cindex installation
+
+The script @samp{config.gdb} automates the process of preparing _GDBN__ for
+installation; you can then use @samp{make} to actually build it.  For
+example, 
+
+@example
+config.gdb sun3os4
+make
+@end example
+
+@noindent
+is all that's required to install _GDBN__ on a Sun 3 running SunOS 4.  
+
+@table @code
+@kindex config.gdb
+@item config.gdb @var{machine}
+@itemx config.gdb -srcdir=@var{dir} @var{machine}
+This is the most usual way of configuring _GDBN__; to debug programs running
+on the same machine as _GDBN__ itself.  If you wish to build the _GDBN__ binaries
+in a completely different directory from the sources, specify a path to
+the source directory using the @samp{-srcdir} option.
+
+@item config.gdb -host
+@cindex host environments
+Display a list of supported host environments for _GDBN__.
+
+@item config.gdb @var{host} @var{target}
+@itemx config.gdb -srcdir=@var{dir} @var{host} @var{target}
+@cindex cross-debugging
+_GDBN__ can also be used as a cross-debugger, running on a machine of one
+type while debugging a program running on a machine of another type.
+You configure it this way by specifying first the @var{host}, then the
+@var{target} environment on the @code{config.gdb} argument list; the
+@var{host} is where _GDBN__ runs, and the @var{target} is where your program
+runs. @xref{Remote}.  Again, you can use @samp{-srcdir} to specify a
+path to the _GDBN__ source.
+
+@item config.gdb -target
+@cindex target environments
+Display a list of supported target environments for _GDBN__.
+@end table
+
+@node License,,,
+@unnumbered GNU GENERAL PUBLIC LICENSE
+@center Version 1, February 1989
+
+@display
+Copyright @copyright{} 1989 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software---to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS
+@end ifinfo
+
+@enumerate
+@item
+This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+``Program'', below, refers to any such program or work, and a ``work based
+on the Program'' means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as ``you''.
+
+@item
+You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+@item
+You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+@itemize @bullet
+@item
+cause the modified files to carry prominent notices stating that
+you changed the files and the date of any change; and
+
+@item
+cause the whole of any work that you distribute or publish, that
+in whole or in part contains the Program or any part thereof, either
+with or without modifications, to be licensed at no charge to all
+third parties under the terms of this General Public License (except
+that you may choose to grant warranty protection to some or all
+third parties, at your option).
+
+@item
+If the modified program normally reads commands interactively when
+run, you must cause it, when started running for such interactive use
+in the simplest and most usual way, to print or display an
+announcement including an appropriate copyright notice and a notice
+that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these
+conditions, and telling the user how to view a copy of this General
+Public License.
+
+@item
+You may charge a fee for the physical act of transferring a
+copy, and you may at your option offer warranty protection in
+exchange for a fee.
+@end itemize
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+@item
+You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+@itemize @bullet
+@item
+accompany it with the complete corresponding machine-readable
+source code, which must be distributed under the terms of
+Paragraphs 1 and 2 above; or,
+
+@item
+accompany it with a written offer, valid for at least three
+years, to give any third party free (except for a nominal charge
+for the cost of distribution) a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of
+Paragraphs 1 and 2 above; or,
+
+@item
+accompany it with the information you received as to where the
+corresponding source code may be obtained.  (This alternative is
+allowed only for noncommercial distribution and only if you
+received the program in object code or executable form alone.)
+@end itemize
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+@item
+You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+@item
+By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+@item
+Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+@item
+The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and ``any
+later version'', you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+@item
+If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+@item
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
+LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES
+SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
+WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+@end enumerate
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+@page
+@unnumberedsec Applying These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+``copyright'' line and a pointer to where the full notice is found.
+
+@smallexample
+@var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) 19@var{yy}  @var{name of author}
+
+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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+@end smallexample
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items---whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a ``copyright disclaimer'' for the program, if
+necessary.  Here is a sample; alter the names:
+
+@smallexample
+Yoyodyne, Inc., hereby disclaims all copyright interest in the
+program `Gnomovision' (a program to direct compilers to make passes
+at assemblers) written by James Hacker.
+
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end smallexample
+
+That's all there is to it!
+
+@node Index,,,
+@unnumbered Index
+
+@printindex cp
+
+@tex
+% I think something like @colophon should be in texinfo.  In the
+% meantime:
+\long\def\colophon{\hbox to0pt{}\vfill
+\centerline{The body of this manual is set in}
+\centerline{\fontname\tenrm,}
+\centerline{with headings in {\bf\fontname\tenbf}}
+\centerline{and examples in {\tt\fontname\tentt}.}
+\centerline{{\it\fontname\tenit\/} and}
+\centerline{{\sl\fontname\tensl\/}}
+\centerline{are used for emphasis.}\vfill}
+\page\colophon
+% Blame: pesch@cygnus.com, 28mar91.
+@end tex
+
+@contents
+@bye
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
new file mode 100644 (file)
index 0000000..e81274f
--- /dev/null
@@ -0,0 +1,218 @@
+\input texinfo
+@setfilename gdb-internals
+@ifinfo
+This file documents the internals of the GNU debugger GDB.
+
+Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+Contributed by Cygnus Support.  Written by John Gilmore.
+
+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 or distribute modified versions of this
+manual under the terms of the GPL (for which purpose this text may be
+regarded as a program in the language TeX).
+@end ifinfo
+
+@setchapternewpage odd
+@settitle GDB Internals
+@titlepage
+@title{Working in GDB}
+@subtitle{A guide to the internals of the GNU debugger}
+@author John Gilmore
+@author Cygnus Support
+@page
+@tex
+\def\$#1${{#1}}  % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision$}  % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1990, 1991 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.
+
+@end titlepage
+
+@node Top, Cleanups, (dir), (dir)
+
+@menu
+* Cleanups::                   Cleanups
+* Wrapping::                   Wrapping output lines
+* Releases::                   Configuring GDB for release
+* README::                     The README file
+* New Architectures::          Defining a new host or target architecture
+
+@end menu
+
+@node Cleanups, Wrapping, Top, Top
+@chapter Cleanups
+
+Cleanups are a structured way to deal with things that need to be done
+later.  When your code does something (like malloc some memory, or open
+a file) that needs to be undone later (e.g. free the memory or close
+the file), it can make a cleanup.  The cleanup will be done at some
+future point:  when the command is finished, when an error occurs, or
+when your code decides it's time to do cleanups.
+
+You can also discard cleanups, that is, throw them away without doing
+what they say.  This is only done if you ask that it be done.
+
+Syntax:
+
+@table @code
+@item old_chain = make_cleanup (function, arg);
+This makes a cleanup which will cause FUNCTION to be called with ARG
+(a char *) later.  The result, OLD_CHAIN, is a handle that can be
+passed to do_cleanups or discard_cleanups later.  Unless you are
+going to call do_cleanups or discard_cleanups yourself,
+you can ignore the result from make_cleanup.
+
+
+@item do_cleanups (old_chain);
+Performs all cleanups done since make_cleanup returned OLD_CHAIN.
+E.g.:   make_cleanup (a, 0); old = make_cleanup (b, 0); do_cleanups (old);
+will call b() but will not call a().  The cleanup that calls a() will remain
+in the cleanup chain, and will be done later unless otherwise discarded.
+
+@item discard_cleanups (old_chain);
+Same as do_cleanups except that it just removes the cleanups from the
+chain and does not call the specified functions.
+
+@end table
+
+Some functions, e.g. @code{fputs_filtered()} or @code{error()}, specify that they
+``should not be called when cleanups are not in place''.  This means
+that any actions you need to reverse in the case of an error or
+interruption must be on the cleanup chain before you call these functions,
+since they might never return to your code (they @samp{longjmp} instead).
+
+
+@node Wrapping, Releases, Cleanups, Top
+@chapter Wrapping output lines
+
+Output that goes through printf_filtered or fputs_filtered or
+fputs_demangled needs only to have calls to wrap_here() added 
+in places that would be good breaking points.  The utility routines
+will take care of actually wrapping if the line width is exceeded.
+
+The argument to wrap_here() is an indentation string which is printed
+ONLY if the line breaks there.  This argument is saved away and used
+later.  It must remain valid until the next call to wrap_here() or
+until a newline has been printed through the *_filtered functions.
+Don't pass in a local variable and then return!
+
+It is usually best to call wrap_here() after printing a comma or space.
+If you call it before printing a space, make sure that your indentation
+properly accounts for the leading space that will print if the line wraps
+there.
+
+Any function or set of functions that produce filtered output must finish
+by printing a newline, to flush the wrap buffer, before switching to
+unfiltered ("printf") output.  Symbol reading routines that print
+warnings are a good example.
+
+
+@node Releases, README, Wrapping, Top
+@chapter Configuring GDB for release
+
+
+GDB should be released after doing @samp{config.gdb none} in the top level
+directory.  This will leave a makefile there, but no tm- or xm- files.
+The makefile is needed, for example, for @samp{make gdb.tar.Z}@dots{}  If you
+have tm- or xm-files in the main source directory, C's include rules
+cause them to be used in preference to tm- and xm-files in the 
+subdirectories where the user will actually configure and build the
+binaries.
+
+@samp{config.gdb none} is also a good way to rebuild the top level Makefile
+after changing Makefile.dist, alldeps.mak, etc.
+
+
+
+@node README, New Architectures, Releases, Top
+@chapter The README file
+
+
+Check the README file, it often has useful information that does not
+appear anywhere else in the directory.
+
+
+
+@node New Architectures,  , README, Top
+@chapter Defining a new host or target architecture
+
+
+When building support for a new host and/or target, this will help you
+organize where to put the various parts.  @var{ARCH} stands for the
+architecture involved.
+
+Object files needed when the host system is an @var{ARCH} are listed in
+the file @file{xconfig/@var{ARCH}}, in the Makefile macro @samp{XDEPFILES
+= }@dots{}.  You can also define XXXXXX in there.
+
+There are some ``generic'' versions of routines that can be used by
+various host systems.  If these routines work for the @var{ARCH} host,
+you can just include the generic file's name (with .o, not .c) in
+@code{XDEPFILES}.  Otherwise, you will need to write routines that
+perform the same functions as the generic file, put them into
+@code{@var{ARCH}-xdep.c}, and put @code{@var{ARCH}-xdep.o} into
+@code{XDEPFILES}.  These generic host support files include:
+
+@example
+       coredep.c, coredep.o
+@end example
+
+@table @code
+@item fetch_core_registers()
+Support for reading registers out of a core file.  This routine calls
+@code{register_addr(}), see below.
+
+@item register_addr()
+If your @code{xm-@var{ARCH}.h} file defines the macro @code{REGISTER_U_ADDR(reg)} to be the
+offset within the @samp{user} struct of a register (represented as a GDB
+register number), @file{coredep.c} will define the @code{register_addr()} function
+and use the macro in it.  If you do not define @code{REGISTER_U_ADDR}, but
+you are using the standard @code{fetch_core_registers}, you
+will need to define your own version of @code{register_addr}, put it into
+your @code{@var{ARCH}-xdep.c} file, and be sure @code{@var{ARCH}-xdep.o} is in the @code{XDEPFILES} list.
+If you have your own @code{fetch_core_registers}, you only need to define
+@code{register_addr} if your @code{fetch_core_registers} calls it.  Many custom
+@code{fetch_core_registers} implementations simply locate the registers
+themselves.
+@end table
+
+Files needed when the target system is an @var{ARCH} are listed in the file
+@file{tconfig/@var{ARCH}}, in the @code{Makefile} macro @samp{TDEPFILES = }@dots{}.  You can also
+define XXXXXX in there.
+
+Similar generic support files for target systems are:
+
+@example
+       exec.c, exec.o:
+@end example
+
+This file defines functions for accessing files that are executable
+on the target system.  These functions open and examine an exec file,
+extract data from one, write data to one, print information about one,
+etc.  Now that executable files are handled with BFD, every architecture
+should be able to use the generic exec.c rather than its own custom code.
+
+@contents
+@bye
+
diff --git a/gdb/doc/refcard.tex b/gdb/doc/refcard.tex
new file mode 100644 (file)
index 0000000..c32695d
--- /dev/null
@@ -0,0 +1,403 @@
+%This file is TeX source for a reference card describing GDB, the GNU debugger.
+%Copyright (C) 1991 Free Software Foundation, Inc.
+%Permission is granted to make and distribute verbatim copies of
+%this reference provided the copyright notices and permission notices
+%are preserved on all copies.
+%
+%TeX markup is a programming language; accordingly this file is source
+%for a program to generate a reference.
+%
+%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 1, 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 can find a copy of the GNU General Public License in the GDB
+%manual; or write to the Free Software Foundation, Inc.,
+%675 Mass Ave, Cambridge, MA 02139, USA.
+%
+%You can contact the author as:  pesch@cygnus.com
+%
+%                                Roland Pesch
+%                                Cygnus Support
+%                                814 University Ave.
+%                                Palo Alto, CA 94301 USA
+%
+%                                +1 415 322 3811
+%
+%            Cygnus Support is an organization devoted to commercial
+%            support of free software.  For general information
+%            contact ``info@cygnus.com''
+%
+%
+\input threecol
+{%
+\def\$#1${{#1}}%   Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision$}%
+}
+\vsize=8in
+\hyphenpenalty=5000\tolerance=2000\raggedright
+%
+\font\bbf=cmbx10
+\font\vbbf=cmbx12
+\font\smrm=cmr6
+\font\brm=cmr10
+\font\rm=cmr8
+\font\it=cmti8
+\font\tt=cmtt8
+\normalbaselineskip=9pt\baselineskip=9pt
+%
+\parindent=0pt
+\parskip=0pt
+\footline={\vbox to0pt{\hss}}
+%
+\def\ctl#1{{\tt C-#1}}
+\def\opt#1{{\brm[{\rm #1}]}}
+\def\xtra#1{\noalign{\smallskip{\tt#1}}}
+%
+\long\def\sec#1;#2\endsec{\vskip 1pc
+\halign{%
+%COL 1 (of halign):
+\vtop{\hsize=1in\tt
+##\par\vskip 2pt
+}\quad
+%COL 2 (of halign):
+&\vtop{\hsize=2.1in\hangafter=1\hangindent=0.5em
+\rm ##\par\vskip 2pt}\cr
+%Tail of \long\def fills in halign body with \sec args:
+\noalign{{\bbf #1}\vskip 2pt}
+#2
+}
+}
+
+{\vbbf GDB QUICK REFERENCE}
+\vskip 5pt
+{\smrm GDB Version 4.00---Cygnus Support 1991}
+
+\sec Starting GDB;
+gdb&starts GDB, with no debugging files\cr
+gdb {\it program}&begin debugging {\it program}\cr
+gdb {\it program core}&debug coredump {\it core} produced by {\it program}\cr
+\endsec
+
+\sec Stopping GDB;
+quit&Exit GDB; abbreviate as {\tt q} or {\tt EOF}\par (eg \ctl{d})\cr
+INTERRUPT&(eg \ctl{c}) terminate current command\cr
+\endsec
+
+\sec Getting Help;
+help&List classes of commands\cr
+help {\it class}&One-line descriptions for commands in {\it class}\cr
+help {\it command}&Describe {\it command}\cr
+\endsec
+
+\sec Executing your Program;
+run {\it arglist}&start your program with {\it arglist}\cr
+run&start your program with current argument list\cr
+run $\ldots$ <{\it inf} >{\it outf}&start program with input, output
+redirected\cr
+\cr
+kill&Kill running program\cr
+\cr
+tty {\it dev}&Use {\it dev} as default i/o for next {\tt run}\cr
+set args {\it arglist}&specify {\it arglist} for next
+{\tt run}\cr
+set args&specify empty argument list\cr
+show args&display argument list\cr
+\cr
+show environment&show all environment variables\cr
+show env {\it var}&show value of environment variable {\it var}\cr
+set env {\it var} {\it expr}&set environment variable {\it var}\cr
+delete env {\it var}&Remove {\it var} from environment\cr
+\endsec
+
+\sec Shell Commands;
+cd {\it dir}&Change working directory to {\it dir}\cr
+pwd&Print working directory\cr
+make $\ldots$&Call ``{\tt make}''\cr
+shell {\it cmd}&Execute arbitrary shell command string\cr
+\endsec
+
+\vfill
+\centerline{\smrm \copyright 1991 Free Software Foundation, Inc.\qquad Permissions on back}
+\eject
+\sec Breakpoints and Watchpoints;
+break \opt{\it file\tt:}{\it line}&Set breakpoint at {\it line} number \opt{in \it file}\par 
+eg:\quad{\tt break main.c:37}\quad\cr
+break \opt{\it file\tt:}{\it fun}&Set breakpoint at {\it
+fun}() \opt{in \it file}\cr
+break +{\it offset}\par
+break -{\it offset}&Set break at offset from current stop\cr
+break *{\it addr}&Set breakpoint at address {\it addr}\cr
+break&Set breakpoint at next instruction\cr
+break $\ldots$ if {\it expr}&Break conditionally on nonzero {\it expr}\cr
+cond {\it bno} \opt{\it expr}&New conditional expression on breakpoint
+number {\it bno}; make unconditional if no {\it expr}\cr
+tbreak $\ldots$&Temporary break; disable when reached\cr
+rbreak {\it regex}&Break on all functions matching {\it regex}\cr
+watch {\it expr}&Set a watchpoint for expression {\it expr}\cr
+catch {\it x}&Set breakpoint at C++ handler for exception {\it x}\cr
+\cr
+info break&Show defined breakpoints\cr
+info watch&Show defined watchpoints\cr
+\cr
+clear&Delete breakpoints at next instruction\cr
+clear \opt{\it file\tt:}{\it fun}&Delete breakpoints at entry to {\it fun}()\cr
+clear \opt{\it file\tt:}{\it line}&Delete breakpoints on source line \cr
+delete \opt{{\it bnos}}&Delete breakpoints numbered {\it bnos};
+\opt{or all breakpoints}\cr
+\cr
+disable \opt{{\it bnos}}&Disable breakpoints {\it bnos} \opt{or all}\cr
+enable {\it bnos}&Enable breakpoints {\it bnos} \opt{or all}\cr
+enable once {\it bnos}&Enable breakpoints; disable again when
+reached\cr
+enable del {\it bnos}&Enable breakpoints; delete when reached\cr
+\cr
+ignore {\it bno} {\it count}&Ignore breakpoint number {\it bno}, {\it count}
+times\cr
+\cr
+commands {\it bno}\par
+\qquad {\it command list}&Execute GDB {\it command list} every time breakpoint {\it bno} is reached\cr
+end&(use only with {\tt commands}) End of {\it command list}\cr
+\endsec
+
+\sec Signals;
+handle {\it signal} {\it act}&Specify GDB actions when {\it signal} occurs:\cr
+\quad print&Announce when signal occurs\cr
+\quad noprint&Be silent when signal occurs\cr
+\quad stop&Halt execution on signal\cr
+\quad nostop&Do not halt execution\cr
+\quad pass&Allow your program to handle signal\cr
+\quad nopass&Do not allow your program to see signal\cr
+info signal&Show table of signals and GDB action for each\cr
+\endsec
+
+\vfill\eject
+\sec Execution Control;
+continue \opt{\it count}\par
+c \opt{\it count}&Continue running; if {\it count} specified, ignore
+this breakpoint next {\it count} times\cr
+\cr
+step \opt{\it count}\par
+s \opt{\it count}&Execute until another line reached; repeat {\it count} times if
+specified\cr
+\cr
+stepi \opt{\it count}\par
+si \opt{\it count}&Step by machine instructions rather than source
+lines\cr
+\cr
+next \opt{\it count}\par
+n \opt{\it count}&Execute next line, including any function calls.\cr
+\cr
+nexti \opt{\it count}\par
+ni \opt{\it count}&Next machine instruction rather than source
+line\cr
+\cr
+until \opt{\it location}&Run until next instruction (or {\it
+location}) reached\cr
+\cr
+finish&Run until selected stack frame returns\cr
+return \opt{\it expr}&Pop selected stack frame without executing,
+optionally setting return value\cr
+\cr
+signal {\it num}&Resume execution with signal {\it num} (none if {\tt 0})\cr
+jump {\it line}\par
+jump *{\it address}&Resume execution at specified {\it line} number or
+{\it address}\cr
+set var {\it expr}&Evaluate {\it expr} without displaying it; use for
+altering program variables\cr
+\endsec
+
+\sec Debugging Targets;
+target {\it type} {\it param}&Connect to target machine, process, or file\cr
+info targets&Display available targets\cr
+attach {\it param}&Connect to another target of same type\cr
+detach&Release target from GDB control\cr
+\endsec
+
+\sec Expressions;
+{\it expr}&An expression in C or C++ (including function calls), or:\cr
+{\it addr\/}@{\it len}&An array of {\it len} elements beginning at {\it
+addr}\cr
+{\it file}::{\it nm}&A variable or function {\it nm} defined in {\it
+file}\cr
+$\tt\{${\it type}$\tt\}${\it addr}&Read memory at {\it addr} as specified
+{\it type}\cr
+print \opt{\tt/{\it f}\/} {\it expr}\par
+p \opt{\tt/{\it f}\/} {\it expr}&Display the value of an expression\par 
+in format {\it f}:\cr
+\qquad x&hexadecimal\cr
+\qquad d&signed decimal\cr
+\qquad u&unsigned decimal\cr
+\qquad o&octal\cr
+\qquad a&address, absolute and relative\cr
+\qquad c&character constant\cr
+\qquad f&floating point\cr
+call \opt{\tt /{\it f}\/} {\it expr}&Like {\tt print} but does not display
+{\tt void}\cr
+\endsec
+
+\vfill\eject
+\sec Memory;
+x \opt{\tt/{\it Nuf}\/} {\it expr}&Examine memory at address {\it expr};
+optional format spec follows slash.\cr
+\quad {\it N}&Count of how many units to display;\cr
+\quad {\it u}&Unit size; one of\cr
+&{\tt\qquad b}\ individual bytes\cr
+&{\tt\qquad h}\ halfwords (two bytes)\cr
+&{\tt\qquad w}\ words (four bytes)\cr
+&{\tt\qquad g}\ giant words (eight bytes)\cr
+\quad {\it f}&Printing format.  Any {\tt print} format, or\cr
+&{\tt\qquad s}\ Null-terminated string\cr
+&{\tt\qquad i}\ Machine instructions\cr
+disassem \opt{\it addr}&Display range of memory as machine
+instructions; function surrounding {\it addr} or program counter, or range between two arguments\cr
+\endsec
+
+\sec Automatic Display;
+display \opt{\tt/\it f\/} {\it expr}&Show value of {\it expr} each time
+program stops \opt{according to format {\it f}\/}\cr
+display&Display all enabled expressions on list\cr
+undisplay {\it dnos}&Remove number(s) {\it dnos} from list of
+automatically displayed expressions\cr
+disable dis {\it dnos}&Disable display for expression(s) number {\it
+dnos}\cr
+enable dis {\it dnos}&Enable display for expression(s) number {\it
+dnos}\cr
+info display&Show numbered list of expressions to display\cr
+\endsec
+
+\sec Program Stack;
+backtrace \opt{\it n}\par
+bt \opt{\it n}&Print trace of all frames in stack; or of {\it n}
+frames---innermost if {\it n}{\tt >0}, outermost if {\it n}{\tt <0}\cr
+frame \opt{\it n}&Select frame number {\it n} or frame at address {\it
+n}; if no {\it n}, display current frame\cr
+up {\it n}&Select frame {\it n} frames up\cr
+down {\it n}&Select frame {\it n} frames down\cr
+info frame \opt{\it addr}&Description of selected frame, or frame at
+{\it addr}\cr
+info args&Arguments of selected frame\cr
+info locals&Local variables of selected frame\cr
+info catch&Exception handlers active in selected frame\cr
+\endsec
+
+\sec Symbol Table;
+info address {\it s}&Show where symbol {\it s} is stored\cr
+info func \opt{\it regex}&Show names, types of defined functions
+(all, or matching {\it regex})\cr
+info var \opt{\it regex}&Show names, types of global variables (all,
+or matching {\it regex})\cr
+info sources&Show all sources having debugging information\cr
+whatis {\it expr}\par
+ptype {\it expr}&Show data type of {\it expr} without evaluating; {\tt
+ptype} gives more detail\cr
+ptype {\it type}&Describe type, struct, union, or enum\cr
+\endsec
+
+\vfill\eject
+\sec Controlling GDB;
+set {\it param} {\it expr}&Set one of GDB's internal parameters,
+controlling its interaction with you\cr
+show {\it param}&Display current setting of a GDB parameter\cr
+\xtra{\rm Parameters understood by {\tt set} and {\tt show}:}
+\quad addressp {\it on/off}&print memory addresses in stacks,
+structs\cr
+\quad array-max {\it limit}&Number of elements to display from an
+array\cr
+\quad arraypr {\it off/on}&Compact or attractive format for
+arrays\cr
+\quad caution {\it on/off}&Enable or disable cautionary queries\cr
+\quad editing {\it on/off}&Control {\tt readline} command-line editing\cr
+\quad history&({\tt h}) covers a number of options:\cr
+\quad h exp {\it off/on}&Disable or enable {\tt readline} history expansion\cr
+\quad h file {\it filename}&File for recording GDB command history\cr
+\quad h size {\it size}&Number of commands kept in history list\cr
+\quad h write {\it off/on}&Control use of external file for
+command history\cr
+\cr
+\quad pretty {\it off/on}&Compact or indented format for struct
+display\cr
+\quad prompt {\it str}&Use {\it str} as GDB prompt\cr
+\quad radix {\it base}&Octal, decimal, or hex number representation\cr
+\quad screen-h {\it lpp}&Number of lines before pause in
+display\cr
+\quad screen-w {\it cpl}&Number of characters before line folded\cr
+\quad unionpr {\it on/off}&Enable or disable display of unions in
+structs\cr
+\quad verbose {\it on/off}&Control messages when loading
+symbol table\cr
+\quad vtblpr {\it off/on}&Display of C++ virtual function tables\cr
+info editing&Show last 10 commands\cr
+info editing {\it n}&Show 10 commands around number {\it n}\cr
+info editing +&Show next 10 commands\cr
+\endsec
+
+\sec Working Files;
+file {\it name}&Use {\it file} for symbols and executable\cr
+core {\it name}&Read {\it file} as coredump\cr
+exec {\it name}&Use {\it file} as executable only\cr
+symbol {\it name}&Use only symbol table from {\it file}\cr
+load {\it file} {\it addr}&Read additional symbols from {\it file},
+dynamically loaded at {\it addr}\cr
+info files&Display working files and targets in use\cr
+\cr
+share \opt{\it regex}&Add symbol information for shared libraries
+matching {\it regex}, or all shared libraries\cr
+info share&List names of shared libraries currently loaded\cr
+\endsec
+
+\vfill\eject
+\sec Source Files;
+dir {\it name}&Add directory {\it name} to front of source path\cr
+dir&Clear source path\cr
+info dir&Show current source path\cr
+\cr
+list&Show next ten lines of source\cr
+list -&Show previous ten lines\cr
+list {\it lines}&Display source centered around {\it lines}, 
+specified as one of:\cr
+\quad{\opt{\it file\tt:}\it num}&Line number \opt{in named file}\cr
+\quad{\opt{\it file\tt:}\it function}&Beginning of function \opt{in
+named file}\cr
+\quad{\tt +\it off}&{\it off} lines after last printed\cr
+\quad{\tt -\it off}&{\it off} lines previous to last printed\cr
+\quad{\tt*\it address}&Line containing {\it address}\cr
+list {\it f},{\it l}&from line {\it f} to line {\it l}\cr
+info line {\it num}&Show starting, ending addresses of compiled code for
+source line {\it num}\cr
+forw {\it regex}&Search following source lines for {\it regex}\cr
+rev {\it regex}&Search preceding source lines for {\it regex}\cr
+\endsec
+
+\sec GDB under GNU Emacs;
+M-x gdb&Run GDB under Emacs\cr
+\ctl{h} m&Describe GDB mode\cr
+M-s&Step one line ({\tt step})\cr
+M-n&Next line ({\tt next})\cr
+M-i&Step one instruction ({\tt stepi})\cr
+\ctl{c} \ctl{f}&Finish current stack frame ({\tt finish})\cr
+M-c&Continue ({\tt cont})\cr
+M-u&Up {\it arg} frames ({\tt up})\cr
+M-d&Down {\it arg} frames ({\tt down})\cr
+\ctl{x} SPC&(in source file) set break at point\cr
+\endsec
+
+
+\vfill
+{\smrm\parskip=6pt
+\centerline{Copyright \copyright 1991 Free Software Foundation, Inc.}
+\centerline{Roland Pesch (pesch@cygnus.com), January 1991---\manvers}
+
+This card may be freely distributed under the terms of the GNU
+General Public License.
+
+Please contribute to development of this card by annotating it.
+
+No author assumes any responsibility for any errors on this card.}
+\end
diff --git a/gdb/doc/threecol.tex b/gdb/doc/threecol.tex
new file mode 100755 (executable)
index 0000000..604101e
--- /dev/null
@@ -0,0 +1,28 @@
+%Three-column format for landscape printing on 8.5x11 paper
+%pesch 1990 december 31
+%We want output .25 inch *from paper edge*; i.e. -.75in from TeX default
+\hoffset=-0.8in \voffset=-0.75in
+\newdimen\fullhsize
+\fullhsize=10.5in \hsize=3.3in
+\def\fulline{\hbox to \fullhsize}
+\let\lcr=L \newbox\leftcolumn\newbox\centercolumn
+\output={\if L\lcr
+            \global\setbox\leftcolumn=\columnbox \global\let\lcr=C
+        \else
+            \if C\lcr
+               \global\setbox\centercolumn=\columnbox \global\let\lcr=R
+            \else \tripleformat \global\let\lcr=L
+            \fi
+         \fi
+%         \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+      }
+\def\tripleformat{\shipout\vbox{\fulline{\box\leftcolumn\hskip .2in plus1fil
+                                         \box\centercolumn\hskip .2in plus1fil
+                                         \columnbox}
+                              }
+                 \advancepageno}
+\def\columnbox{\leftline{\pagebody}}
+\def\bye{\par\vfill
+         \supereject
+         \if R\lcr \null\vfill\eject\fi
+         \end}
diff --git a/gdb/environ.c b/gdb/environ.c
new file mode 100644 (file)
index 0000000..4109472
--- /dev/null
@@ -0,0 +1,187 @@
+/* environ.c -- library for manipulating environments for GNU.
+   Copyright (C) 1986, 1989 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#include "environ.h"
+#include <string.h>
+
+extern char *xmalloc ();
+extern char *xrealloc ();
+extern void free ();
+\f
+/* Return a new environment object.  */
+
+struct environ *
+make_environ ()
+{
+  register struct environ *e;
+
+  e = (struct environ *) xmalloc (sizeof (struct environ));
+
+  e->allocated = 10;
+  e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
+  e->vector[0] = 0;
+  return e;
+}
+
+/* Free an environment and all the strings in it.  */
+
+void
+free_environ (e)
+     register struct environ *e;
+{
+  register char **vector = e->vector;
+
+  while (*vector)
+    free (*vector++);
+
+  free (e);
+}
+
+/* Copy the environment given to this process into E.
+   Also copies all the strings in it, so we can be sure
+   that all strings in these environments are safe to free.  */
+
+void
+init_environ (e)
+     register struct environ *e;
+{
+  extern char **environ;
+  register int i;
+
+  for (i = 0; environ[i]; i++) /*EMPTY*/;
+
+  if (e->allocated < i)
+    {
+      e->allocated = max (i, e->allocated + 10);
+      e->vector = (char **) xrealloc ((char *)e->vector,
+                                     (e->allocated + 1) * sizeof (char *));
+    }
+
+  bcopy (environ, e->vector, (i + 1) * sizeof (char *));
+
+  while (--i >= 0)
+    {
+      register int len = strlen (e->vector[i]);
+      register char *new = (char *) xmalloc (len + 1);
+      bcopy (e->vector[i], new, len + 1);
+      e->vector[i] = new;
+    }
+}
+
+/* Return the vector of environment E.
+   This is used to get something to pass to execve.  */
+
+char **
+environ_vector (e)
+     struct environ *e;
+{
+  return e->vector;
+}
+\f
+/* Return the value in environment E of variable VAR.  */
+
+char *
+get_in_environ (e, var)
+     struct environ *e;
+     char *var;
+{
+  register int len = strlen (var);
+  register char **vector = e->vector;
+  register char *s;
+
+  for (; s = *vector; vector++)
+    if (!strncmp (s, var, len)
+       && s[len] == '=')
+      return &s[len + 1];
+
+  return 0;
+}
+
+/* Store the value in E of VAR as VALUE.  */
+
+void
+set_in_environ (e, var, value)
+     struct environ *e;
+     char *var;
+     char *value;
+{
+  register int i;
+  register int len = strlen (var);
+  register char **vector = e->vector;
+  register char *s;
+
+  for (i = 0; s = vector[i]; i++)
+    if (!strncmp (s, var, len)
+       && s[len] == '=')
+      break;
+
+  if (s == 0)
+    {
+      if (i == e->allocated)
+       {
+         e->allocated += 10;
+         vector = (char **) xrealloc ((char *)vector,
+                                      (e->allocated + 1) * sizeof (char *));
+         e->vector = vector;
+       }
+      vector[i + 1] = 0;
+    }
+  else
+    free (s);
+
+  s = (char *) xmalloc (len + strlen (value) + 2);
+  strcpy (s, var);
+  strcat (s, "=");
+  strcat (s, value);
+  vector[i] = s;
+
+  /* Certain variables get exported back to the parent (e.g. our) 
+     environment, too.  */
+  if (!strcmp(var, "PATH")                     /* Object file location */
+   || !strcmp (var, "G960BASE")                /* Intel 960 downloads */
+   || !strcmp (var, "G960BIN")                         /* Intel 960 downloads */
+                               ) {
+    putenv (strsave (s));
+  }
+  return;
+}
+
+/* Remove the setting for variable VAR from environment E.  */
+
+void
+unset_in_environ (e, var)
+     struct environ *e;
+     char *var;
+{
+  register int len = strlen (var);
+  register char **vector = e->vector;
+  register char *s;
+
+  for (; s = *vector; vector++)
+    if (!strncmp (s, var, len)
+       && s[len] == '=')
+      {
+       free (s);
+       bcopy (vector + 1, vector,
+              (e->allocated - (vector - e->vector)) * sizeof (char *));
+       e->vector[e->allocated - 1] = 0;
+       return;
+      }
+}
diff --git a/gdb/environ.h b/gdb/environ.h
new file mode 100644 (file)
index 0000000..13f31f4
--- /dev/null
@@ -0,0 +1,39 @@
+/* Header for environment manipulation library.
+   Copyright (C) 1989, Free Software Foundation.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* We manipulate environments represented as these structures.  */
+
+struct environ
+{
+  /* Number of usable slots allocated in VECTOR.
+     VECTOR always has one slot not counted here,
+     to hold the terminating zero.  */
+  int allocated;
+  /* A vector of slots, ALLOCATED + 1 of them.
+     The first few slots contain strings "VAR=VALUE"
+     and the next one contains zero.
+     Then come some unused slots.  */
+  char **vector;
+};
+
+struct environ *make_environ ();
+void free_environ ();
+void init_environ ();
+char *get_in_environ ();
+void set_in_environ ();
+void unset_in_environ ();
+char **environ_vector ();
diff --git a/gdb/eval.c b/gdb/eval.c
new file mode 100644 (file)
index 0000000..0cf5cbf
--- /dev/null
@@ -0,0 +1,1042 @@
+/* Evaluate expressions for GDB.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "expression.h"
+#include "target.h"
+
+#define        NULL_TYPE       ((struct type *)0)
+
+\f
+/* Parse the string EXP as a C expression, evaluate it,
+   and return the result as a number.  */
+
+CORE_ADDR
+parse_and_eval_address (exp)
+     char *exp;
+{
+  struct expression *expr = parse_c_expression (exp);
+  register CORE_ADDR addr;
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+
+  addr = (CORE_ADDR) value_as_long (evaluate_expression (expr));
+  do_cleanups (old_chain);
+  return addr;
+}
+
+/* Like parse_and_eval_address but takes a pointer to a char * variable
+   and advanced that variable across the characters parsed.  */
+
+CORE_ADDR
+parse_and_eval_address_1 (expptr)
+     char **expptr;
+{
+  struct expression *expr = parse_c_1 (expptr, 0, 0);
+  register CORE_ADDR addr;
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+
+  addr = (CORE_ADDR) value_as_long (evaluate_expression (expr));
+  do_cleanups (old_chain);
+  return addr;
+}
+
+value
+parse_and_eval (exp)
+     char *exp;
+{
+  struct expression *expr = parse_c_expression (exp);
+  register value val;
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+
+  val = evaluate_expression (expr);
+  do_cleanups (old_chain);
+  return val;
+}
+
+/* Parse up to a comma (or to a closeparen)
+   in the string EXPP as an expression, evaluate it, and return the value.
+   EXPP is advanced to point to the comma.  */
+
+value
+parse_to_comma_and_eval (expp)
+     char **expp;
+{
+  struct expression *expr = parse_c_1 (expp, 0, 1);
+  register value val;
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+
+  val = evaluate_expression (expr);
+  do_cleanups (old_chain);
+  return val;
+}
+\f
+/* Evaluate an expression in internal prefix form
+   such as is constructed by expread.y.
+
+   See expression.h for info on the format of an expression.  */
+
+static value evaluate_subexp ();
+static value evaluate_subexp_for_address ();
+static value evaluate_subexp_for_sizeof ();
+static value evaluate_subexp_with_coercion ();
+
+/* Values of NOSIDE argument to eval_subexp.  */
+enum noside
+{ EVAL_NORMAL,
+  EVAL_SKIP,                   /* Only effect is to increment pos.  */
+  EVAL_AVOID_SIDE_EFFECTS,     /* Don't modify any variables or
+                                  call any functions.  The value
+                                  returned will have the correct
+                                  type, and will have an
+                                  approximately correct lvalue
+                                  type (inaccuracy: anything that is
+                                  listed as being in a register in
+                                  the function in which it was
+                                  declared will be lval_register).  */
+};
+
+value
+evaluate_expression (exp)
+     struct expression *exp;
+{
+  int pc = 0;
+  return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);
+}
+
+/* Evaluate an expression, avoiding all memory references
+   and getting a value whose type alone is correct.  */
+
+value
+evaluate_type (exp)
+     struct expression *exp;
+{
+  int pc = 0;
+  return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+}
+
+static value
+evaluate_subexp (expect_type, exp, pos, noside)
+     struct type *expect_type;
+     register struct expression *exp;
+     register int *pos;
+     enum noside noside;
+{
+  enum exp_opcode op;
+  int tem;
+  register int pc, pc2, oldpos;
+  register value arg1, arg2, arg3;
+  int nargs;
+  value *argvec;
+
+  pc = (*pos)++;
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+    case OP_SCOPE:
+      tem = strlen (&exp->elts[pc + 2].string);
+      (*pos) += 3 + ((tem + sizeof (union exp_element))
+                    / sizeof (union exp_element));
+      return value_static_field (exp->elts[pc + 1].type,
+                                &exp->elts[pc + 2].string, -1);
+
+    case OP_LONG:
+      (*pos) += 3;
+      return value_from_long (exp->elts[pc + 1].type,
+                             exp->elts[pc + 2].longconst);
+
+    case OP_DOUBLE:
+      (*pos) += 3;
+      return value_from_double (exp->elts[pc + 1].type,
+                               exp->elts[pc + 2].doubleconst);
+
+    case OP_VAR_VALUE:
+      (*pos) += 2;
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       {
+         struct symbol * sym = exp->elts[pc + 1].symbol;
+         enum lval_type lv;
+
+         switch (SYMBOL_CLASS (sym))
+           {
+           case LOC_CONST:
+           case LOC_LABEL:
+           case LOC_CONST_BYTES:
+             lv = not_lval;
+             break;
+
+           case LOC_REGISTER:
+           case LOC_REGPARM:
+             lv = lval_register;
+             break;
+
+           default:
+             lv = lval_memory;
+             break;
+           }
+
+         return value_zero (SYMBOL_TYPE (sym), lv);
+       }
+      else
+       return value_of_variable (exp->elts[pc + 1].symbol);
+
+    case OP_LAST:
+      (*pos) += 2;
+      return access_value_history ((int) exp->elts[pc + 1].longconst);
+
+    case OP_REGISTER:
+      (*pos) += 2;
+      return value_of_register ((int) exp->elts[pc + 1].longconst);
+
+    case OP_INTERNALVAR:
+      (*pos) += 2;
+      return value_of_internalvar (exp->elts[pc + 1].internalvar);
+
+    case OP_STRING:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + ((tem + sizeof (union exp_element))
+                    / sizeof (union exp_element));
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_string (&exp->elts[pc + 1].string, tem);
+
+    case TERNOP_COND:
+      /* Skip third and second args to evaluate the first one.  */
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (value_zerop (arg1))
+       {
+         evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+         return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+       }
+      else
+       {
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+         return arg2;
+       }
+
+    case OP_FUNCALL:
+      (*pos) += 2;
+      op = exp->elts[*pos].opcode;
+      if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+       {
+         int fnptr;
+
+         nargs = (int) exp->elts[pc + 1].longconst + 1;
+         /* First, evaluate the structure into arg2 */
+         pc2 = (*pos)++;
+
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+
+         if (op == STRUCTOP_MEMBER)
+           {
+             arg2 = evaluate_subexp_for_address (exp, pos, noside);
+           }
+         else
+           {
+             arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+           }
+
+         /* If the function is a virtual function, then the
+            aggregate value (providing the structure) plays
+            its part by providing the vtable.  Otherwise,
+            it is just along for the ride: call the function
+            directly.  */
+
+         arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+         fnptr = (int) value_as_long (arg1);
+         if (fnptr < 128)
+           {
+             struct type *basetype;
+             int i, j;
+             basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
+             basetype = TYPE_VPTR_BASETYPE (basetype);
+             for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
+               {
+                 struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
+                 /* If one is virtual, then all are virtual.  */
+                 if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
+                   for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
+                     if (TYPE_FN_FIELD_VOFFSET (f, j) == fnptr)
+                       {
+                         value vtbl;
+                         value base = value_ind (arg2);
+                         struct type *fntype = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+
+                         if (TYPE_VPTR_FIELDNO (basetype) < 0)
+                           TYPE_VPTR_FIELDNO (basetype)
+                             = fill_in_vptr_fieldno (basetype);
+
+                         VALUE_TYPE (base) = basetype;
+                         vtbl = value_field (base, TYPE_VPTR_FIELDNO (basetype));
+                         VALUE_TYPE (vtbl) = lookup_pointer_type (fntype);
+                         VALUE_TYPE (arg1) = builtin_type_int;
+                         arg1 = value_subscript (vtbl, arg1);
+                         VALUE_TYPE (arg1) = fntype;
+                         goto got_it;
+                       }
+               }
+             if (i < 0)
+               error ("virtual function at index %d not found", fnptr);
+           }
+         else
+           {
+             VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
+           }
+       got_it:
+
+         /* Now, say which argument to start evaluating from */
+         tem = 2;
+       }
+      else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+       {
+         /* Hair for method invocations */
+         int tem2;
+
+         nargs = (int) exp->elts[pc + 1].longconst + 1;
+         /* First, evaluate the structure into arg2 */
+         pc2 = (*pos)++;
+         tem2 = strlen (&exp->elts[pc2 + 1].string);
+         *pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element);
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+
+         if (op == STRUCTOP_STRUCT)
+           {
+             arg2 = evaluate_subexp_for_address (exp, pos, noside);
+           }
+         else
+           {
+             arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+           }
+         /* Now, say which argument to start evaluating from */
+         tem = 2;
+       }
+      else
+       {
+         nargs = (int) exp->elts[pc + 1].longconst;
+         tem = 0;
+       }
+      argvec = (value *) alloca (sizeof (value) * (nargs + 2));
+      for (; tem <= nargs; tem++)
+       /* Ensure that array expressions are coerced into pointer objects. */
+       argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+
+      /* signal end of arglist */
+      argvec[tem] = 0;
+
+      if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+       {
+         int static_memfuncp;
+         value temp = arg2;
+
+         argvec[1] = arg2;
+         argvec[0] =
+           value_struct_elt (&temp, argvec+1, &exp->elts[pc2 + 1].string,
+                             &static_memfuncp,
+                             op == STRUCTOP_STRUCT
+                             ? "structure" : "structure pointer");
+         if (VALUE_OFFSET (temp))
+           {
+             arg2 = value_from_long (builtin_type_long,
+                                     value_as_long (arg2)+VALUE_OFFSET (temp));
+             VALUE_TYPE (arg2) = lookup_pointer_type (VALUE_TYPE (temp));
+             argvec[1] = arg2;
+           }
+         if (static_memfuncp)
+           {
+             argvec[1] = argvec[0];
+             nargs--;
+             argvec++;
+           }
+       }
+      else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+       {
+         argvec[1] = arg2;
+         argvec[0] = arg1;
+       }
+
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       {
+         /* If the return type doesn't look like a function type, call an
+            error.  This can happen if somebody tries to turn a variable into
+            a function call. This is here because people often want to
+            call, eg, strcmp, which gdb doesn't know is a function.  If
+            gdb isn't asked for it's opinion (ie. through "whatis"),
+            it won't offer it. */
+
+         struct type *ftype =
+           TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0]));
+
+         if (ftype)
+           return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
+         else
+           error ("Expression of type other than \"Function returning ...\" used as function");
+       }
+      return target_call_function (argvec[0], nargs, argvec + 1);
+
+    case STRUCTOP_STRUCT:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + ((tem + sizeof (union exp_element))
+                    / sizeof (union exp_element));
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
+                                                  &exp->elts[pc + 1].string),
+                          lval_memory);
+      else
+       {
+         value temp = arg1;
+         return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 1].string,
+                                  (int *) 0, "structure");
+       }
+
+    case STRUCTOP_PTR:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE
+                                                  (VALUE_TYPE (arg1)),
+                                                  &exp->elts[pc + 1].string),
+                          lval_memory);
+      else
+       {
+         value temp = arg1;
+         return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 1].string,
+                                  (int *) 0, "structure pointer");
+       }
+
+    case STRUCTOP_MEMBER:
+      arg1 = evaluate_subexp_for_address (exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      /* Now, convert these values to an address.  */
+      if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
+         || ((TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
+              != TYPE_CODE_MEMBER)
+             && (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
+                 != TYPE_CODE_METHOD)))
+       error ("non-pointer-to-member value used in pointer-to-member construct");
+      arg3 = value_from_long (builtin_type_long,
+                             value_as_long (arg1) + value_as_long (arg2));
+      VALUE_TYPE (arg3) =
+       lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
+      return value_ind (arg3);
+
+    case STRUCTOP_MPTR:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      /* Now, convert these values to an address.  */
+      if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
+         || (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_MEMBER
+             && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_METHOD))
+       error ("non-pointer-to-member value used in pointer-to-member construct");
+      arg3 = value_from_long (builtin_type_long,
+                             value_as_long (arg1) + value_as_long (arg2));
+      VALUE_TYPE (arg3) =
+       lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
+      return value_ind (arg3);
+
+    case BINOP_ASSIGN:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, 0);
+      else
+       return value_assign (arg1, arg2);
+
+    case BINOP_ASSIGN_MODIFY:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      op = exp->elts[pc + 1].opcode;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op);
+      else if (op == BINOP_ADD)
+       arg2 = value_add (arg1, arg2);
+      else if (op == BINOP_SUB)
+       arg2 = value_sub (arg1, arg2);
+      else
+       arg2 = value_binop (arg1, arg2, op);
+      return value_assign (arg1, arg2);
+
+    case BINOP_ADD:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, 0);
+      else
+       return value_add (arg1, arg2);
+
+    case BINOP_SUB:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, 0);
+      else
+       return value_sub (arg1, arg2);
+
+    case BINOP_MUL:
+    case BINOP_DIV:
+    case BINOP_REM:
+    case BINOP_LSH:
+    case BINOP_RSH:
+    case BINOP_LOGAND:
+    case BINOP_LOGIOR:
+    case BINOP_LOGXOR:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, 0);
+      else
+       if (noside == EVAL_AVOID_SIDE_EFFECTS
+           && op == BINOP_DIV)
+         return value_zero (VALUE_TYPE (arg1), not_lval);
+      else
+       return value_binop (arg1, arg2, op);
+
+    case BINOP_SUBSCRIPT:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+                          VALUE_LVAL (arg1));
+                          
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, 0);
+      else
+       return value_subscript (arg1, arg2);
+      
+    case BINOP_AND:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       {
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         goto nosideret;
+       }
+      
+      oldpos = *pos;
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      *pos = oldpos;
+      
+      if (binop_user_defined_p (op, arg1, arg2)) 
+       {
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else
+       {
+         tem = value_zerop (arg1);
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
+                                 (tem ? EVAL_SKIP : noside));
+         return value_from_long (builtin_type_int,
+                                 (LONGEST) (!tem && !value_zerop (arg2)));
+       }
+
+    case BINOP_OR:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       {
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         goto nosideret;
+       }
+      
+      oldpos = *pos;
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      *pos = oldpos;
+      
+      if (binop_user_defined_p (op, arg1, arg2)) 
+       {
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else
+       {
+         tem = value_zerop (arg1);
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
+                                 (!tem ? EVAL_SKIP : noside));
+         return value_from_long (builtin_type_int,
+                                 (LONGEST) (!tem || !value_zerop (arg2)));
+       }
+
+    case BINOP_EQUAL:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       {
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else
+       {
+         tem = value_equal (arg1, arg2);
+         return value_from_long (builtin_type_int, (LONGEST) tem);
+       }
+
+    case BINOP_NOTEQUAL:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       {
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else
+       {
+         tem = value_equal (arg1, arg2);
+         return value_from_long (builtin_type_int, (LONGEST) ! tem);
+       }
+
+    case BINOP_LESS:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       {
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else
+       {
+         tem = value_less (arg1, arg2);
+         return value_from_long (builtin_type_int, (LONGEST) tem);
+       }
+
+    case BINOP_GTR:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       {
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else
+       {
+         tem = value_less (arg2, arg1);
+         return value_from_long (builtin_type_int, (LONGEST) tem);
+       }
+
+    case BINOP_GEQ:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       {
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else
+       {
+         tem = value_less (arg1, arg2);
+         return value_from_long (builtin_type_int, (LONGEST) ! tem);
+       }
+
+    case BINOP_LEQ:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       {
+         return value_x_binop (arg1, arg2, op, 0);
+       }
+      else 
+       {
+         tem = value_less (arg2, arg1);
+         return value_from_long (builtin_type_int, (LONGEST) ! tem);
+       }
+
+    case BINOP_REPEAT:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT)
+       error ("Non-integral right operand for \"@\" operator.");
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return allocate_repeat_value (VALUE_TYPE (arg1),
+                                      (int) value_as_long (arg2));
+      else
+       return value_repeat (arg1, (int) value_as_long (arg2));
+
+    case BINOP_COMMA:
+      evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+    case UNOP_NEG:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (unop_user_defined_p (op, arg1))
+       return value_x_unop (arg1, op);
+      else
+       return value_neg (arg1);
+
+    case UNOP_LOGNOT:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (unop_user_defined_p (op, arg1))
+       return value_x_unop (arg1, op);
+      else
+       return value_lognot (arg1);
+
+    case UNOP_ZEROP:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (unop_user_defined_p (op, arg1))
+       return value_x_unop (arg1, op);
+      else
+       return value_from_long (builtin_type_int,
+                               (LONGEST) value_zerop (arg1));
+
+    case UNOP_IND:
+      if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
+        expect_type = TYPE_TARGET_TYPE (expect_type);
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       {
+         if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+             || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
+             /* In C you can dereference an array to get the 1st elt.  */
+             || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY
+             )
+           return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+                              lval_memory);
+         else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
+           /* GDB allows dereferencing an int.  */
+           return value_zero (builtin_type_int, lval_memory);
+         else
+           error ("Attempt to take contents of a non-pointer value.");
+       }
+      return value_ind (arg1);
+
+    case UNOP_ADDR:
+      /* C++: check for and handle pointer to members.  */
+      
+      op = exp->elts[*pos].opcode;
+
+      if (noside == EVAL_SKIP)
+       {
+         if (op == OP_SCOPE)
+           {
+             char *name = &exp->elts[pc+3].string;
+             int temm = strlen (name);
+             (*pos) += 2 + (temm + sizeof (union exp_element)) / sizeof (union exp_element);
+           }
+         else
+           evaluate_subexp (expect_type, exp, pos, EVAL_SKIP);
+         goto nosideret;
+       }
+
+      if (op == OP_SCOPE)
+       {
+         char *name = &exp->elts[pc+3].string;
+         int temm = strlen (name);
+         struct type *domain = exp->elts[pc+2].type;
+         (*pos) += 2 + (temm + sizeof (union exp_element)) / sizeof (union exp_element);
+         arg1 = value_struct_elt_for_address (domain, expect_type, name);
+         if (arg1)
+           return arg1;
+         error ("no field `%s' in structure", name);
+       }
+      else
+       return evaluate_subexp_for_address (exp, pos, noside);
+
+    case UNOP_SIZEOF:
+      if (noside == EVAL_SKIP)
+       {
+         evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+         goto nosideret;
+       }
+      return evaluate_subexp_for_sizeof (exp, pos);
+
+    case UNOP_CAST:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_cast (exp->elts[pc + 1].type, arg1);
+
+    case UNOP_MEMVAL:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return value_zero (exp->elts[pc + 1].type, lval_memory);
+      else
+       return value_at_lazy (exp->elts[pc + 1].type,
+                        (CORE_ADDR) value_as_long (arg1));
+
+    case UNOP_PREINCREMENT:
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      else if (unop_user_defined_p (op, arg1))
+       {
+         return value_x_unop (arg1, op);
+       }
+      else
+       {
+         arg2 = value_add (arg1, value_from_long (builtin_type_char, 
+                                                  (LONGEST) 1));
+         return value_assign (arg1, arg2);
+       }
+
+    case UNOP_PREDECREMENT:
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      else if (unop_user_defined_p (op, arg1))
+       {
+         return value_x_unop (arg1, op);
+       }
+      else
+       {
+         arg2 = value_sub (arg1, value_from_long (builtin_type_char, 
+                                                  (LONGEST) 1));
+         return value_assign (arg1, arg2);
+       }
+
+    case UNOP_POSTINCREMENT:
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      else if (unop_user_defined_p (op, arg1))
+       {
+         return value_x_unop (arg1, op);
+       }
+      else
+       {
+         arg2 = value_add (arg1, value_from_long (builtin_type_char, 
+                                                  (LONGEST) 1));
+         value_assign (arg1, arg2);
+         return arg1;
+       }
+
+    case UNOP_POSTDECREMENT:
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      else if (unop_user_defined_p (op, arg1))
+       {
+         return value_x_unop (arg1, op);
+       }
+      else
+       {
+         arg2 = value_sub (arg1, value_from_long (builtin_type_char, 
+                                                  (LONGEST) 1));
+         value_assign (arg1, arg2);
+         return arg1;
+       }
+       
+    case OP_THIS:
+      (*pos) += 1;
+      return value_of_this (1);
+
+    default:
+      error ("internal error: I do not know how to evaluate what you gave me");
+    }
+
+ nosideret:
+  return value_from_long (builtin_type_long, (LONGEST) 1);
+}
+\f
+/* Evaluate a subexpression of EXP, at index *POS,
+   and return the address of that subexpression.
+   Advance *POS over the subexpression.
+   If the subexpression isn't an lvalue, get an error.
+   NOSIDE may be EVAL_AVOID_SIDE_EFFECTS;
+   then only the type of the result need be correct.  */
+
+static value
+evaluate_subexp_for_address (exp, pos, noside)
+     register struct expression *exp;
+     register int *pos;
+     enum noside noside;
+{
+  enum exp_opcode op;
+  register int pc;
+
+  pc = (*pos);
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+    case UNOP_IND:
+      (*pos)++;
+      return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+    case UNOP_MEMVAL:
+      (*pos) += 3;
+      return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
+                        evaluate_subexp (NULL_TYPE, exp, pos, noside));
+
+    case OP_VAR_VALUE:
+      (*pos) += 3;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       {
+         struct type *type =
+           lookup_pointer_type (SYMBOL_TYPE (exp->elts[pc + 1].symbol));
+         enum address_class sym_class =
+           SYMBOL_CLASS (exp->elts[pc + 1].symbol);
+
+         if (sym_class == LOC_CONST
+             || sym_class == LOC_CONST_BYTES
+             || sym_class == LOC_REGISTER
+             || sym_class == LOC_REGPARM)
+           error ("Attempt to take address of register or constant.");
+
+       return
+         value_zero (type, not_lval);
+       }
+      else
+       return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+
+    default:
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       {
+         value x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         if (VALUE_LVAL (x) == lval_memory)
+           return value_zero (TYPE_POINTER_TYPE (VALUE_TYPE (x)),
+                              not_lval);
+         else
+           error ("Attempt to take address of non-lval");
+       }
+      return value_addr (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+    }
+}
+
+/* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
+   When used in contexts where arrays will be coerced anyway,
+   this is equivalent to `evaluate_subexp'
+   but much faster because it avoids actually fetching array contents.  */
+
+static value
+evaluate_subexp_with_coercion (exp, pos, noside)
+     register struct expression *exp;
+     register int *pos;
+     enum noside noside;
+{
+  register enum exp_opcode op;
+  register int pc;
+  register value val;
+
+  pc = (*pos);
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+    case OP_VAR_VALUE:
+      if (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 1].symbol)) == TYPE_CODE_ARRAY)
+       {
+         (*pos) += 3;
+         val = locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+         return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (exp->elts[pc + 1].symbol))),
+                            val);
+       }
+      default:
+       return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+    }
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+   and return a value for the size of that subexpression.
+   Advance *POS over the subexpression.  */
+
+static value
+evaluate_subexp_for_sizeof (exp, pos)
+     register struct expression *exp;
+     register int *pos;
+{
+  enum exp_opcode op;
+  register int pc;
+  value val;
+
+  pc = (*pos);
+  op = exp->elts[pc].opcode;
+
+  switch (op)
+    {
+      /* This case is handled specially
+        so that we avoid creating a value for the result type.
+        If the result type is very big, it's desirable not to
+        create a value unnecessarily.  */
+    case UNOP_IND:
+      (*pos)++;
+      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      return value_from_long (builtin_type_int, (LONGEST)
+                     TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
+
+    case UNOP_MEMVAL:
+      (*pos) += 3;
+      return value_from_long (builtin_type_int, 
+                             (LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type));
+
+    case OP_VAR_VALUE:
+      (*pos) += 3;
+      return value_from_long (builtin_type_int,
+        (LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
+
+    default:
+      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      return value_from_long (builtin_type_int,
+                             (LONGEST) TYPE_LENGTH (VALUE_TYPE (val)));
+    }
+}
diff --git a/gdb/exec.c b/gdb/exec.c
new file mode 100644 (file)
index 0000000..eefe772
--- /dev/null
@@ -0,0 +1,350 @@
+/* Work with executable files, for GDB. 
+   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+
+#ifdef STILL_NEEDED_FOR_DECSTATION
+#include <sys/dir.h>           /* For DECstations */
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#endif
+
+#include <sys/stat.h>
+
+extern char *getenv();
+extern void child_create_inferior (), child_attach ();
+extern void symbol_file_command ();
+
+/* The Binary File Descriptor handle for the executable file.  */
+
+bfd *exec_bfd = NULL;
+
+/* The base and bounds of the table of the exec file's sections.  */
+
+struct section_table *exec_sections, *exec_sections_end;
+
+/* Forward decl */
+
+extern struct target_ops exec_ops;
+
+void
+exec_close (quitting)
+     int quitting;
+{
+  if (exec_bfd) {
+    bfd_close (exec_bfd);
+    exec_bfd = NULL;
+  }
+}
+
+void
+exec_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+
+  /* Remove any previous exec file.  */
+  unpush_target (&exec_ops);
+
+  /* Now open and digest the file the user requested, if any.  */
+
+  if (filename)
+    {
+      char *scratch_pathname;
+      int scratch_chan;
+      
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+/* FIXME, if writeable is set, open for read/write. */
+      scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+                           &scratch_pathname);
+      if (scratch_chan < 0)
+       perror_with_name (filename);
+
+      exec_bfd = bfd_fdopenr (scratch_pathname, NULL, scratch_chan);
+      if (!exec_bfd)
+       error ("Could not open `%s' as an executable file: %s",
+              scratch_pathname, bfd_errmsg (bfd_error));
+      if (!bfd_check_format (exec_bfd, bfd_object))
+       error ("\"%s\": not in executable format: %s.",
+              scratch_pathname, bfd_errmsg (bfd_error));
+
+#if FIXME
+/* This code needs to be incorporated into BFD */
+#ifdef COFF_ENCAPSULATE
+       /* If we have a coff header, it can give us better values for
+          text_start and exec_data_start.  This is particularly useful
+          for remote debugging of embedded systems.  */
+       if (N_FLAGS(exec_aouthdr) & N_FLAGS_COFF_ENCAPSULATE)
+       {
+               struct coffheader ch;
+               int val;
+               val = lseek (execchan, -(sizeof (AOUTHDR) + sizeof (ch)), 1);
+               if (val == -1)
+                       perror_with_name (filename);
+               val = myread (execchan, &ch, sizeof (ch));
+               if (val < 0)
+                       perror_with_name (filename);
+               text_start = ch.text_start;
+               exec_data_start = ch.data_start;
+       } else
+#endif
+              {
+               text_start =
+                 IS_OBJECT_FILE (exec_aouthdr) ? 0 : N_TXTADDR (exec_aouthdr);
+               exec_data_start = IS_OBJECT_FILE (exec_aouthdr)
+                 ? exec_aouthdr.a_text : N_DATADDR (exec_aouthdr);
+       }
+#endif FIXME
+
+      if (build_section_table (exec_bfd, &exec_sections, &exec_sections_end))
+       error ("Can't find the file sections in `%s': %s", 
+               exec_bfd->filename, bfd_errmsg (bfd_error));
+
+      validate_files ();
+
+      push_target (&exec_ops);
+
+      /* Tell display code (if any) about the changed file name.  */
+      if (exec_file_display_hook)
+       (*exec_file_display_hook) (filename);
+    }
+  else if (from_tty)
+    printf ("No exec file now.\n");
+}
+
+/* Set both the exec file and the symbol file, in one command.  
+   What a novelty.  Why did GDB go through four major releases before this
+   command was added?  */
+
+void
+file_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  /* FIXME, if we lose on reading the symbol file, we should revert
+     the exec file, but that's rough.  */
+  exec_file_command (arg, from_tty);
+  symbol_file_command (arg, from_tty);
+}
+
+\f
+/* Locate all mappable sections of a BFD file.  */
+
+void
+add_to_section_table (abfd, asect, table_pp)
+     bfd *abfd;
+     sec_ptr asect;
+     struct section_table **table_pp;
+{
+  flagword aflag;
+
+  aflag = bfd_get_section_flags (abfd, asect);
+  /* FIXME, we need to handle BSS segment here...it alloc's but doesn't load */
+  if (!(aflag & SEC_LOAD))
+    return;
+  (*table_pp)->sec_ptr = asect;
+  (*table_pp)->addr = bfd_section_vma (abfd, asect);
+  (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect);
+  (*table_pp)++;
+}
+
+int
+build_section_table (some_bfd, start, end)
+     bfd *some_bfd;
+     struct section_table **start, **end;
+{
+  unsigned count;
+
+  count = bfd_count_sections (some_bfd);
+  if (count == 0)
+    abort();   /* return 1? */
+  *start = (struct section_table *) xmalloc (count * sizeof (**start));
+  *end = *start;
+  bfd_map_over_sections (some_bfd, add_to_section_table, end);
+  if (*end > *start + count)
+    abort();
+  /* We could realloc the table, but it probably loses for most files.  */
+  return 0;
+}
+\f
+/* Read or write the exec file.
+
+   Args are address within exec file, address within gdb address-space,
+   length, and a flag indicating whether to read or write.
+
+   Result is a length:
+
+       0:    We cannot handle this address and length.
+       > 0:  We have handled N bytes starting at this address.
+             (If N == length, we did it all.)  We might be able
+             to handle more bytes beyond this length, but no
+             promises.
+       < 0:  We cannot handle this address, but if somebody
+             else handles (-N) bytes, we can start from there.
+
+    The same routine is used to handle both core and exec files;
+    we just tail-call it with more arguments to select between them.  */
+
+int
+xfer_memory (memaddr, myaddr, len, write, abfd, sections, sections_end)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+     bfd *abfd;
+     struct section_table *sections, *sections_end;
+{
+  boolean res;
+  struct section_table *p;
+  CORE_ADDR nextsectaddr, memend;
+  boolean (*xfer_fn) ();
+
+  if (len <= 0)
+    abort();
+
+  memend = memaddr + len;
+  xfer_fn = write? bfd_set_section_contents: bfd_get_section_contents;
+  nextsectaddr = memend;
+
+  for (p = sections; p < sections_end; p++)
+    {
+      if (p->addr <= memaddr)
+       if (p->endaddr >= memend)
+         {
+           /* Entire transfer is within this section.  */
+           res = xfer_fn (abfd, p->sec_ptr, myaddr, memaddr - p->addr, len);
+           return (res != false)? len: 0;
+         }
+       else if (p->endaddr <= memaddr)
+         {
+           /* This section ends before the transfer starts.  */
+           continue;
+         }
+       else 
+         {
+           /* This section overlaps the transfer.  Just do half.  */
+           len = p->endaddr - memaddr;
+           res = xfer_fn (abfd, p->sec_ptr, myaddr, memaddr - p->addr, len);
+           return (res != false)? len: 0;
+         }
+      else if (p->addr < nextsectaddr)
+       nextsectaddr = p->addr;
+    }
+
+  if (nextsectaddr >= memend)
+    return 0;                          /* We can't help */
+  else
+    return - (nextsectaddr - memaddr); /* Next boundary where we can help */
+}
+
+/* The function called by target_xfer_memory via our target_ops */
+
+int
+exec_xfer_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  return xfer_memory (memaddr, myaddr, len, write,
+                     exec_bfd, exec_sections, exec_sections_end);
+}
+
+
+#ifdef FIXME
+#ifdef REG_STACK_SEGMENT
+/* MOVE TO BFD... */
+    /* Pyramids and AM29000s have an extra segment in the virtual address space
+       for the (control) stack of register-window frames.  The AM29000 folk
+       call it the "register stack" rather than the "memory stack".  */
+    else if (memaddr >= reg_stack_start && memaddr < reg_stack_end)
+      {
+       i = min (len, reg_stack_end - memaddr);
+       fileptr = memaddr - reg_stack_start + reg_stack_offset;
+       wanna_xfer = coredata;
+      }
+#endif                         /* REG_STACK_SEGMENT */
+#endif FIXME
+\f
+static void
+exec_files_info ()
+{
+  struct section_table *p;
+
+  printf ("\tExecutable file `%s'.\n", bfd_get_filename(exec_bfd));
+
+  for (p = exec_sections; p < exec_sections_end; p++)
+    printf("\texecutable from 0x%08x to 0x%08x is %s\n",
+       p->addr, p->endaddr,
+       bfd_section_name (exec_bfd, p->sec_ptr));
+}
+
+struct target_ops exec_ops = {
+       "exec", "Local exec file",
+       exec_file_command, exec_close, /* open, close */
+       child_attach, 0, 0, 0, /* attach, detach, resume, wait, */
+       0, 0, /* fetch_registers, store_registers, */
+       0, 0, 0, /* prepare_to_store, conv_to, conv_from, */
+       exec_xfer_memory, exec_files_info,
+       0, 0, /* insert_breakpoint, remove_breakpoint, */
+       0, 0, 0, 0, 0, /* terminal stuff */
+       0, 0, 0, 0, 0, /* kill, load, add_syms, call fn, lookup sym */
+       child_create_inferior,
+       0, /* mourn_inferior */
+       file_stratum, 0, /* next */
+       0, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_exec()
+{
+
+  add_com ("file", class_files, file_command,
+          "Use FILE as program to be debugged.\n\
+It is read for its symbols, for getting the contents of pure memory,\n\
+and it is the program executed when you use the `run' command.\n\
+If FILE cannot be found as specified, your execution directory path\n\
+($PATH) is searched for a command of that name.\n\
+No arg means to have no executable file and no symbols.");
+
+  add_com ("exec-file", class_files, exec_file_command,
+          "Use FILE as program for getting contents of pure memory.\n\
+If FILE cannot be found as specified, your execution directory path\n\
+is searched for a command of that name.\n\
+No arg means have no executable file.");
+
+  add_target (&exec_ops);
+}
diff --git a/gdb/expprint.c b/gdb/expprint.c
new file mode 100644 (file)
index 0000000..9e1e9d2
--- /dev/null
@@ -0,0 +1,324 @@
+/* Print in infix form a struct expression.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "symtab.h"
+#include "param.h"
+#include "expression.h"
+#include "value.h"
+
+\f
+/* These codes indicate operator precedences, least tightly binding first.  */
+/* Adding 1 to a precedence value is done for binary operators,
+   on the operand which is more tightly bound, so that operators
+   of equal precedence within that operand will get parentheses.  */
+/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
+   they are used as the "surrounding precedence" to force
+   various kinds of things to be parenthesized.  */
+enum precedence
+{ PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
+  PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
+  PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
+  PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+
+struct op_print
+{
+  char *string;
+  enum exp_opcode opcode;
+  /* Precedence of operator.  These values are used only by comparisons.  */
+  enum precedence precedence;
+  int right_assoc;
+};
+
+static struct op_print op_print_tab[] =
+  {
+    {",", BINOP_COMMA, PREC_COMMA, 0},
+    {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+    {"||", BINOP_OR, PREC_OR, 0},
+    {"&&", BINOP_AND, PREC_AND, 0},
+    {"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
+    {"&", BINOP_LOGAND, PREC_LOGAND, 0},
+    {"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
+    {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+    {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+    {"<=", BINOP_LEQ, PREC_ORDER, 0},
+    {">=", BINOP_GEQ, PREC_ORDER, 0},
+    {">", BINOP_GTR, PREC_ORDER, 0},
+    {"<", BINOP_LESS, PREC_ORDER, 0},
+    {">>", BINOP_RSH, PREC_SHIFT, 0},
+    {"<<", BINOP_LSH, PREC_SHIFT, 0},
+    {"+", BINOP_ADD, PREC_ADD, 0},
+    {"-", BINOP_SUB, PREC_ADD, 0},
+    {"*", BINOP_MUL, PREC_MUL, 0},
+    {"/", BINOP_DIV, PREC_MUL, 0},
+    {"%", BINOP_REM, PREC_MUL, 0},
+    {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+    {"-", UNOP_NEG, PREC_PREFIX, 0},
+    {"!", UNOP_ZEROP, PREC_PREFIX, 0},
+    {"~", UNOP_LOGNOT, PREC_PREFIX, 0},
+    {"*", UNOP_IND, PREC_PREFIX, 0},
+    {"&", UNOP_ADDR, PREC_PREFIX, 0},
+    {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+    {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+    {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+    /* C++  */
+    {"::", BINOP_SCOPE, PREC_PREFIX, 0},
+  };
+\f
+static void print_subexp ();
+
+void
+print_expression (exp, stream)
+     struct expression *exp;
+     FILE *stream;
+{
+  int pc = 0;
+  print_subexp (exp, &pc, stream, PREC_NULL);
+}
+
+/* Print the subexpression of EXP that starts in position POS, on STREAM.
+   PREC is the precedence of the surrounding operator;
+   if the precedence of the main operator of this subexpression is less,
+   parentheses are needed here.  */
+
+static void
+print_subexp (exp, pos, stream, prec)
+     register struct expression *exp;
+     register int *pos;
+     FILE *stream;
+     enum precedence prec;
+{
+  register unsigned tem;
+  register int pc;
+  unsigned nargs;
+  register char *op_str;
+  int assign_modify = 0;
+  enum exp_opcode opcode;
+  enum precedence myprec;
+  /* Set to 1 for a right-associative operator.  */
+  int assoc;
+
+  pc = (*pos)++;
+  opcode = exp->elts[pc].opcode;
+  switch (opcode)
+    {
+    case OP_SCOPE:
+      myprec = PREC_PREFIX;
+      assoc = 0;
+      (*pos) += 2;
+      print_subexp (exp, pos, stream, (int) myprec + assoc);
+      fprintf (stream, " :: ");
+      nargs = strlen (&exp->elts[pc + 2].string);
+      (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
+
+      fprintf (stream, &exp->elts[pc + 2].string);
+      return;
+
+    case OP_LONG:
+      (*pos) += 3;
+      value_print (value_from_long (exp->elts[pc + 1].type,
+                                   exp->elts[pc + 2].longconst),
+                  stream, 0, Val_no_prettyprint);
+      return;
+
+    case OP_DOUBLE:
+      (*pos) += 3;
+      value_print (value_from_double (exp->elts[pc + 1].type,
+                                     exp->elts[pc + 2].doubleconst),
+                  stream, 0, Val_no_prettyprint);
+      return;
+
+    case OP_VAR_VALUE:
+      (*pos) += 2;
+      fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
+      return;
+
+    case OP_LAST:
+      (*pos) += 2;
+      fprintf (stream, "$%d", (int) exp->elts[pc + 1].longconst);
+      return;
+
+    case OP_REGISTER:
+      (*pos) += 2;
+      fprintf (stream, "$%s", reg_names[exp->elts[pc + 1].longconst]);
+      return;
+
+    case OP_INTERNALVAR:
+      (*pos) += 2;
+      fprintf (stream, "$%s",
+              internalvar_name (exp->elts[pc + 1].internalvar));
+      return;
+
+    case OP_FUNCALL:
+      (*pos) += 2;
+      nargs = exp->elts[pc + 1].longconst;
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, " (");
+      for (tem = 0; tem < nargs; tem++)
+       {
+         if (tem != 0)
+           fprintf (stream, ", ");
+         print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+       }
+      fprintf (stream, ")");
+      return;
+
+    case OP_STRING:
+      nargs = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
+      fprintf (stream, "\"");
+      for (tem = 0; tem < nargs; tem++)
+       printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
+      fprintf (stream, "\"");
+      return;
+
+    case TERNOP_COND:
+      if ((int) prec > (int) PREC_COMMA)
+       fprintf (stream, "(");
+      /* Print the subexpressions, forcing parentheses
+        around any binary operations within them.
+        This is more parentheses than are strictly necessary,
+        but it looks clearer.  */
+      print_subexp (exp, pos, stream, PREC_HYPER);
+      fprintf (stream, " ? ");
+      print_subexp (exp, pos, stream, PREC_HYPER);
+      fprintf (stream, " : ");
+      print_subexp (exp, pos, stream, PREC_HYPER);
+      if ((int) prec > (int) PREC_COMMA)
+       fprintf (stream, ")");
+      return;
+
+    case STRUCTOP_STRUCT:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, ".%s", &exp->elts[pc + 1].string);
+      return;
+
+    case STRUCTOP_PTR:
+      tem = strlen (&exp->elts[pc + 1].string);
+      (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "->%s", &exp->elts[pc + 1].string);
+      return;
+
+    case BINOP_SUBSCRIPT:
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "[");
+      print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+      fprintf (stream, "]");
+      return;
+
+    case UNOP_POSTINCREMENT:
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "++");
+      return;
+
+    case UNOP_POSTDECREMENT:
+      print_subexp (exp, pos, stream, PREC_SUFFIX);
+      fprintf (stream, "--");
+      return;
+
+    case UNOP_CAST:
+      (*pos) += 2;
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, "(");
+      fprintf (stream, "(");
+      type_print (exp->elts[pc + 1].type, "", stream, 0);
+      fprintf (stream, ") ");
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, ")");
+      return;
+
+    case UNOP_MEMVAL:
+      (*pos) += 2;
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, "(");
+      fprintf (stream, "{");
+      type_print (exp->elts[pc + 1].type, "", stream, 0);
+      fprintf (stream, "} ");
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      if ((int) prec > (int) PREC_PREFIX)
+       fprintf (stream, ")");
+      return;
+
+    case BINOP_ASSIGN_MODIFY:
+      opcode = exp->elts[pc + 1].opcode;
+      (*pos) += 2;
+      myprec = PREC_ASSIGN;
+      assoc = 1;
+      assign_modify = 1;
+      for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
+       if (op_print_tab[tem].opcode == opcode)
+         {
+           op_str = op_print_tab[tem].string;
+           break;
+         }
+
+    case OP_THIS:
+      ++(*pos);
+      fprintf (stream, "this");
+      return;
+
+    default:
+      for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
+       if (op_print_tab[tem].opcode == opcode)
+         {
+           op_str = op_print_tab[tem].string;
+           myprec = op_print_tab[tem].precedence;
+           assoc = op_print_tab[tem].right_assoc;
+           break;
+         }
+    }
+
+  if ((int) myprec < (int) prec)
+    fprintf (stream, "(");
+  if ((int) opcode > (int) BINOP_END)
+    {
+      /* Unary prefix operator.  */
+      fprintf (stream, "%s", op_str);
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+    }
+  else
+    {
+      /* Binary operator.  */
+      /* Print left operand.
+        If operator is right-associative,
+        increment precedence for this operand.  */
+      print_subexp (exp, pos, stream, (int) myprec + assoc);
+      /* Print the operator itself.  */
+      if (assign_modify)
+       fprintf (stream, " %s= ", op_str);
+      else if (op_str[0] == ',')
+       fprintf (stream, "%s ", op_str);
+      else
+       fprintf (stream, " %s ", op_str);
+      /* Print right operand.
+        If operator is left-associative,
+        increment precedence for this operand.  */
+      print_subexp (exp, pos, stream, (int) myprec + !assoc);
+    }
+  if ((int) myprec < (int) prec)
+    fprintf (stream, ")");
+}
diff --git a/gdb/expread.tab.c b/gdb/expread.tab.c
new file mode 100755 (executable)
index 0000000..86fbd0f
--- /dev/null
@@ -0,0 +1,2657 @@
+
+/*  A Bison parser, made from ../expread.y  */
+
+#define        INT     258
+#define        CHAR    259
+#define        UINT    260
+#define        FLOAT   261
+#define        STRING  262
+#define        NAME    263
+#define        BLOCKNAME       264
+#define        TYPENAME        265
+#define        NAME_OR_INT     266
+#define        NAME_OR_UINT    267
+#define        STRUCT  268
+#define        UNION   269
+#define        ENUM    270
+#define        SIZEOF  271
+#define        UNSIGNED        272
+#define        COLONCOLON      273
+#define        ERROR   274
+#define        SIGNED  275
+#define        LONG    276
+#define        SHORT   277
+#define        INT_KEYWORD     278
+#define        LAST    279
+#define        REGNAME 280
+#define        VARIABLE        281
+#define        ASSIGN_MODIFY   282
+#define        THIS    283
+#define        ABOVE_COMMA     284
+#define        OR      285
+#define        AND     286
+#define        EQUAL   287
+#define        NOTEQUAL        288
+#define        LEQ     289
+#define        GEQ     290
+#define        LSH     291
+#define        RSH     292
+#define        UNARY   293
+#define        INCREMENT       294
+#define        DECREMENT       295
+#define        ARROW   296
+
+#line 29 "../expread.y"
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "expression.h"
+#include "value.h"
+#include "command.h"
+
+static struct expression *expout;
+static int expout_size;
+static int expout_ptr;
+
+static int yylex ();
+static void yyerror ();
+static void write_exp_elt ();
+static void write_exp_elt_opcode ();
+static void write_exp_elt_sym ();
+static void write_exp_elt_longcst ();
+static void write_exp_elt_dblcst ();
+static void write_exp_elt_type ();
+static void write_exp_elt_intern ();
+static void write_exp_string ();
+static void start_arglist ();
+static int end_arglist ();
+static void free_funcalls ();
+static char *copy_name ();
+static int parse_number ();
+
+/* If this is nonzero, this block is used as the lexical context
+   for symbol names.  */
+
+static struct block *expression_context_block;
+
+/* The innermost context required by the stack and register variables
+   we've encountered so far. */
+struct block *innermost_block;
+
+/* The block in which the most recently discovered symbol was found. */
+struct block *block_found;
+
+/* Number of arguments seen so far in innermost function call.  */
+static int arglist_len;
+
+/* Data structure for saving values of arglist_len
+   for function calls whose arguments contain other function calls.  */
+
+struct funcall
+  {
+    struct funcall *next;
+    int arglist_len;
+  };
+
+struct funcall *funcall_chain;
+
+/* This kind of datum is used to represent the name
+   of a symbol token.  */
+
+struct stoken
+  {
+    char *ptr;
+    int length;
+  };
+
+struct ttype
+  {
+    struct stoken stoken;
+    struct type *type;
+  };
+
+struct symtoken
+  {
+    struct stoken stoken;
+    struct symbol *sym;
+    int is_a_field_of_this;
+  };
+
+/* For parsing of complicated types.
+   An array should be preceded in the list by the size of the array.  */
+enum type_pieces
+  {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function};
+static enum type_pieces *type_stack;
+static int type_stack_depth, type_stack_size;
+
+static void push_type ();
+static enum type_pieces pop_type ();
+
+/* Allow debugging of parsing.  */
+#define YYDEBUG 1
+
+#line 125 "../expread.y"
+typedef union
+  {
+    LONGEST lval;
+    unsigned LONGEST ulval;
+    double dval;
+    struct symbol *sym;
+    struct type *tval;
+    struct stoken sval;
+    struct ttype tsym;
+    struct symtoken ssym;
+    int voidval;
+    struct block *bval;
+    enum exp_opcode opcode;
+    struct internalvar *ivar;
+
+    struct type **tvec;
+    int *ivec;
+  } YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+  struct yyltype
+    {
+      int timestamp;
+      int first_line;
+      int first_column;
+      int last_line;
+      int last_column;
+      char *text;
+   }
+  yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __STDC__
+#define const
+#endif
+
+
+
+#define        YYFINAL         189
+#define        YYFLAG          -32768
+#define        YYNTBASE        66
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 296 ? yytranslate[x] : 84)
+
+static const char yytranslate[] = {     0,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,    59,     2,     2,     2,    51,    37,     2,    58,
+    62,    49,    47,    29,    48,    56,    50,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,    65,     2,    40,
+    31,    41,    32,    46,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+    57,     2,    61,    36,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,    63,    35,    64,    60,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     1,     2,     3,     4,     5,
+     6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+    16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+    26,    27,    28,    30,    33,    34,    38,    39,    42,    43,
+    44,    45,    52,    53,    54,    55
+};
+
+static const short yyrline[] = {     0,
+   218,   222,   223,   228,   231,   234,   238,   242,   246,   250,
+   254,   258,   262,   266,   272,   276,   282,   286,   290,   294,
+   300,   303,   307,   311,   317,   323,   329,   333,   337,   341,
+   345,   349,   353,   357,   361,   365,   369,   373,   377,   381,
+   385,   389,   393,   397,   401,   405,   409,   413,   419,   429,
+   442,   454,   467,   474,   481,   484,   490,   496,   502,   509,
+   516,   523,   540,   550,   562,   575,   621,   695,   696,   731,
+   733,   735,   738,   740,   745,   751,   753,   757,   759,   763,
+   767,   768,   770,   772,   775,   782,   784,   786,   788,   790,
+   792,   794,   796,   798,   801,   804,   807,   809,   811,   813,
+   817,   818,   824,   830,   839,   844,   851,   852,   853,   854,
+   855,   858,   859,   860,   861
+};
+
+static const char * const yytname[] = {     0,
+"error","$illegal.","INT","CHAR","UINT","FLOAT","STRING","NAME","BLOCKNAME","TYPENAME",
+"NAME_OR_INT","NAME_OR_UINT","STRUCT","UNION","ENUM","SIZEOF","UNSIGNED","COLONCOLON","ERROR","SIGNED",
+"LONG","SHORT","INT_KEYWORD","LAST","REGNAME","VARIABLE","ASSIGN_MODIFY","THIS","','","ABOVE_COMMA",
+"'='","'?'","OR","AND","'|'","'^'","'&'","EQUAL","NOTEQUAL","'<'",
+"'>'","LEQ","GEQ","LSH","RSH","'@'","'+'","'-'","'*'","'/'",
+"'%'","UNARY","INCREMENT","DECREMENT","ARROW","'.'","'['","'('","'!'","'~'",
+"']'","')'","'{'","'}'","':'","start"
+};
+
+static const short yyr1[] = {     0,
+    66,    67,    67,    68,    68,    68,    68,    68,    68,    68,
+    68,    68,    68,    68,    68,    68,    68,    68,    69,    68,
+    70,    70,    70,    68,    68,    68,    68,    68,    68,    68,
+    68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
+    68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
+    68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
+    68,    71,    71,    72,    72,    72,    72,    73,    73,    74,
+    74,    74,    75,    75,    75,    75,    75,    76,    76,    77,
+    78,    78,    78,    78,    78,    79,    79,    79,    79,    79,
+    79,    79,    79,    79,    79,    79,    79,    79,    79,    79,
+    80,    80,    80,    80,    81,    81,    82,    82,    82,    82,
+    82,    83,    83,    83,    83
+};
+
+static const short yyr2[] = {     0,
+     1,     1,     3,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     3,     4,     3,     4,     4,     0,     5,
+     0,     1,     3,     4,     4,     3,     3,     3,     3,     3,
+     3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
+     3,     3,     3,     3,     3,     5,     3,     3,     1,     1,
+     1,     1,     1,     1,     1,     1,     1,     1,     4,     1,
+     1,     1,     3,     3,     3,     2,     1,     1,     2,     1,
+     2,     1,     3,     2,     1,     2,     1,     2,     3,     2,
+     1,     3,     6,     8,     9,     1,     1,     1,     1,     2,
+     3,     2,     3,     2,     2,     2,     2,     1,     2,     1,
+     1,     1,     1,     1,     1,     3,     1,     1,     1,     1,
+     1,     1,     1,     1,     1
+};
+
+static const short yydefact[] = {     0,
+    49,    53,    51,    54,    60,   112,   113,    86,    50,    52,
+     0,     0,     0,     0,    98,     0,   100,    88,    89,    87,
+    56,    57,    58,    61,     0,     0,     0,     0,     0,     0,
+     0,     0,     0,     1,     2,     0,    55,     0,    67,   107,
+   108,   109,   110,   111,    94,    95,    96,     0,    13,   101,
+   103,   104,   102,    97,    66,   103,   104,    99,    90,    92,
+     5,     6,     4,     9,    10,     0,    81,     0,    68,     7,
+     8,     0,    68,     0,     0,     0,     0,     0,     0,     0,
+     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     0,     0,     0,     0,     0,     0,    11,    12,     0,     0,
+     0,    19,     0,     0,     0,    91,    93,    26,     0,     0,
+     0,    70,     0,     0,    69,    72,    75,    77,     0,     0,
+     3,    48,    47,     0,    45,    44,    43,    42,    41,    35,
+    36,    39,    40,    37,    38,    33,    34,    27,    31,    32,
+    28,    29,    30,     0,    14,     0,    16,     0,    21,    64,
+    65,    59,     0,    25,    82,    71,     0,    78,    80,     0,
+     0,    74,    76,    24,     0,    15,    17,    18,    22,     0,
+     0,    79,    73,    46,     0,    20,     0,    23,    83,     0,
+    84,   105,     0,     0,    85,   106,     0,     0,     0
+};
+
+static const short yydefgoto[] = {   187,
+    66,    35,   149,   170,    36,    37,    67,   115,   116,   117,
+   118,    68,    38,    54,   183,   151,    39
+};
+
+static const short yypact[] = {   159,
+-32768,-32768,-32768,-32768,-32768,-32768,   -13,-32768,-32768,-32768,
+    21,    21,    21,   220,   121,    21,   124,   -15,     3,-32768,
+-32768,-32768,-32768,-32768,   159,   159,   159,   159,   159,   159,
+   159,   159,   272,    80,   306,    32,-32768,    99,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,   159,   508,-32768,
+   100,   101,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+   508,   508,   508,   508,   508,    -4,-32768,   -52,    79,   508,
+   508,   -55,    92,   159,   159,   159,   159,   159,   159,   159,
+   159,   159,   159,   159,   159,   159,   159,   159,   159,   159,
+   159,   159,   159,   159,   159,   159,-32768,-32768,    90,   104,
+   159,-32768,    21,    21,   -35,-32768,-32768,-32768,   272,   159,
+   110,   157,    25,   209,-32768,    30,-32768,-32768,   159,    84,
+   306,   306,   306,   271,   358,   382,   405,   427,   448,   467,
+   467,   144,   144,   144,   144,   480,   480,   492,   502,   502,
+   508,   508,   508,   159,-32768,   159,-32768,    66,   159,   111,
+-32768,    31,   122,   508,-32768,-32768,    94,-32768,-32768,    95,
+    98,-32768,-32768,   508,   159,   508,   508,-32768,   306,    63,
+   107,-32768,-32768,   333,   159,-32768,   116,   306,   128,   239,
+-32768,   145,    64,   272,-32768,   145,   204,   205,-32768
+};
+
+static const short yypgoto[] = {-32768,
+     2,   -14,-32768,-32768,-32768,-32768,-32768,    -8,-32768,    93,
+   105,   -32,   -26,   193,-32768,     8,-32768
+};
+
+
+#define        YYLAST          566
+
+
+static const short yytable[] = {    49,
+    72,    34,   109,    69,   -62,   109,    73,    59,   119,   110,
+    61,    62,    63,    64,    65,   105,    70,    71,    45,    46,
+    47,    69,   109,    55,    74,    60,   152,   157,    40,    41,
+    42,    43,    44,     1,     2,     3,     4,     5,     6,     7,
+     8,     9,    10,    11,    12,    13,    14,    15,    16,   103,
+    17,    18,    19,    20,    21,    22,    23,   108,    24,   121,
+   122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
+   132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
+   142,   143,   153,    28,    29,   158,   113,   161,    30,    31,
+    32,   175,   184,    33,    74,   154,   111,    40,    41,    42,
+    43,    44,   148,   156,   164,   160,   145,   147,    74,   120,
+   150,    40,    41,    42,    43,    44,   104,    40,    41,    42,
+    43,    44,   106,   107,   176,   185,   168,   112,   -63,   166,
+    50,   167,   155,    50,   169,   113,   114,   154,   144,   171,
+   112,    51,    52,    53,    56,    57,    53,   182,   113,   114,
+   174,   186,   146,    73,   172,   177,   173,    73,   155,   159,
+   178,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+    10,    11,    12,    13,    14,    15,    16,   179,    17,    18,
+    19,    20,    21,    22,    23,   180,    24,    89,    90,    91,
+    92,    93,    94,    95,    96,    25,    97,    98,    99,   100,
+   101,   102,   109,   188,   189,   112,    26,    27,   162,    58,
+     0,    28,    29,   113,   114,     0,    30,    31,    32,     0,
+   163,    33,     1,     2,     3,     4,     5,     6,     7,     8,
+     9,    10,    11,    12,    13,    14,    15,    16,     0,    17,
+    18,    19,    20,    21,    22,    23,     0,    24,     8,     0,
+     0,    11,    12,    13,     0,    15,    25,   112,    17,    18,
+    19,    20,     0,     0,     0,   113,   114,    26,    27,     0,
+   159,     0,    28,    29,     0,     0,     0,    48,    31,    32,
+     0,     8,    33,     0,    11,    12,    13,     0,    15,     0,
+     0,    17,    18,    19,    20,     0,     0,    75,     0,     0,
+   181,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+    85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+    95,    96,     0,    97,    98,    99,   100,   101,   102,     0,
+     0,     0,    75,     0,     0,   165,    76,    77,    78,    79,
+    80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+    90,    91,    92,    93,    94,    95,    96,     0,    97,    98,
+    99,   100,   101,   102,    77,    78,    79,    80,    81,    82,
+    83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
+    93,    94,    95,    96,     0,    97,    98,    99,   100,   101,
+   102,    79,    80,    81,    82,    83,    84,    85,    86,    87,
+    88,    89,    90,    91,    92,    93,    94,    95,    96,     0,
+    97,    98,    99,   100,   101,   102,    80,    81,    82,    83,
+    84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
+    94,    95,    96,     0,    97,    98,    99,   100,   101,   102,
+    81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
+    91,    92,    93,    94,    95,    96,     0,    97,    98,    99,
+   100,   101,   102,    82,    83,    84,    85,    86,    87,    88,
+    89,    90,    91,    92,    93,    94,    95,    96,     0,    97,
+    98,    99,   100,   101,   102,    83,    84,    85,    86,    87,
+    88,    89,    90,    91,    92,    93,    94,    95,    96,     0,
+    97,    98,    99,   100,   101,   102,    85,    86,    87,    88,
+    89,    90,    91,    92,    93,    94,    95,    96,     0,    97,
+    98,    99,   100,   101,   102,    91,    92,    93,    94,    95,
+    96,     0,    97,    98,    99,   100,   101,   102,    92,    93,
+    94,    95,    96,     0,    97,    98,    99,   100,   101,   102,
+    94,    95,    96,     0,    97,    98,    99,   100,   101,   102,
+    97,    98,    99,   100,   101,   102
+};
+
+static const short yycheck[] = {    14,
+    33,     0,    58,    30,    18,    58,    33,    23,    64,    62,
+    25,    26,    27,    28,    29,    48,    31,    32,    11,    12,
+    13,    48,    58,    16,    29,    23,    62,     3,     8,     9,
+    10,    11,    12,     3,     4,     5,     6,     7,     8,     9,
+    10,    11,    12,    13,    14,    15,    16,    17,    18,    18,
+    20,    21,    22,    23,    24,    25,    26,    62,    28,    74,
+    75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+    85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+    95,    96,   109,    53,    54,    61,    57,    58,    58,    59,
+    60,    29,    29,    63,    29,   110,    18,     8,     9,    10,
+    11,    12,   101,   112,   119,   114,    99,   100,    29,    18,
+   103,     8,     9,    10,    11,    12,    18,     8,     9,    10,
+    11,    12,    23,    23,    62,    62,    61,    49,    18,   144,
+    10,   146,    49,    10,   149,    57,    58,   152,    49,    18,
+    49,    21,    22,    23,    21,    22,    23,   180,    57,    58,
+   165,   184,    49,   180,    61,    49,    62,   184,    49,    62,
+   175,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+    12,    13,    14,    15,    16,    17,    18,    62,    20,    21,
+    22,    23,    24,    25,    26,    58,    28,    44,    45,    46,
+    47,    48,    49,    50,    51,    37,    53,    54,    55,    56,
+    57,    58,    58,     0,     0,    49,    48,    49,   116,    17,
+    -1,    53,    54,    57,    58,    -1,    58,    59,    60,    -1,
+   116,    63,     3,     4,     5,     6,     7,     8,     9,    10,
+    11,    12,    13,    14,    15,    16,    17,    18,    -1,    20,
+    21,    22,    23,    24,    25,    26,    -1,    28,    10,    -1,
+    -1,    13,    14,    15,    -1,    17,    37,    49,    20,    21,
+    22,    23,    -1,    -1,    -1,    57,    58,    48,    49,    -1,
+    62,    -1,    53,    54,    -1,    -1,    -1,    58,    59,    60,
+    -1,    10,    63,    -1,    13,    14,    15,    -1,    17,    -1,
+    -1,    20,    21,    22,    23,    -1,    -1,    27,    -1,    -1,
+    62,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+    40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+    50,    51,    -1,    53,    54,    55,    56,    57,    58,    -1,
+    -1,    -1,    27,    -1,    -1,    65,    31,    32,    33,    34,
+    35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+    45,    46,    47,    48,    49,    50,    51,    -1,    53,    54,
+    55,    56,    57,    58,    32,    33,    34,    35,    36,    37,
+    38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+    48,    49,    50,    51,    -1,    53,    54,    55,    56,    57,
+    58,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+    43,    44,    45,    46,    47,    48,    49,    50,    51,    -1,
+    53,    54,    55,    56,    57,    58,    35,    36,    37,    38,
+    39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+    49,    50,    51,    -1,    53,    54,    55,    56,    57,    58,
+    36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+    46,    47,    48,    49,    50,    51,    -1,    53,    54,    55,
+    56,    57,    58,    37,    38,    39,    40,    41,    42,    43,
+    44,    45,    46,    47,    48,    49,    50,    51,    -1,    53,
+    54,    55,    56,    57,    58,    38,    39,    40,    41,    42,
+    43,    44,    45,    46,    47,    48,    49,    50,    51,    -1,
+    53,    54,    55,    56,    57,    58,    40,    41,    42,    43,
+    44,    45,    46,    47,    48,    49,    50,    51,    -1,    53,
+    54,    55,    56,    57,    58,    46,    47,    48,    49,    50,
+    51,    -1,    53,    54,    55,    56,    57,    58,    47,    48,
+    49,    50,    51,    -1,    53,    54,    55,    56,    57,    58,
+    49,    50,    51,    -1,    53,    54,    55,    56,    57,    58,
+    53,    54,    55,    56,    57,    58
+};
+#define YYPURE 1
+
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "bison.simple"
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984 Bob Corbett and Richard Stallman
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
+#include <alloca.h>
+#endif
+
+/* This is the parser code that is written into each bison parser
+  when the %semantic_parser declaration is not specified in the grammar.
+  It was written by Richard Stallman by simplifying the hairy parser
+  used when %semantic_parser is specified.  */
+
+/* Note: there must be only one dollar sign in this file.
+   It is replaced by the list of actions, each action
+   as one case of the switch.  */
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+#define YYFAIL         goto yyerrlab;
+#define YYACCEPT       return(0)
+#define YYABORT        return(1)
+#define YYERROR                goto yyerrlab
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+#ifndef YYIMPURE
+#define YYLEX          yylex()
+#endif
+
+#ifndef YYPURE
+#define YYLEX          yylex(&yylval, &yylloc)
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYIMPURE
+
+int    yychar;                 /*  the lookahead symbol                */
+YYSTYPE        yylval;                 /*  the semantic value of the           */
+                               /*  lookahead symbol                    */
+
+YYLTYPE yylloc;                        /*  location data for the lookahead     */
+                               /*  symbol                              */
+
+int yynerrs;                   /*  number of parse errors so far       */
+#endif  /* YYIMPURE */
+
+#if YYDEBUG != 0
+int yydebug;                   /*  nonzero means print parse trace     */
+/* Since this is uninitialized, it does not stop multiple parsers
+   from coexisting.  */
+#endif
+
+/*  YYMAXDEPTH indicates the initial size of the parser's stacks       */
+
+#ifndef        YYMAXDEPTH
+#define YYMAXDEPTH 200
+#endif
+
+/*  YYMAXLIMIT is the maximum size the stacks can grow to
+    (effective only if the built-in stack extension method is used).  */
+
+#ifndef YYMAXLIMIT
+#define YYMAXLIMIT 10000
+#endif
+
+
+#line 90 "bison.simple"
+int
+yyparse()
+{
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register YYSTYPE *yyvsp;
+  YYLTYPE *yylsp;
+  int yyerrstatus;     /*  number of tokens to shift before error messages enabled */
+  int yychar1;         /*  lookahead token as an internal (translated) token number */
+
+  short        yyssa[YYMAXDEPTH];      /*  the state stack                     */
+  YYSTYPE yyvsa[YYMAXDEPTH];   /*  the semantic value stack            */
+  YYLTYPE yylsa[YYMAXDEPTH];   /*  the location stack                  */
+
+  short *yyss = yyssa;         /*  refer to the stacks thru separate pointers */
+  YYSTYPE *yyvs = yyvsa;       /*  to allow yyoverflow to reallocate them elsewhere */
+  YYLTYPE *yyls = yylsa;
+
+  int yymaxdepth = YYMAXDEPTH;
+
+#ifndef YYPURE
+  int yychar;
+  YYSTYPE yylval;
+  YYLTYPE yylloc;
+  int yynerrs;
+#endif
+
+  YYSTYPE yyval;               /*  the variable used to return         */
+                               /*  semantic values from the action     */
+                               /*  routines                            */
+
+  int yylen;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.  */
+
+  yyssp = yyss - 1;
+  yyvsp = yyvs;
+  yylsp = yyls;
+
+/* Push a new state, which is found in  yystate  .  */
+/* In all cases, when you get here, the value and location stacks
+   have just been pushed. so pushing a state here evens the stacks.  */
+yynewstate:
+
+  *++yyssp = yystate;
+
+  if (yyssp >= yyss + yymaxdepth - 1)
+    {
+      /* Give user a chance to reallocate the stack */
+      /* Use copies of these so that the &'s don't force the real ones into memory. */
+      YYSTYPE *yyvs1 = yyvs;
+      YYLTYPE *yyls1 = yyls;
+      short *yyss1 = yyss;
+
+      /* Get the current used size of the three stacks, in elements.  */
+      int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      /* Each stack pointer address is followed by the size of
+        the data in use in that stack, in bytes.  */
+      yyoverflow("parser stack overflow",
+                &yyss1, size * sizeof (*yyssp),
+                &yyvs1, size * sizeof (*yyvsp),
+                &yyls1, size * sizeof (*yylsp),
+                &yymaxdepth);
+
+      yyss = yyss1; yyvs = yyvs1; yyls = yyls1;
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yymaxdepth >= YYMAXLIMIT)
+       yyerror("parser stack overflow");
+      yymaxdepth *= 2;
+      if (yymaxdepth > YYMAXLIMIT)
+       yymaxdepth = YYMAXLIMIT;
+      yyss = (short *) alloca (yymaxdepth * sizeof (*yyssp));
+      bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+      yyvs = (YYSTYPE *) alloca (yymaxdepth * sizeof (*yyvsp));
+      bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+      yyls = (YYLTYPE *) alloca (yymaxdepth * sizeof (*yylsp));
+      bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + size - 1;
+      yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+      yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Stack size increased to %d\n", yymaxdepth);
+#endif
+
+      if (yyssp >= yyss + yymaxdepth - 1)
+       YYABORT;
+    }
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+yyresume:
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Reading a token: ");
+#endif
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)             /* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Next token is %d (%s)\n", yychar, yytname[yychar1]);
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* count tokens shifted since error; after three, turn off error status.  */
+  if (yyerrstatus) yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+/* Do the default action for the current state.  */
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+yyreduce:
+  yylen = yyr2[yyn];
+  yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      if (yylen == 1)
+       fprintf (stderr, "Reducing 1 value via line %d, ",
+                yyrline[yyn]);
+      else
+       fprintf (stderr, "Reducing %d values via line %d, ",
+                yylen, yyrline[yyn]);
+    }
+#endif
+
+
+  switch (yyn) {
+
+case 3:
+#line 224 "../expread.y"
+{ write_exp_elt_opcode (BINOP_COMMA); ;
+    break;}
+case 4:
+#line 229 "../expread.y"
+{ write_exp_elt_opcode (UNOP_IND); ;
+    break;}
+case 5:
+#line 232 "../expread.y"
+{ write_exp_elt_opcode (UNOP_ADDR); ;
+    break;}
+case 6:
+#line 235 "../expread.y"
+{ write_exp_elt_opcode (UNOP_NEG); ;
+    break;}
+case 7:
+#line 239 "../expread.y"
+{ write_exp_elt_opcode (UNOP_ZEROP); ;
+    break;}
+case 8:
+#line 243 "../expread.y"
+{ write_exp_elt_opcode (UNOP_LOGNOT); ;
+    break;}
+case 9:
+#line 247 "../expread.y"
+{ write_exp_elt_opcode (UNOP_PREINCREMENT); ;
+    break;}
+case 10:
+#line 251 "../expread.y"
+{ write_exp_elt_opcode (UNOP_PREDECREMENT); ;
+    break;}
+case 11:
+#line 255 "../expread.y"
+{ write_exp_elt_opcode (UNOP_POSTINCREMENT); ;
+    break;}
+case 12:
+#line 259 "../expread.y"
+{ write_exp_elt_opcode (UNOP_POSTDECREMENT); ;
+    break;}
+case 13:
+#line 263 "../expread.y"
+{ write_exp_elt_opcode (UNOP_SIZEOF); ;
+    break;}
+case 14:
+#line 267 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_PTR);
+                         write_exp_string (yyvsp[0].sval);
+                         write_exp_elt_opcode (STRUCTOP_PTR); ;
+    break;}
+case 15:
+#line 273 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_MPTR); ;
+    break;}
+case 16:
+#line 277 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_exp_string (yyvsp[0].sval);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); ;
+    break;}
+case 17:
+#line 283 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_MEMBER); ;
+    break;}
+case 18:
+#line 287 "../expread.y"
+{ write_exp_elt_opcode (BINOP_SUBSCRIPT); ;
+    break;}
+case 19:
+#line 293 "../expread.y"
+{ start_arglist (); ;
+    break;}
+case 20:
+#line 295 "../expread.y"
+{ write_exp_elt_opcode (OP_FUNCALL);
+                         write_exp_elt_longcst ((LONGEST) end_arglist ());
+                         write_exp_elt_opcode (OP_FUNCALL); ;
+    break;}
+case 22:
+#line 304 "../expread.y"
+{ arglist_len = 1; ;
+    break;}
+case 23:
+#line 308 "../expread.y"
+{ arglist_len++; ;
+    break;}
+case 24:
+#line 312 "../expread.y"
+{ write_exp_elt_opcode (UNOP_MEMVAL);
+                         write_exp_elt_type (yyvsp[-2].tval);
+                         write_exp_elt_opcode (UNOP_MEMVAL); ;
+    break;}
+case 25:
+#line 318 "../expread.y"
+{ write_exp_elt_opcode (UNOP_CAST);
+                         write_exp_elt_type (yyvsp[-2].tval);
+                         write_exp_elt_opcode (UNOP_CAST); ;
+    break;}
+case 26:
+#line 324 "../expread.y"
+{ ;
+    break;}
+case 27:
+#line 330 "../expread.y"
+{ write_exp_elt_opcode (BINOP_REPEAT); ;
+    break;}
+case 28:
+#line 334 "../expread.y"
+{ write_exp_elt_opcode (BINOP_MUL); ;
+    break;}
+case 29:
+#line 338 "../expread.y"
+{ write_exp_elt_opcode (BINOP_DIV); ;
+    break;}
+case 30:
+#line 342 "../expread.y"
+{ write_exp_elt_opcode (BINOP_REM); ;
+    break;}
+case 31:
+#line 346 "../expread.y"
+{ write_exp_elt_opcode (BINOP_ADD); ;
+    break;}
+case 32:
+#line 350 "../expread.y"
+{ write_exp_elt_opcode (BINOP_SUB); ;
+    break;}
+case 33:
+#line 354 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LSH); ;
+    break;}
+case 34:
+#line 358 "../expread.y"
+{ write_exp_elt_opcode (BINOP_RSH); ;
+    break;}
+case 35:
+#line 362 "../expread.y"
+{ write_exp_elt_opcode (BINOP_EQUAL); ;
+    break;}
+case 36:
+#line 366 "../expread.y"
+{ write_exp_elt_opcode (BINOP_NOTEQUAL); ;
+    break;}
+case 37:
+#line 370 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LEQ); ;
+    break;}
+case 38:
+#line 374 "../expread.y"
+{ write_exp_elt_opcode (BINOP_GEQ); ;
+    break;}
+case 39:
+#line 378 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LESS); ;
+    break;}
+case 40:
+#line 382 "../expread.y"
+{ write_exp_elt_opcode (BINOP_GTR); ;
+    break;}
+case 41:
+#line 386 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LOGAND); ;
+    break;}
+case 42:
+#line 390 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LOGXOR); ;
+    break;}
+case 43:
+#line 394 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LOGIOR); ;
+    break;}
+case 44:
+#line 398 "../expread.y"
+{ write_exp_elt_opcode (BINOP_AND); ;
+    break;}
+case 45:
+#line 402 "../expread.y"
+{ write_exp_elt_opcode (BINOP_OR); ;
+    break;}
+case 46:
+#line 406 "../expread.y"
+{ write_exp_elt_opcode (TERNOP_COND); ;
+    break;}
+case 47:
+#line 410 "../expread.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN); ;
+    break;}
+case 48:
+#line 414 "../expread.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+                         write_exp_elt_opcode (yyvsp[-1].opcode);
+                         write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); ;
+    break;}
+case 49:
+#line 420 "../expread.y"
+{ write_exp_elt_opcode (OP_LONG);
+                         if (yyvsp[0].lval == (int) yyvsp[0].lval || yyvsp[0].lval == (unsigned int) yyvsp[0].lval)
+                           write_exp_elt_type (builtin_type_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         write_exp_elt_opcode (OP_LONG); ;
+    break;}
+case 50:
+#line 430 "../expread.y"
+{ YYSTYPE val;
+                         parse_number (yyvsp[0].ssym.stoken.ptr, yyvsp[0].ssym.stoken.length, 0, &val);
+                         write_exp_elt_opcode (OP_LONG);
+                         if (val.lval == (int) val.lval ||
+                             val.lval == (unsigned int) val.lval)
+                           write_exp_elt_type (builtin_type_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+                         write_exp_elt_longcst (val.lval);
+                         write_exp_elt_opcode (OP_LONG); ;
+    break;}
+case 51:
+#line 443 "../expread.y"
+{
+                         write_exp_elt_opcode (OP_LONG);
+                         if (yyvsp[0].ulval == (unsigned int) yyvsp[0].ulval)
+                           write_exp_elt_type (builtin_type_unsigned_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].ulval);
+                         write_exp_elt_opcode (OP_LONG);
+                       ;
+    break;}
+case 52:
+#line 455 "../expread.y"
+{ YYSTYPE val;
+                         parse_number (yyvsp[0].ssym.stoken.ptr, yyvsp[0].ssym.stoken.length, 0, &val);
+                         write_exp_elt_opcode (OP_LONG);
+                         if (val.ulval == (unsigned int) val.ulval)
+                           write_exp_elt_type (builtin_type_unsigned_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+                         write_exp_elt_longcst ((LONGEST)val.ulval);
+                         write_exp_elt_opcode (OP_LONG);
+                       ;
+    break;}
+case 53:
+#line 468 "../expread.y"
+{ write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (builtin_type_char);
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         write_exp_elt_opcode (OP_LONG); ;
+    break;}
+case 54:
+#line 475 "../expread.y"
+{ write_exp_elt_opcode (OP_DOUBLE);
+                         write_exp_elt_type (builtin_type_double);
+                         write_exp_elt_dblcst (yyvsp[0].dval);
+                         write_exp_elt_opcode (OP_DOUBLE); ;
+    break;}
+case 56:
+#line 485 "../expread.y"
+{ write_exp_elt_opcode (OP_LAST);
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         write_exp_elt_opcode (OP_LAST); ;
+    break;}
+case 57:
+#line 491 "../expread.y"
+{ write_exp_elt_opcode (OP_REGISTER);
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         write_exp_elt_opcode (OP_REGISTER); ;
+    break;}
+case 58:
+#line 497 "../expread.y"
+{ write_exp_elt_opcode (OP_INTERNALVAR);
+                         write_exp_elt_intern (yyvsp[0].ivar);
+                         write_exp_elt_opcode (OP_INTERNALVAR); ;
+    break;}
+case 59:
+#line 503 "../expread.y"
+{ write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (builtin_type_int);
+                         write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (yyvsp[-1].tval));
+                         write_exp_elt_opcode (OP_LONG); ;
+    break;}
+case 60:
+#line 510 "../expread.y"
+{ write_exp_elt_opcode (OP_STRING);
+                         write_exp_string (yyvsp[0].sval);
+                         write_exp_elt_opcode (OP_STRING); ;
+    break;}
+case 61:
+#line 517 "../expread.y"
+{ write_exp_elt_opcode (OP_THIS);
+                         write_exp_elt_opcode (OP_THIS); ;
+    break;}
+case 62:
+#line 524 "../expread.y"
+{
+                         if (yyvsp[0].ssym.sym != 0)
+                             yyval.bval = SYMBOL_BLOCK_VALUE (yyvsp[0].ssym.sym);
+                         else
+                           {
+                             struct symtab *tem =
+                                 lookup_symtab (copy_name (yyvsp[0].ssym.stoken));
+                             if (tem)
+                               yyval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1);
+                             else
+                               error ("No file or function \"%s\".",
+                                      copy_name (yyvsp[0].ssym.stoken));
+                           }
+                       ;
+    break;}
+case 63:
+#line 541 "../expread.y"
+{ struct symbol *tem
+                           = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+                                            VAR_NAMESPACE, 0, NULL);
+                         if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+                           error ("No function \"%s\" in specified context.",
+                                  copy_name (yyvsp[0].sval));
+                         yyval.bval = SYMBOL_BLOCK_VALUE (tem); ;
+    break;}
+case 64:
+#line 551 "../expread.y"
+{ struct symbol *sym;
+                         sym = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+                                              VAR_NAMESPACE, 0, NULL);
+                         if (sym == 0)
+                           error ("No symbol \"%s\" in specified context.",
+                                  copy_name (yyvsp[0].sval));
+                         write_exp_elt_opcode (OP_VAR_VALUE);
+                         write_exp_elt_sym (sym);
+                         write_exp_elt_opcode (OP_VAR_VALUE); ;
+    break;}
+case 65:
+#line 563 "../expread.y"
+{
+                         struct type *type = yyvsp[-2].tval;
+                         if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+                             && TYPE_CODE (type) != TYPE_CODE_UNION)
+                           error ("`%s' is not defined as an aggregate type.",
+                                  TYPE_NAME (type));
+
+                         write_exp_elt_opcode (OP_SCOPE);
+                         write_exp_elt_type (type);
+                         write_exp_string (yyvsp[0].sval);
+                         write_exp_elt_opcode (OP_SCOPE);
+                       ;
+    break;}
+case 66:
+#line 576 "../expread.y"
+{
+                         char *name = copy_name (yyvsp[0].sval);
+                         struct symbol *sym;
+                         int i;
+
+                         sym =
+                           lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+                         if (sym)
+                           {
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                             write_exp_elt_sym (sym);
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                             break;
+                           }
+                         for (i = 0; i < misc_function_count; i++)
+                           if (!strcmp (misc_function_vector[i].name, name))
+                             break;
+
+                         if (i < misc_function_count)
+                           {
+                             enum misc_function_type mft =
+                                 misc_function_vector[i].type;
+                             
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_type (builtin_type_int);
+                             write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_opcode (UNOP_MEMVAL);
+                             if (mft == mf_data || mft == mf_bss)
+                               write_exp_elt_type (builtin_type_int);
+                             else if (mft == mf_text)
+                               write_exp_elt_type (lookup_function_type (builtin_type_int));
+                             else
+                               write_exp_elt_type (builtin_type_char);
+                             write_exp_elt_opcode (UNOP_MEMVAL);
+                           }
+                         else
+                           if (symtab_list == 0
+                               && partial_symtab_list == 0)
+                             error ("No symbol table is loaded.  Use the \"file\" command.");
+                           else
+                             error ("No symbol \"%s\" in current context.", name);
+                       ;
+    break;}
+case 67:
+#line 622 "../expread.y"
+{ struct symbol *sym = yyvsp[0].ssym.sym;
+
+                         if (sym)
+                           {
+                             switch (sym->class)
+                               {
+                               case LOC_REGISTER:
+                               case LOC_ARG:
+                               case LOC_LOCAL:
+                               case LOC_LOCAL_ARG:
+                                 if (innermost_block == 0 ||
+                                     contained_in (block_found, 
+                                                   innermost_block))
+                                   innermost_block = block_found;
+                               }
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                             write_exp_elt_sym (sym);
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                           }
+                         else if (yyvsp[0].ssym.is_a_field_of_this)
+                           {
+                             /* C++: it hangs off of `this'.  Must
+                                not inadvertently convert from a method call
+                                to data ref.  */
+                             if (innermost_block == 0 || 
+                                 contained_in (block_found, innermost_block))
+                               innermost_block = block_found;
+                             write_exp_elt_opcode (OP_THIS);
+                             write_exp_elt_opcode (OP_THIS);
+                             write_exp_elt_opcode (STRUCTOP_PTR);
+                             write_exp_string (yyvsp[0].ssym.stoken);
+                             write_exp_elt_opcode (STRUCTOP_PTR);
+                           }
+                         else
+                           {
+                             register int i;
+                             register char *arg = copy_name (yyvsp[0].ssym.stoken);
+
+                               /* FIXME, this search is linear!  At least
+                                  optimize the strcmp with a 1-char cmp... */
+                             for (i = 0; i < misc_function_count; i++)
+                               if (!strcmp (misc_function_vector[i].name, arg))
+                                 break;
+
+                             if (i < misc_function_count)
+                               {
+                                 enum misc_function_type mft =
+                                     misc_function_vector[i].type;
+                                 
+                                 write_exp_elt_opcode (OP_LONG);
+                                 write_exp_elt_type (builtin_type_int);
+                                 write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+                                 write_exp_elt_opcode (OP_LONG);
+                                 write_exp_elt_opcode (UNOP_MEMVAL);
+                                 if (mft == mf_data || mft == mf_bss)
+                                   write_exp_elt_type (builtin_type_int);
+                                 else if (mft == mf_text)
+                                   write_exp_elt_type (lookup_function_type (builtin_type_int));
+                                 else
+                                   write_exp_elt_type (builtin_type_char);
+                                 write_exp_elt_opcode (UNOP_MEMVAL);
+                               }
+                             else if (symtab_list == 0
+                                      && partial_symtab_list == 0)
+                               error ("No symbol table is loaded.  Use the \"file\" command.");
+                             else
+                               error ("No symbol \"%s\" in current context.",
+                                      copy_name (yyvsp[0].ssym.stoken));
+                           }
+                       ;
+    break;}
+case 69:
+#line 697 "../expread.y"
+{
+                 /* This is where the interesting stuff happens.  */
+                 int done = 0;
+                 int array_size;
+                 struct type *follow_type = yyvsp[-1].tval;
+                 
+                 while (!done)
+                   switch (pop_type ())
+                     {
+                     case tp_end:
+                       done = 1;
+                       break;
+                     case tp_pointer:
+                       follow_type = lookup_pointer_type (follow_type);
+                       break;
+                     case tp_reference:
+                       follow_type = lookup_reference_type (follow_type);
+                       break;
+                     case tp_array:
+                       array_size = (int) pop_type ();
+                       if (array_size != -1)
+                         follow_type = create_array_type (follow_type,
+                                                          array_size);
+                       else
+                         follow_type = lookup_pointer_type (follow_type);
+                       break;
+                     case tp_function:
+                       follow_type = lookup_function_type (follow_type);
+                       break;
+                     }
+                 yyval.tval = follow_type;
+               ;
+    break;}
+case 70:
+#line 732 "../expread.y"
+{ push_type (tp_pointer); yyval.voidval = 0; ;
+    break;}
+case 71:
+#line 734 "../expread.y"
+{ push_type (tp_pointer); yyval.voidval = yyvsp[0].voidval; ;
+    break;}
+case 73:
+#line 739 "../expread.y"
+{ yyval.voidval = yyvsp[-1].voidval; ;
+    break;}
+case 74:
+#line 741 "../expread.y"
+{
+                         push_type ((enum type_pieces) yyvsp[0].lval);
+                         push_type (tp_array);
+                       ;
+    break;}
+case 75:
+#line 746 "../expread.y"
+{
+                         push_type ((enum type_pieces) yyvsp[0].lval);
+                         push_type (tp_array);
+                         yyval.voidval = 0;
+                       ;
+    break;}
+case 76:
+#line 752 "../expread.y"
+{ push_type (tp_function); ;
+    break;}
+case 77:
+#line 754 "../expread.y"
+{ push_type (tp_function); ;
+    break;}
+case 78:
+#line 758 "../expread.y"
+{ yyval.lval = -1; ;
+    break;}
+case 79:
+#line 760 "../expread.y"
+{ yyval.lval = yyvsp[-1].lval; ;
+    break;}
+case 80:
+#line 764 "../expread.y"
+{ yyval.voidval = 0; ;
+    break;}
+case 82:
+#line 769 "../expread.y"
+{ yyval.tval = lookup_member_type (builtin_type_int, yyvsp[-2].tval); ;
+    break;}
+case 83:
+#line 771 "../expread.y"
+{ yyval.tval = lookup_member_type (yyvsp[-5].tval, yyvsp[-3].tval); ;
+    break;}
+case 84:
+#line 773 "../expread.y"
+{ yyval.tval = lookup_member_type
+                           (lookup_function_type (yyvsp[-7].tval), yyvsp[-5].tval); ;
+    break;}
+case 85:
+#line 776 "../expread.y"
+{ yyval.tval = lookup_member_type
+                           (lookup_function_type (yyvsp[-8].tval), yyvsp[-6].tval);
+                         free (yyvsp[-1].tvec); ;
+    break;}
+case 86:
+#line 783 "../expread.y"
+{ yyval.tval = yyvsp[0].tsym.type; ;
+    break;}
+case 87:
+#line 785 "../expread.y"
+{ yyval.tval = builtin_type_int; ;
+    break;}
+case 88:
+#line 787 "../expread.y"
+{ yyval.tval = builtin_type_long; ;
+    break;}
+case 89:
+#line 789 "../expread.y"
+{ yyval.tval = builtin_type_short; ;
+    break;}
+case 90:
+#line 791 "../expread.y"
+{ yyval.tval = builtin_type_long; ;
+    break;}
+case 91:
+#line 793 "../expread.y"
+{ yyval.tval = builtin_type_unsigned_long; ;
+    break;}
+case 92:
+#line 795 "../expread.y"
+{ yyval.tval = builtin_type_short; ;
+    break;}
+case 93:
+#line 797 "../expread.y"
+{ yyval.tval = builtin_type_unsigned_short; ;
+    break;}
+case 94:
+#line 799 "../expread.y"
+{ yyval.tval = lookup_struct (copy_name (yyvsp[0].sval),
+                                             expression_context_block); ;
+    break;}
+case 95:
+#line 802 "../expread.y"
+{ yyval.tval = lookup_union (copy_name (yyvsp[0].sval),
+                                            expression_context_block); ;
+    break;}
+case 96:
+#line 805 "../expread.y"
+{ yyval.tval = lookup_enum (copy_name (yyvsp[0].sval),
+                                           expression_context_block); ;
+    break;}
+case 97:
+#line 808 "../expread.y"
+{ yyval.tval = lookup_unsigned_typename (TYPE_NAME(yyvsp[0].tsym.type)); ;
+    break;}
+case 98:
+#line 810 "../expread.y"
+{ yyval.tval = builtin_type_unsigned_int; ;
+    break;}
+case 99:
+#line 812 "../expread.y"
+{ yyval.tval = yyvsp[0].tsym.type; ;
+    break;}
+case 100:
+#line 814 "../expread.y"
+{ yyval.tval = builtin_type_int; ;
+    break;}
+case 102:
+#line 819 "../expread.y"
+{
+                 yyval.tsym.stoken.ptr = "int";
+                 yyval.tsym.stoken.length = 3;
+                 yyval.tsym.type = builtin_type_int;
+               ;
+    break;}
+case 103:
+#line 825 "../expread.y"
+{
+                 yyval.tsym.stoken.ptr = "long";
+                 yyval.tsym.stoken.length = 4;
+                 yyval.tsym.type = builtin_type_long;
+               ;
+    break;}
+case 104:
+#line 831 "../expread.y"
+{
+                 yyval.tsym.stoken.ptr = "short";
+                 yyval.tsym.stoken.length = 5;
+                 yyval.tsym.type = builtin_type_short;
+               ;
+    break;}
+case 105:
+#line 840 "../expread.y"
+{ yyval.tvec = (struct type **)xmalloc (sizeof (struct type *) * 2);
+                 yyval.tvec[0] = (struct type *)0;
+                 yyval.tvec[1] = yyvsp[0].tval;
+               ;
+    break;}
+case 106:
+#line 845 "../expread.y"
+{ int len = sizeof (struct type *) * ++(yyvsp[-2].ivec[0]);
+                 yyval.tvec = (struct type **)xrealloc (yyvsp[-2].tvec, len);
+                 yyval.tvec[yyval.ivec[0]] = yyvsp[0].tval;
+               ;
+    break;}
+case 107:
+#line 851 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+    break;}
+case 108:
+#line 852 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+    break;}
+case 109:
+#line 853 "../expread.y"
+{ yyval.sval = yyvsp[0].tsym.stoken; ;
+    break;}
+case 110:
+#line 854 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+    break;}
+case 111:
+#line 855 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+    break;}
+}
+   /* the action file gets copied in in place of this dollarsign */
+#line 327 "bison.simple"
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != yyssp)
+       fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+  yylsp++;
+  if (yylen == 0)
+    {
+      yylsp->first_line = yylloc.first_line;
+      yylsp->first_column = yylloc.first_column;
+      yylsp->last_line = (yylsp-1)->last_line;
+      yylsp->last_column = (yylsp-1)->last_column;
+      yylsp->text = 0;
+    }
+  else
+    {
+      yylsp->last_line = (yylsp+yylen-1)->last_line;
+      yylsp->last_column = (yylsp+yylen-1)->last_column;
+    }
+#endif
+
+  /* Now "shift" the result of the reduction.
+     Determine what state that goes to,
+     based on the state we popped back to
+     and the rule number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yyerrlab:   /* here on detecting error */
+
+  if (! yyerrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++yynerrs;
+      yyerror("parse error");
+    }
+
+  if (yyerrstatus == 3)
+    {
+      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+       YYABORT;
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token
+     after shifting the error token.  */
+
+  yyerrstatus = 3;             /* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+yyerrdefault:  /* current state does not do anything special for the error token. */
+
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
+  if (yyn) goto yydefault;
+#endif
+
+yyerrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (yyssp == yyss) YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != yyssp)
+       fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+yyerrhandle:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+}
+#line 864 "../expread.y"
+
+\f
+/* Begin counting arguments for a function call,
+   saving the data about any containing call.  */
+
+static void
+start_arglist ()
+{
+  register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+
+  new->next = funcall_chain;
+  new->arglist_len = arglist_len;
+  arglist_len = 0;
+  funcall_chain = new;
+}
+
+/* Return the number of arguments in a function call just terminated,
+   and restore the data for the containing function call.  */
+
+static int
+end_arglist ()
+{
+  register int val = arglist_len;
+  register struct funcall *call = funcall_chain;
+  funcall_chain = call->next;
+  arglist_len = call->arglist_len;
+  free (call);
+  return val;
+}
+
+/* Free everything in the funcall chain.
+   Used when there is an error inside parsing.  */
+
+static void
+free_funcalls ()
+{
+  register struct funcall *call, *next;
+
+  for (call = funcall_chain; call; call = next)
+    {
+      next = call->next;
+      free (call);
+    }
+}
+\f
+/* This page contains the functions for adding data to the  struct expression
+   being constructed.  */
+
+/* Add one element to the end of the expression.  */
+
+/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
+   a register through here */
+
+static void
+write_exp_elt (expelt)
+     union exp_element expelt;
+{
+  if (expout_ptr >= expout_size)
+    {
+      expout_size *= 2;
+      expout = (struct expression *) xrealloc (expout,
+                                              sizeof (struct expression)
+                                              + expout_size * sizeof (union exp_element));
+    }
+  expout->elts[expout_ptr++] = expelt;
+}
+
+static void
+write_exp_elt_opcode (expelt)
+     enum exp_opcode expelt;
+{
+  union exp_element tmp;
+
+  tmp.opcode = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_sym (expelt)
+     struct symbol *expelt;
+{
+  union exp_element tmp;
+
+  tmp.symbol = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_longcst (expelt)
+     LONGEST expelt;
+{
+  union exp_element tmp;
+
+  tmp.longconst = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_dblcst (expelt)
+     double expelt;
+{
+  union exp_element tmp;
+
+  tmp.doubleconst = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_type (expelt)
+     struct type *expelt;
+{
+  union exp_element tmp;
+
+  tmp.type = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_intern (expelt)
+     struct internalvar *expelt;
+{
+  union exp_element tmp;
+
+  tmp.internalvar = expelt;
+
+  write_exp_elt (tmp);
+}
+
+/* Add a string constant to the end of the expression.
+   Follow it by its length in bytes, as a separate exp_element.  */
+
+static void
+write_exp_string (str)
+     struct stoken str;
+{
+  register int len = str.length;
+  register int lenelt
+    = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+
+  expout_ptr += lenelt;
+
+  if (expout_ptr >= expout_size)
+    {
+      expout_size = max (expout_size * 2, expout_ptr + 10);
+      expout = (struct expression *)
+       xrealloc (expout, (sizeof (struct expression)
+                          + (expout_size * sizeof (union exp_element))));
+    }
+  bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
+  ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+  write_exp_elt_longcst ((LONGEST) len);
+}
+\f
+/* During parsing of a C expression, the pointer to the next character
+   is in this variable.  */
+
+static char *lexptr;
+
+/* Tokens that refer to names do so with explicit pointer and length,
+   so they can share the storage that lexptr is parsing.
+
+   When it is necessary to pass a name to a function that expects
+   a null-terminated string, the substring is copied out
+   into a block of storage that namecopy points to.
+
+   namecopy is allocated once, guaranteed big enough, for each parsing.  */
+
+static char *namecopy;
+
+/* Current depth in parentheses within the expression.  */
+
+static int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses).  */
+
+static int comma_terminates;
+
+/* Take care of parsing a number (anything that starts with a digit).
+   Set yylval and return the token type; update lexptr.
+   LEN is the number of characters in it.  */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+     register char *p;
+     register int len;
+     int parsed_float;
+     YYSTYPE *putithere;
+{
+  register LONGEST n = 0;
+  register int i;
+  register int c;
+  register int base = input_radix;
+  int unsigned_p = 0;
+
+  extern double atof ();
+
+  if (parsed_float)
+    {
+      /* It's a float since it contains a point or an exponent.  */
+      putithere->dval = atof (p);
+      return FLOAT;
+    }
+
+  /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+  if (p[0] == '0')
+    switch (p[1])
+      {
+      case 'x':
+      case 'X':
+       if (len >= 3)
+         {
+           p += 2;
+           base = 16;
+           len -= 2;
+         }
+       break;
+
+      case 't':
+      case 'T':
+      case 'd':
+      case 'D':
+       if (len >= 3)
+         {
+           p += 2;
+           base = 10;
+           len -= 2;
+         }
+       break;
+
+      default:
+       base = 8;
+       break;
+      }
+
+  while (len-- > 0)
+    {
+      c = *p++;
+      if (c >= 'A' && c <= 'Z')
+       c += 'a' - 'A';
+      if (c != 'l' && c != 'u')
+       n *= base;
+      if (c >= '0' && c <= '9')
+       n += i = c - '0';
+      else
+       {
+         if (base > 10 && c >= 'a' && c <= 'f')
+           n += i = c - 'a' + 10;
+         else if (len == 0 && c == 'l')
+           ;
+         else if (len == 0 && c == 'u')
+           unsigned_p = 1;
+         else
+           return ERROR;       /* Char not a digit */
+       }
+      if (i >= base)
+       return ERROR;           /* Invalid digit in this base */
+    }
+
+  if (unsigned_p)
+    {
+      putithere->ulval = n;
+      return UINT;
+    }
+  else
+    {
+      putithere->lval = n;
+      return INT;
+    }
+}
+
+struct token
+{
+  char *operator;
+  int token;
+  enum exp_opcode opcode;
+};
+
+static struct token tokentab3[] =
+  {
+    {">>=", ASSIGN_MODIFY, BINOP_RSH},
+    {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+  };
+
+static struct token tokentab2[] =
+  {
+    {"+=", ASSIGN_MODIFY, BINOP_ADD},
+    {"-=", ASSIGN_MODIFY, BINOP_SUB},
+    {"*=", ASSIGN_MODIFY, BINOP_MUL},
+    {"/=", ASSIGN_MODIFY, BINOP_DIV},
+    {"%=", ASSIGN_MODIFY, BINOP_REM},
+    {"|=", ASSIGN_MODIFY, BINOP_LOGIOR},
+    {"&=", ASSIGN_MODIFY, BINOP_LOGAND},
+    {"^=", ASSIGN_MODIFY, BINOP_LOGXOR},
+    {"++", INCREMENT, BINOP_END},
+    {"--", DECREMENT, BINOP_END},
+    {"->", ARROW, BINOP_END},
+    {"&&", AND, BINOP_END},
+    {"||", OR, BINOP_END},
+    {"::", COLONCOLON, BINOP_END},
+    {"<<", LSH, BINOP_END},
+    {">>", RSH, BINOP_END},
+    {"==", EQUAL, BINOP_END},
+    {"!=", NOTEQUAL, BINOP_END},
+    {"<=", LEQ, BINOP_END},
+    {">=", GEQ, BINOP_END}
+  };
+
+/* assign machine-independent names to certain registers 
+ * (unless overridden by the REGISTER_NAMES table)
+ */
+struct std_regs {
+       char *name;
+       int regnum;
+} std_regs[] = {
+#ifdef PC_REGNUM
+       { "pc", PC_REGNUM },
+#endif
+#ifdef FP_REGNUM
+       { "fp", FP_REGNUM },
+#endif
+#ifdef SP_REGNUM
+       { "sp", SP_REGNUM },
+#endif
+#ifdef PS_REGNUM
+       { "ps", PS_REGNUM },
+#endif
+};
+
+#define NUM_STD_REGS (sizeof std_regs / sizeof std_regs[0])
+
+/* Read one token, getting characters through lexptr.  */
+
+static int
+yylex ()
+{
+  register int c;
+  register int namelen;
+  register unsigned i;
+  register char *tokstart;
+
+ retry:
+
+  tokstart = lexptr;
+  /* See if it is a special token of length 3.  */
+  for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+    if (!strncmp (tokstart, tokentab3[i].operator, 3))
+      {
+       lexptr += 3;
+       yylval.opcode = tokentab3[i].opcode;
+       return tokentab3[i].token;
+      }
+
+  /* See if it is a special token of length 2.  */
+  for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+    if (!strncmp (tokstart, tokentab2[i].operator, 2))
+      {
+       lexptr += 2;
+       yylval.opcode = tokentab2[i].opcode;
+       return tokentab2[i].token;
+      }
+
+  switch (c = *tokstart)
+    {
+    case 0:
+      return 0;
+
+    case ' ':
+    case '\t':
+    case '\n':
+      lexptr++;
+      goto retry;
+
+    case '\'':
+      lexptr++;
+      c = *lexptr++;
+      if (c == '\\')
+       c = parse_escape (&lexptr);
+      yylval.lval = c;
+      c = *lexptr++;
+      if (c != '\'')
+       error ("Invalid character constant.");
+      return CHAR;
+
+    case '(':
+      paren_depth++;
+      lexptr++;
+      return c;
+
+    case ')':
+      if (paren_depth == 0)
+       return 0;
+      paren_depth--;
+      lexptr++;
+      return c;
+
+    case ',':
+      if (comma_terminates && paren_depth == 0)
+       return 0;
+      lexptr++;
+      return c;
+
+    case '.':
+      /* Might be a floating point number.  */
+      if (lexptr[1] < '0' || lexptr[1] > '9')
+       goto symbol;            /* Nope, must be a symbol. */
+      /* FALL THRU into number case.  */
+
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      {
+       /* It's a number.  */
+       int got_dot = 0, got_e = 0, toktype;
+       register char *p = tokstart;
+       int hex = input_radix > 10;
+
+       if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+         {
+           p += 2;
+           hex = 1;
+         }
+       else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+         {
+           p += 2;
+           hex = 0;
+         }
+
+       for (;; ++p)
+         {
+           if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+             got_dot = got_e = 1;
+           else if (!hex && !got_dot && *p == '.')
+             got_dot = 1;
+           else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+                    && (*p == '-' || *p == '+'))
+             /* This is the sign of the exponent, not the end of the
+                number.  */
+             continue;
+           /* We will take any letters or digits.  parse_number will
+              complain if past the radix, or if L or U are not final.  */
+           else if ((*p < '0' || *p > '9')
+                    && ((*p < 'a' || *p > 'z')
+                                 && (*p < 'A' || *p > 'Z')))
+             break;
+         }
+       toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
+        if (toktype == ERROR)
+         {
+           char *err_copy = (char *) alloca (p - tokstart + 1);
+
+           bcopy (tokstart, err_copy, p - tokstart);
+           err_copy[p - tokstart] = 0;
+           error ("Invalid number \"%s\".", err_copy);
+         }
+       lexptr = p;
+       return toktype;
+      }
+
+    case '+':
+    case '-':
+    case '*':
+    case '/':
+    case '%':
+    case '|':
+    case '&':
+    case '^':
+    case '~':
+    case '!':
+    case '@':
+    case '<':
+    case '>':
+    case '[':
+    case ']':
+    case '?':
+    case ':':
+    case '=':
+    case '{':
+    case '}':
+    symbol:
+      lexptr++;
+      return c;
+
+    case '"':
+      for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++)
+       if (c == '\\')
+         {
+           c = tokstart[++namelen];
+           if (c >= '0' && c <= '9')
+             {
+               c = tokstart[++namelen];
+               if (c >= '0' && c <= '9')
+                 c = tokstart[++namelen];
+             }
+         }
+      yylval.sval.ptr = tokstart + 1;
+      yylval.sval.length = namelen - 1;
+      lexptr += namelen + 1;
+      return STRING;
+    }
+
+  if (!(c == '_' || c == '$'
+       || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+    /* We must have come across a bad character (e.g. ';').  */
+    error ("Invalid character '%c' in expression.", c);
+
+  /* It's a name.  See how long it is.  */
+  namelen = 0;
+  for (c = tokstart[namelen];
+       (c == '_' || c == '$' || (c >= '0' && c <= '9')
+       || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+       c = tokstart[++namelen])
+    ;
+
+  /* The token "if" terminates the expression and is NOT 
+     removed from the input stream.  */
+  if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+    {
+      return 0;
+    }
+
+  lexptr += namelen;
+
+  /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+     and $$digits (equivalent to $<-digits> if you could type that).
+     Make token type LAST, and put the number (the digits) in yylval.  */
+
+  if (*tokstart == '$')
+    {
+      register int negate = 0;
+      c = 1;
+      /* Double dollar means negate the number and add -1 as well.
+        Thus $$ alone means -1.  */
+      if (namelen >= 2 && tokstart[1] == '$')
+       {
+         negate = 1;
+         c = 2;
+       }
+      if (c == namelen)
+       {
+         /* Just dollars (one or two) */
+         yylval.lval = - negate;
+         return LAST;
+       }
+      /* Is the rest of the token digits?  */
+      for (; c < namelen; c++)
+       if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
+         break;
+      if (c == namelen)
+       {
+         yylval.lval = atoi (tokstart + 1 + negate);
+         if (negate)
+           yylval.lval = - yylval.lval;
+         return LAST;
+       }
+    }
+
+  /* Handle tokens that refer to machine registers:
+     $ followed by a register name.  */
+
+  if (*tokstart == '$') {
+    for (c = 0; c < NUM_REGS; c++)
+      if (namelen - 1 == strlen (reg_names[c])
+         && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+       {
+         yylval.lval = c;
+         return REGNAME;
+       }
+    for (c = 0; c < NUM_STD_REGS; c++)
+     if (namelen - 1 == strlen (std_regs[c].name)
+        && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+       {
+        yylval.lval = std_regs[c].regnum;
+        return REGNAME;
+       }
+  }
+  /* Catch specific keywords.  Should be done with a data structure.  */
+  switch (namelen)
+    {
+    case 8:
+      if (!strncmp (tokstart, "unsigned", 8))
+       return UNSIGNED;
+      break;
+    case 6:
+      if (!strncmp (tokstart, "struct", 6))
+       return STRUCT;
+      if (!strncmp (tokstart, "signed", 6))
+       return SIGNED;
+      if (!strncmp (tokstart, "sizeof", 6))      
+       return SIZEOF;
+      break;
+    case 5:
+      if (!strncmp (tokstart, "union", 5))
+       return UNION;
+      if (!strncmp (tokstart, "short", 5))
+       return SHORT;
+      break;
+    case 4:
+      if (!strncmp (tokstart, "enum", 4))
+       return ENUM;
+      if (!strncmp (tokstart, "long", 4))
+       return LONG;
+      if (!strncmp (tokstart, "this", 4))
+       {
+         static const char this_name[] =
+                                { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
+
+         if (lookup_symbol (this_name, expression_context_block,
+                            VAR_NAMESPACE, 0, NULL))
+           return THIS;
+       }
+      break;
+    case 3:
+      if (!strncmp (tokstart, "int", 3))
+       return INT_KEYWORD;
+      break;
+    default:
+      break;
+    }
+
+  yylval.sval.ptr = tokstart;
+  yylval.sval.length = namelen;
+
+  /* Any other names starting in $ are debugger internal variables.  */
+
+  if (*tokstart == '$')
+    {
+      yylval.ivar =  lookup_internalvar (copy_name (yylval.sval) + 1);
+      return VARIABLE;
+    }
+
+  /* Use token-type BLOCKNAME for symbols that happen to be defined as
+     functions or symtabs.  If this is not so, then ...
+     Use token-type TYPENAME for symbols that happen to be defined
+     currently as names of types; NAME for other symbols.
+     The caller is not constrained to care about the distinction.  */
+  {
+    char *tmp = copy_name (yylval.sval);
+    struct symbol *sym;
+    int is_a_field_of_this = 0;
+    int hextype;
+
+    sym = lookup_symbol (tmp, expression_context_block,
+                        VAR_NAMESPACE, &is_a_field_of_this, NULL);
+    if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
+        lookup_partial_symtab (tmp))
+      {
+       yylval.ssym.sym = sym;
+       yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+       return BLOCKNAME;
+      }
+    if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+        {
+         yylval.tsym.type = SYMBOL_TYPE (sym);
+         return TYPENAME;
+        }
+    if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+       return TYPENAME;
+
+    /* Input names that aren't symbols but ARE valid hex numbers,
+       when the input radix permits them, can be names or numbers
+       depending on the parse.  Note we support radixes > 16 here.  */
+    if (!sym && 
+        ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
+         (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+      {
+       YYSTYPE newlval;        /* Its value is ignored.  */
+       hextype = parse_number (tokstart, namelen, 0, &newlval);
+       if (hextype == INT)
+         {
+           yylval.ssym.sym = sym;
+           yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+           return NAME_OR_INT;
+         }
+       if (hextype == UINT)
+         {
+           yylval.ssym.sym = sym;
+           yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+           return NAME_OR_UINT;
+         }
+      }
+
+    /* Any other kind of symbol */
+    yylval.ssym.sym = sym;
+    yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+    return NAME;
+  }
+}
+
+static void
+yyerror (msg)
+     char *msg;
+{
+  error ("Invalid syntax in expression.");
+}
+
+/* Return a null-terminated temporary copy of the name
+   of a string token.  */
+
+static char *
+copy_name (token)
+     struct stoken token;
+{
+  bcopy (token.ptr, namecopy, token.length);
+  namecopy[token.length] = 0;
+  return namecopy;
+}
+\f
+/* Reverse an expression from suffix form (in which it is constructed)
+   to prefix form (in which we can conveniently print or execute it).  */
+
+static void prefixify_subexp ();
+
+static void
+prefixify_expression (expr)
+     register struct expression *expr;
+{
+  register int len = sizeof (struct expression) +
+                                   expr->nelts * sizeof (union exp_element);
+  register struct expression *temp;
+  register int inpos = expr->nelts, outpos = 0;
+
+  temp = (struct expression *) alloca (len);
+
+  /* Copy the original expression into temp.  */
+  bcopy (expr, temp, len);
+
+  prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the subexpression of EXPR
+   whose last exp_element is at index ENDPOS - 1 in EXPR.  */
+
+static int
+length_of_subexp (expr, endpos)
+     register struct expression *expr;
+     register int endpos;
+{
+  register int oplen = 1;
+  register int args = 0;
+  register int i;
+
+  if (endpos < 0)
+    error ("?error in length_of_subexp");
+
+  i = (int) expr->elts[endpos - 1].opcode;
+
+  switch (i)
+    {
+      /* C++  */
+    case OP_SCOPE:
+      oplen = 4 + ((expr->elts[endpos - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+      break;
+
+    case OP_LONG:
+    case OP_DOUBLE:
+      oplen = 4;
+      break;
+
+    case OP_VAR_VALUE:
+    case OP_LAST:
+    case OP_REGISTER:
+    case OP_INTERNALVAR:
+      oplen = 3;
+      break;
+
+    case OP_FUNCALL:
+      oplen = 3;
+      args = 1 + expr->elts[endpos - 2].longconst;
+      break;
+
+    case UNOP_CAST:
+    case UNOP_MEMVAL:
+      oplen = 3;
+      args = 1;
+      break;
+
+    case STRUCTOP_STRUCT:
+    case STRUCTOP_PTR:
+      args = 1;
+    case OP_STRING:
+      oplen = 3 + ((expr->elts[endpos - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+      break;
+
+    case TERNOP_COND:
+      args = 3;
+      break;
+
+    case BINOP_ASSIGN_MODIFY:
+      oplen = 3;
+      args = 2;
+      break;
+
+      /* C++ */
+    case OP_THIS:
+      oplen = 2;
+      break;
+
+    default:
+      args = 1 + (i < (int) BINOP_END);
+    }
+
+  while (args > 0)
+    {
+      oplen += length_of_subexp (expr, endpos - oplen);
+      args--;
+    }
+
+  return oplen;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+   into OUTEXPR, starting at index OUTBEG.
+   In the process, convert it from suffix to prefix form.  */
+
+static void
+prefixify_subexp (inexpr, outexpr, inend, outbeg)
+     register struct expression *inexpr;
+     struct expression *outexpr;
+     register int inend;
+     int outbeg;
+{
+  register int oplen = 1;
+  register int args = 0;
+  register int i;
+  int *arglens;
+  enum exp_opcode opcode;
+
+  /* Compute how long the last operation is (in OPLEN),
+     and also how many preceding subexpressions serve as
+     arguments for it (in ARGS).  */
+
+  opcode = inexpr->elts[inend - 1].opcode;
+  switch (opcode)
+    {
+      /* C++  */
+    case OP_SCOPE:
+      oplen = 4 + ((inexpr->elts[inend - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+      break;
+
+    case OP_LONG:
+    case OP_DOUBLE:
+      oplen = 4;
+      break;
+
+    case OP_VAR_VALUE:
+    case OP_LAST:
+    case OP_REGISTER:
+    case OP_INTERNALVAR:
+      oplen = 3;
+      break;
+
+    case OP_FUNCALL:
+      oplen = 3;
+      args = 1 + inexpr->elts[inend - 2].longconst;
+      break;
+
+    case UNOP_CAST:
+    case UNOP_MEMVAL:
+      oplen = 3;
+      args = 1;
+      break;
+
+    case STRUCTOP_STRUCT:
+    case STRUCTOP_PTR:
+      args = 1;
+    case OP_STRING:
+      oplen = 3 + ((inexpr->elts[inend - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+                  
+      break;
+
+    case TERNOP_COND:
+      args = 3;
+      break;
+
+    case BINOP_ASSIGN_MODIFY:
+      oplen = 3;
+      args = 2;
+      break;
+
+      /* C++ */
+    case OP_THIS:
+      oplen = 2;
+      break;
+
+    default:
+      args = 1 + ((int) opcode < (int) BINOP_END);
+    }
+
+  /* Copy the final operator itself, from the end of the input
+     to the beginning of the output.  */
+  inend -= oplen;
+  bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg],
+        oplen * sizeof (union exp_element));
+  outbeg += oplen;
+
+  /* Find the lengths of the arg subexpressions.  */
+  arglens = (int *) alloca (args * sizeof (int));
+  for (i = args - 1; i >= 0; i--)
+    {
+      oplen = length_of_subexp (inexpr, inend);
+      arglens[i] = oplen;
+      inend -= oplen;
+    }
+
+  /* Now copy each subexpression, preserving the order of
+     the subexpressions, but prefixifying each one.
+     In this loop, inend starts at the beginning of
+     the expression this level is working on
+     and marches forward over the arguments.
+     outbeg does similarly in the output.  */
+  for (i = 0; i < args; i++)
+    {
+      oplen = arglens[i];
+      inend += oplen;
+      prefixify_subexp (inexpr, outexpr, inend, outbeg);
+      outbeg += oplen;
+    }
+}
+\f
+/* This page contains the two entry points to this file.  */
+
+/* Read a C expression from the string *STRINGPTR points to,
+   parse it, and return a pointer to a  struct expression  that we malloc.
+   Use block BLOCK as the lexical context for variable names;
+   if BLOCK is zero, use the block of the selected stack frame.
+   Meanwhile, advance *STRINGPTR to point after the expression,
+   at the first nonwhite character that is not part of the expression
+   (possibly a null character).
+
+   If COMMA is nonzero, stop if a comma is reached.  */
+
+struct expression *
+parse_c_1 (stringptr, block, comma)
+     char **stringptr;
+     struct block *block;
+     int comma;
+{
+  struct cleanup *old_chain;
+
+  lexptr = *stringptr;
+
+  paren_depth = 0;
+  type_stack_depth = 0;
+
+  comma_terminates = comma;
+
+  if (lexptr == 0 || *lexptr == 0)
+    error_no_arg ("expression to compute");
+
+  old_chain = make_cleanup (free_funcalls, 0);
+  funcall_chain = 0;
+
+  expression_context_block = block ? block : get_selected_block ();
+
+  namecopy = (char *) alloca (strlen (lexptr) + 1);
+  expout_size = 10;
+  expout_ptr = 0;
+  expout = (struct expression *)
+    xmalloc (sizeof (struct expression)
+            + expout_size * sizeof (union exp_element));
+  make_cleanup (free_current_contents, &expout);
+  if (yyparse ())
+    yyerror (NULL);
+  discard_cleanups (old_chain);
+  expout->nelts = expout_ptr;
+  expout = (struct expression *)
+    xrealloc (expout,
+             sizeof (struct expression)
+             + expout_ptr * sizeof (union exp_element));
+  prefixify_expression (expout);
+  *stringptr = lexptr;
+  return expout;
+}
+
+/* Parse STRING as an expression, and complain if this fails
+   to use up all of the contents of STRING.  */
+
+struct expression *
+parse_c_expression (string)
+     char *string;
+{
+  register struct expression *exp;
+  exp = parse_c_1 (&string, 0, 0);
+  if (*string)
+    error ("Junk after end of expression.");
+  return exp;
+}
+
+static void 
+push_type (tp)
+     enum type_pieces tp;
+{
+  if (type_stack_depth == type_stack_size)
+    {
+      type_stack_size *= 2;
+      type_stack = (enum type_pieces *)
+       xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces));
+    }
+  type_stack[type_stack_depth++] = tp;
+}
+
+static enum type_pieces 
+pop_type ()
+{
+  if (type_stack_depth)
+    return type_stack[--type_stack_depth];
+  return tp_end;
+}
+
+void
+_initialize_expread ()
+{
+  type_stack_size = 80;
+  type_stack_depth = 0;
+  type_stack = (enum type_pieces *)
+    xmalloc (type_stack_size * sizeof (enum type_pieces));
+}
diff --git a/gdb/expread.y b/gdb/expread.y
new file mode 100755 (executable)
index 0000000..3b19750
--- /dev/null
@@ -0,0 +1,1902 @@
+/* Parse C expressions for GDB.
+   Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+/* Parse a C expression from text in a string,
+   and return the result as a  struct expression  pointer.
+   That structure contains arithmetic operations in reverse polish,
+   with constants represented by operations that are followed by special data.
+   See expression.h for the details of the format.
+   What is important here is that it can be built up sequentially
+   during the process of parsing; the lower levels of the tree always
+   come first in the result.  */
+   
+%{
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "expression.h"
+#include "value.h"
+#include "command.h"
+
+static struct expression *expout;
+static int expout_size;
+static int expout_ptr;
+
+static int yylex ();
+static void yyerror ();
+static void write_exp_elt ();
+static void write_exp_elt_opcode ();
+static void write_exp_elt_sym ();
+static void write_exp_elt_longcst ();
+static void write_exp_elt_dblcst ();
+static void write_exp_elt_type ();
+static void write_exp_elt_intern ();
+static void write_exp_string ();
+static void start_arglist ();
+static int end_arglist ();
+static void free_funcalls ();
+static char *copy_name ();
+static int parse_number ();
+
+/* If this is nonzero, this block is used as the lexical context
+   for symbol names.  */
+
+static struct block *expression_context_block;
+
+/* The innermost context required by the stack and register variables
+   we've encountered so far. */
+struct block *innermost_block;
+
+/* The block in which the most recently discovered symbol was found. */
+struct block *block_found;
+
+/* Number of arguments seen so far in innermost function call.  */
+static int arglist_len;
+
+/* Data structure for saving values of arglist_len
+   for function calls whose arguments contain other function calls.  */
+
+struct funcall
+  {
+    struct funcall *next;
+    int arglist_len;
+  };
+
+struct funcall *funcall_chain;
+
+/* This kind of datum is used to represent the name
+   of a symbol token.  */
+
+struct stoken
+  {
+    char *ptr;
+    int length;
+  };
+
+struct ttype
+  {
+    struct stoken stoken;
+    struct type *type;
+  };
+
+struct symtoken
+  {
+    struct stoken stoken;
+    struct symbol *sym;
+    int is_a_field_of_this;
+  };
+
+/* For parsing of complicated types.
+   An array should be preceded in the list by the size of the array.  */
+enum type_pieces
+  {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function};
+static enum type_pieces *type_stack;
+static int type_stack_depth, type_stack_size;
+
+static void push_type ();
+static enum type_pieces pop_type ();
+
+/* Allow debugging of parsing.  */
+#define YYDEBUG 1
+%}
+
+/* Although the yacc "value" of an expression is not used,
+   since the result is stored in the structure being created,
+   other node types do have values.  */
+
+%union
+  {
+    LONGEST lval;
+    unsigned LONGEST ulval;
+    double dval;
+    struct symbol *sym;
+    struct type *tval;
+    struct stoken sval;
+    struct ttype tsym;
+    struct symtoken ssym;
+    int voidval;
+    struct block *bval;
+    enum exp_opcode opcode;
+    struct internalvar *ivar;
+
+    struct type **tvec;
+    int *ivec;
+  }
+
+%type <voidval> exp exp1 start variable
+%type <tval> type typebase
+%type <tvec> nonempty_typelist
+%type <bval> block
+
+/* Fancy type parsing.  */
+%type <voidval> func_mod direct_abs_decl abs_decl
+%type <tval> ptype
+%type <lval> array_mod
+
+%token <lval> INT CHAR
+%token <ulval> UINT
+%token <dval> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+   and both convey their data as strings.
+   But a TYPENAME is a string that happens to be defined as a typedef
+   or builtin type name (such as int or char)
+   and a NAME is any other symbol.
+
+   Contexts where this distinction is not important can use the
+   nonterminal "name", which matches either NAME or TYPENAME.  */
+
+%token <sval> STRING
+%token <ssym> NAME BLOCKNAME
+%token <tsym> TYPENAME
+%type <sval> name
+%type <ssym> name_not_typename
+%type <tsym> typename
+
+/* A NAME_OR_INT is a symbol which is not known in the symbol table,
+   but which would parse as a valid number in the current input radix.
+   E.g. "c" when input_radix==16.  Depending on the parse, it will be
+   turned into a name or into a number.  NAME_OR_UINT ditto.  */
+
+%token <ssym> NAME_OR_INT NAME_OR_UINT
+
+%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+   legal basetypes.  */
+%token SIGNED LONG SHORT INT_KEYWORD
+
+%token <lval> LAST REGNAME
+
+%token <ivar> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+/* C++ */
+%token THIS
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY INCREMENT DECREMENT
+%right ARROW '.' '[' '('
+%left COLONCOLON
+\f
+%%
+
+start   :      exp1
+       ;
+
+/* Expressions, including the comma operator.  */
+exp1   :       exp
+       |       exp1 ',' exp
+                       { write_exp_elt_opcode (BINOP_COMMA); }
+       ;
+
+/* Expressions, not including the comma operator.  */
+exp    :       '*' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_IND); }
+
+exp    :       '&' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_ADDR); }
+
+exp    :       '-' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_NEG); }
+       ;
+
+exp    :       '!' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_ZEROP); }
+       ;
+
+exp    :       '~' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_LOGNOT); }
+       ;
+
+exp    :       INCREMENT exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_PREINCREMENT); }
+       ;
+
+exp    :       DECREMENT exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_PREDECREMENT); }
+       ;
+
+exp    :       exp INCREMENT    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
+       ;
+
+exp    :       exp DECREMENT    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
+       ;
+
+exp    :       SIZEOF exp       %prec UNARY
+                       { write_exp_elt_opcode (UNOP_SIZEOF); }
+       ;
+
+exp    :       exp ARROW name
+                       { write_exp_elt_opcode (STRUCTOP_PTR);
+                         write_exp_string ($3);
+                         write_exp_elt_opcode (STRUCTOP_PTR); }
+       ;
+
+exp    :       exp ARROW '*' exp
+                       { write_exp_elt_opcode (STRUCTOP_MPTR); }
+       ;
+
+exp    :       exp '.' name
+                       { write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_exp_string ($3);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); }
+       ;
+
+exp    :       exp '.' '*' exp
+                       { write_exp_elt_opcode (STRUCTOP_MEMBER); }
+       ;
+
+exp    :       exp '[' exp1 ']'
+                       { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+       ;
+
+exp    :       exp '(' 
+                       /* This is to save the value of arglist_len
+                          being accumulated by an outer function call.  */
+                       { start_arglist (); }
+               arglist ')'     %prec ARROW
+                       { write_exp_elt_opcode (OP_FUNCALL);
+                         write_exp_elt_longcst ((LONGEST) end_arglist ());
+                         write_exp_elt_opcode (OP_FUNCALL); }
+       ;
+
+arglist        :
+       ;
+
+arglist        :       exp
+                       { arglist_len = 1; }
+       ;
+
+arglist        :       arglist ',' exp   %prec ABOVE_COMMA
+                       { arglist_len++; }
+       ;
+
+exp    :       '{' type '}' exp  %prec UNARY
+                       { write_exp_elt_opcode (UNOP_MEMVAL);
+                         write_exp_elt_type ($2);
+                         write_exp_elt_opcode (UNOP_MEMVAL); }
+       ;
+
+exp    :       '(' type ')' exp  %prec UNARY
+                       { write_exp_elt_opcode (UNOP_CAST);
+                         write_exp_elt_type ($2);
+                         write_exp_elt_opcode (UNOP_CAST); }
+       ;
+
+exp    :       '(' exp1 ')'
+                       { }
+       ;
+
+/* Binary operators in order of decreasing precedence.  */
+
+exp    :       exp '@' exp
+                       { write_exp_elt_opcode (BINOP_REPEAT); }
+       ;
+
+exp    :       exp '*' exp
+                       { write_exp_elt_opcode (BINOP_MUL); }
+       ;
+
+exp    :       exp '/' exp
+                       { write_exp_elt_opcode (BINOP_DIV); }
+       ;
+
+exp    :       exp '%' exp
+                       { write_exp_elt_opcode (BINOP_REM); }
+       ;
+
+exp    :       exp '+' exp
+                       { write_exp_elt_opcode (BINOP_ADD); }
+       ;
+
+exp    :       exp '-' exp
+                       { write_exp_elt_opcode (BINOP_SUB); }
+       ;
+
+exp    :       exp LSH exp
+                       { write_exp_elt_opcode (BINOP_LSH); }
+       ;
+
+exp    :       exp RSH exp
+                       { write_exp_elt_opcode (BINOP_RSH); }
+       ;
+
+exp    :       exp EQUAL exp
+                       { write_exp_elt_opcode (BINOP_EQUAL); }
+       ;
+
+exp    :       exp NOTEQUAL exp
+                       { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+       ;
+
+exp    :       exp LEQ exp
+                       { write_exp_elt_opcode (BINOP_LEQ); }
+       ;
+
+exp    :       exp GEQ exp
+                       { write_exp_elt_opcode (BINOP_GEQ); }
+       ;
+
+exp    :       exp '<' exp
+                       { write_exp_elt_opcode (BINOP_LESS); }
+       ;
+
+exp    :       exp '>' exp
+                       { write_exp_elt_opcode (BINOP_GTR); }
+       ;
+
+exp    :       exp '&' exp
+                       { write_exp_elt_opcode (BINOP_LOGAND); }
+       ;
+
+exp    :       exp '^' exp
+                       { write_exp_elt_opcode (BINOP_LOGXOR); }
+       ;
+
+exp    :       exp '|' exp
+                       { write_exp_elt_opcode (BINOP_LOGIOR); }
+       ;
+
+exp    :       exp AND exp
+                       { write_exp_elt_opcode (BINOP_AND); }
+       ;
+
+exp    :       exp OR exp
+                       { write_exp_elt_opcode (BINOP_OR); }
+       ;
+
+exp    :       exp '?' exp ':' exp     %prec '?'
+                       { write_exp_elt_opcode (TERNOP_COND); }
+       ;
+                         
+exp    :       exp '=' exp
+                       { write_exp_elt_opcode (BINOP_ASSIGN); }
+       ;
+
+exp    :       exp ASSIGN_MODIFY exp
+                       { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+                         write_exp_elt_opcode ($2);
+                         write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+       ;
+
+exp    :       INT
+                       { write_exp_elt_opcode (OP_LONG);
+                         if ($1 == (int) $1 || $1 == (unsigned int) $1)
+                           write_exp_elt_type (builtin_type_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+                         write_exp_elt_longcst ((LONGEST) $1);
+                         write_exp_elt_opcode (OP_LONG); }
+       ;
+
+exp    :       NAME_OR_INT
+                       { YYSTYPE val;
+                         parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
+                         write_exp_elt_opcode (OP_LONG);
+                         if (val.lval == (int) val.lval ||
+                             val.lval == (unsigned int) val.lval)
+                           write_exp_elt_type (builtin_type_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+                         write_exp_elt_longcst (val.lval);
+                         write_exp_elt_opcode (OP_LONG); }
+       ;
+
+exp    :       UINT
+                       {
+                         write_exp_elt_opcode (OP_LONG);
+                         if ($1 == (unsigned int) $1)
+                           write_exp_elt_type (builtin_type_unsigned_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+                         write_exp_elt_longcst ((LONGEST) $1);
+                         write_exp_elt_opcode (OP_LONG);
+                       }
+       ;
+
+exp    :       NAME_OR_UINT
+                       { YYSTYPE val;
+                         parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
+                         write_exp_elt_opcode (OP_LONG);
+                         if (val.ulval == (unsigned int) val.ulval)
+                           write_exp_elt_type (builtin_type_unsigned_int);
+                         else
+                           write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+                         write_exp_elt_longcst ((LONGEST)val.ulval);
+                         write_exp_elt_opcode (OP_LONG);
+                       }
+       ;
+
+exp    :       CHAR
+                       { write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (builtin_type_char);
+                         write_exp_elt_longcst ((LONGEST) $1);
+                         write_exp_elt_opcode (OP_LONG); }
+       ;
+
+exp    :       FLOAT
+                       { write_exp_elt_opcode (OP_DOUBLE);
+                         write_exp_elt_type (builtin_type_double);
+                         write_exp_elt_dblcst ($1);
+                         write_exp_elt_opcode (OP_DOUBLE); }
+       ;
+
+exp    :       variable
+       ;
+
+exp    :       LAST
+                       { write_exp_elt_opcode (OP_LAST);
+                         write_exp_elt_longcst ((LONGEST) $1);
+                         write_exp_elt_opcode (OP_LAST); }
+       ;
+
+exp    :       REGNAME
+                       { write_exp_elt_opcode (OP_REGISTER);
+                         write_exp_elt_longcst ((LONGEST) $1);
+                         write_exp_elt_opcode (OP_REGISTER); }
+       ;
+
+exp    :       VARIABLE
+                       { write_exp_elt_opcode (OP_INTERNALVAR);
+                         write_exp_elt_intern ($1);
+                         write_exp_elt_opcode (OP_INTERNALVAR); }
+       ;
+
+exp    :       SIZEOF '(' type ')'     %prec UNARY
+                       { write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (builtin_type_int);
+                         write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+                         write_exp_elt_opcode (OP_LONG); }
+       ;
+
+exp    :       STRING
+                       { write_exp_elt_opcode (OP_STRING);
+                         write_exp_string ($1);
+                         write_exp_elt_opcode (OP_STRING); }
+       ;
+
+/* C++.  */
+exp    :       THIS
+                       { write_exp_elt_opcode (OP_THIS);
+                         write_exp_elt_opcode (OP_THIS); }
+       ;
+
+/* end of C++.  */
+
+block  :       BLOCKNAME
+                       {
+                         if ($1.sym != 0)
+                             $$ = SYMBOL_BLOCK_VALUE ($1.sym);
+                         else
+                           {
+                             struct symtab *tem =
+                                 lookup_symtab (copy_name ($1.stoken));
+                             if (tem)
+                               $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1);
+                             else
+                               error ("No file or function \"%s\".",
+                                      copy_name ($1.stoken));
+                           }
+                       }
+       ;
+
+block  :       block COLONCOLON name
+                       { struct symbol *tem
+                           = lookup_symbol (copy_name ($3), $1,
+                                            VAR_NAMESPACE, 0, NULL);
+                         if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+                           error ("No function \"%s\" in specified context.",
+                                  copy_name ($3));
+                         $$ = SYMBOL_BLOCK_VALUE (tem); }
+       ;
+
+variable:      block COLONCOLON name
+                       { struct symbol *sym;
+                         sym = lookup_symbol (copy_name ($3), $1,
+                                              VAR_NAMESPACE, 0, NULL);
+                         if (sym == 0)
+                           error ("No symbol \"%s\" in specified context.",
+                                  copy_name ($3));
+                         write_exp_elt_opcode (OP_VAR_VALUE);
+                         write_exp_elt_sym (sym);
+                         write_exp_elt_opcode (OP_VAR_VALUE); }
+       ;
+
+variable:      typebase COLONCOLON name
+                       {
+                         struct type *type = $1;
+                         if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+                             && TYPE_CODE (type) != TYPE_CODE_UNION)
+                           error ("`%s' is not defined as an aggregate type.",
+                                  TYPE_NAME (type));
+
+                         write_exp_elt_opcode (OP_SCOPE);
+                         write_exp_elt_type (type);
+                         write_exp_string ($3);
+                         write_exp_elt_opcode (OP_SCOPE);
+                       }
+       |       COLONCOLON name
+                       {
+                         char *name = copy_name ($2);
+                         struct symbol *sym;
+                         int i;
+
+                         sym =
+                           lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+                         if (sym)
+                           {
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                             write_exp_elt_sym (sym);
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                             break;
+                           }
+                         for (i = 0; i < misc_function_count; i++)
+                           if (!strcmp (misc_function_vector[i].name, name))
+                             break;
+
+                         if (i < misc_function_count)
+                           {
+                             enum misc_function_type mft =
+                                 misc_function_vector[i].type;
+                             
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_type (builtin_type_int);
+                             write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_opcode (UNOP_MEMVAL);
+                             if (mft == mf_data || mft == mf_bss)
+                               write_exp_elt_type (builtin_type_int);
+                             else if (mft == mf_text)
+                               write_exp_elt_type (lookup_function_type (builtin_type_int));
+                             else
+                               write_exp_elt_type (builtin_type_char);
+                             write_exp_elt_opcode (UNOP_MEMVAL);
+                           }
+                         else
+                           if (symtab_list == 0
+                               && partial_symtab_list == 0)
+                             error ("No symbol table is loaded.  Use the \"file\" command.");
+                           else
+                             error ("No symbol \"%s\" in current context.", name);
+                       }
+       ;
+
+variable:      name_not_typename
+                       { struct symbol *sym = $1.sym;
+
+                         if (sym)
+                           {
+                             switch (sym->class)
+                               {
+                               case LOC_REGISTER:
+                               case LOC_ARG:
+                               case LOC_LOCAL:
+                               case LOC_LOCAL_ARG:
+                                 if (innermost_block == 0 ||
+                                     contained_in (block_found, 
+                                                   innermost_block))
+                                   innermost_block = block_found;
+                               }
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                             write_exp_elt_sym (sym);
+                             write_exp_elt_opcode (OP_VAR_VALUE);
+                           }
+                         else if ($1.is_a_field_of_this)
+                           {
+                             /* C++: it hangs off of `this'.  Must
+                                not inadvertently convert from a method call
+                                to data ref.  */
+                             if (innermost_block == 0 || 
+                                 contained_in (block_found, innermost_block))
+                               innermost_block = block_found;
+                             write_exp_elt_opcode (OP_THIS);
+                             write_exp_elt_opcode (OP_THIS);
+                             write_exp_elt_opcode (STRUCTOP_PTR);
+                             write_exp_string ($1.stoken);
+                             write_exp_elt_opcode (STRUCTOP_PTR);
+                           }
+                         else
+                           {
+                             register int i;
+                             register char *arg = copy_name ($1.stoken);
+
+                               /* FIXME, this search is linear!  At least
+                                  optimize the strcmp with a 1-char cmp... */
+                             for (i = 0; i < misc_function_count; i++)
+                               if (!strcmp (misc_function_vector[i].name, arg))
+                                 break;
+
+                             if (i < misc_function_count)
+                               {
+                                 enum misc_function_type mft =
+                                     misc_function_vector[i].type;
+                                 
+                                 write_exp_elt_opcode (OP_LONG);
+                                 write_exp_elt_type (builtin_type_int);
+                                 write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+                                 write_exp_elt_opcode (OP_LONG);
+                                 write_exp_elt_opcode (UNOP_MEMVAL);
+                                 if (mft == mf_data || mft == mf_bss)
+                                   write_exp_elt_type (builtin_type_int);
+                                 else if (mft == mf_text)
+                                   write_exp_elt_type (lookup_function_type (builtin_type_int));
+                                 else
+                                   write_exp_elt_type (builtin_type_char);
+                                 write_exp_elt_opcode (UNOP_MEMVAL);
+                               }
+                             else if (symtab_list == 0
+                                      && partial_symtab_list == 0)
+                               error ("No symbol table is loaded.  Use the \"file\" command.");
+                             else
+                               error ("No symbol \"%s\" in current context.",
+                                      copy_name ($1.stoken));
+                           }
+                       }
+       ;
+
+
+ptype  :       typebase
+       |       typebase abs_decl
+               {
+                 /* This is where the interesting stuff happens.  */
+                 int done = 0;
+                 int array_size;
+                 struct type *follow_type = $1;
+                 
+                 while (!done)
+                   switch (pop_type ())
+                     {
+                     case tp_end:
+                       done = 1;
+                       break;
+                     case tp_pointer:
+                       follow_type = lookup_pointer_type (follow_type);
+                       break;
+                     case tp_reference:
+                       follow_type = lookup_reference_type (follow_type);
+                       break;
+                     case tp_array:
+                       array_size = (int) pop_type ();
+                       if (array_size != -1)
+                         follow_type = create_array_type (follow_type,
+                                                          array_size);
+                       else
+                         follow_type = lookup_pointer_type (follow_type);
+                       break;
+                     case tp_function:
+                       follow_type = lookup_function_type (follow_type);
+                       break;
+                     }
+                 $$ = follow_type;
+               }
+       ;
+
+abs_decl:      '*'
+                       { push_type (tp_pointer); $$ = 0; }
+       |       '*' abs_decl
+                       { push_type (tp_pointer); $$ = $2; }
+       |       direct_abs_decl
+       ;
+
+direct_abs_decl: '(' abs_decl ')'
+                       { $$ = $2; }
+       |       direct_abs_decl array_mod
+                       {
+                         push_type ((enum type_pieces) $2);
+                         push_type (tp_array);
+                       }
+       |       array_mod
+                       {
+                         push_type ((enum type_pieces) $1);
+                         push_type (tp_array);
+                         $$ = 0;
+                       }
+       |       direct_abs_decl func_mod
+                       { push_type (tp_function); }
+       |       func_mod
+                       { push_type (tp_function); }
+       ;
+
+array_mod:     '[' ']'
+                       { $$ = -1; }
+       |       '[' INT ']'
+                       { $$ = $2; }
+       ;
+
+func_mod:      '(' ')'
+                       { $$ = 0; }
+       ;
+
+type   :       ptype
+       |       typebase COLONCOLON '*'
+                       { $$ = lookup_member_type (builtin_type_int, $1); }
+       |       type '(' typebase COLONCOLON '*' ')'
+                       { $$ = lookup_member_type ($1, $3); }
+       |       type '(' typebase COLONCOLON '*' ')' '(' ')'
+                       { $$ = lookup_member_type
+                           (lookup_function_type ($1), $3); }
+       |       type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
+                       { $$ = lookup_member_type
+                           (lookup_function_type ($1), $3);
+                         free ($8); }
+       ;
+
+typebase
+       :       TYPENAME
+                       { $$ = $1.type; }
+       |       INT_KEYWORD
+                       { $$ = builtin_type_int; }
+       |       LONG
+                       { $$ = builtin_type_long; }
+       |       SHORT
+                       { $$ = builtin_type_short; }
+       |       LONG INT_KEYWORD
+                       { $$ = builtin_type_long; }
+       |       UNSIGNED LONG INT_KEYWORD
+                       { $$ = builtin_type_unsigned_long; }
+       |       SHORT INT_KEYWORD
+                       { $$ = builtin_type_short; }
+       |       UNSIGNED SHORT INT_KEYWORD
+                       { $$ = builtin_type_unsigned_short; }
+       |       STRUCT name
+                       { $$ = lookup_struct (copy_name ($2),
+                                             expression_context_block); }
+       |       UNION name
+                       { $$ = lookup_union (copy_name ($2),
+                                            expression_context_block); }
+       |       ENUM name
+                       { $$ = lookup_enum (copy_name ($2),
+                                           expression_context_block); }
+       |       UNSIGNED typename
+                       { $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
+       |       UNSIGNED
+                       { $$ = builtin_type_unsigned_int; }
+       |       SIGNED typename
+                       { $$ = $2.type; }
+       |       SIGNED
+                       { $$ = builtin_type_int; }
+       ;
+
+typename:      TYPENAME
+       |       INT_KEYWORD
+               {
+                 $$.stoken.ptr = "int";
+                 $$.stoken.length = 3;
+                 $$.type = builtin_type_int;
+               }
+       |       LONG
+               {
+                 $$.stoken.ptr = "long";
+                 $$.stoken.length = 4;
+                 $$.type = builtin_type_long;
+               }
+       |       SHORT
+               {
+                 $$.stoken.ptr = "short";
+                 $$.stoken.length = 5;
+                 $$.type = builtin_type_short;
+               }
+       ;
+
+nonempty_typelist
+       :       type
+               { $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
+                 $$[0] = (struct type *)0;
+                 $$[1] = $1;
+               }
+       |       nonempty_typelist ',' type
+               { int len = sizeof (struct type *) * ++($<ivec>1[0]);
+                 $$ = (struct type **)xrealloc ($1, len);
+                 $$[$<ivec>$[0]] = $3;
+               }
+       ;
+
+name   :       NAME { $$ = $1.stoken; }
+       |       BLOCKNAME { $$ = $1.stoken; }
+       |       TYPENAME { $$ = $1.stoken; }
+       |       NAME_OR_INT  { $$ = $1.stoken; }
+       |       NAME_OR_UINT  { $$ = $1.stoken; }
+       ;
+
+name_not_typename :    NAME
+       |       BLOCKNAME
+       |       NAME_OR_INT
+       |       NAME_OR_UINT
+       ;
+
+%%
+\f
+/* Begin counting arguments for a function call,
+   saving the data about any containing call.  */
+
+static void
+start_arglist ()
+{
+  register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+
+  new->next = funcall_chain;
+  new->arglist_len = arglist_len;
+  arglist_len = 0;
+  funcall_chain = new;
+}
+
+/* Return the number of arguments in a function call just terminated,
+   and restore the data for the containing function call.  */
+
+static int
+end_arglist ()
+{
+  register int val = arglist_len;
+  register struct funcall *call = funcall_chain;
+  funcall_chain = call->next;
+  arglist_len = call->arglist_len;
+  free (call);
+  return val;
+}
+
+/* Free everything in the funcall chain.
+   Used when there is an error inside parsing.  */
+
+static void
+free_funcalls ()
+{
+  register struct funcall *call, *next;
+
+  for (call = funcall_chain; call; call = next)
+    {
+      next = call->next;
+      free (call);
+    }
+}
+\f
+/* This page contains the functions for adding data to the  struct expression
+   being constructed.  */
+
+/* Add one element to the end of the expression.  */
+
+/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
+   a register through here */
+
+static void
+write_exp_elt (expelt)
+     union exp_element expelt;
+{
+  if (expout_ptr >= expout_size)
+    {
+      expout_size *= 2;
+      expout = (struct expression *) xrealloc (expout,
+                                              sizeof (struct expression)
+                                              + expout_size * sizeof (union exp_element));
+    }
+  expout->elts[expout_ptr++] = expelt;
+}
+
+static void
+write_exp_elt_opcode (expelt)
+     enum exp_opcode expelt;
+{
+  union exp_element tmp;
+
+  tmp.opcode = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_sym (expelt)
+     struct symbol *expelt;
+{
+  union exp_element tmp;
+
+  tmp.symbol = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_longcst (expelt)
+     LONGEST expelt;
+{
+  union exp_element tmp;
+
+  tmp.longconst = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_dblcst (expelt)
+     double expelt;
+{
+  union exp_element tmp;
+
+  tmp.doubleconst = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_type (expelt)
+     struct type *expelt;
+{
+  union exp_element tmp;
+
+  tmp.type = expelt;
+
+  write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_intern (expelt)
+     struct internalvar *expelt;
+{
+  union exp_element tmp;
+
+  tmp.internalvar = expelt;
+
+  write_exp_elt (tmp);
+}
+
+/* Add a string constant to the end of the expression.
+   Follow it by its length in bytes, as a separate exp_element.  */
+
+static void
+write_exp_string (str)
+     struct stoken str;
+{
+  register int len = str.length;
+  register int lenelt
+    = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+
+  expout_ptr += lenelt;
+
+  if (expout_ptr >= expout_size)
+    {
+      expout_size = max (expout_size * 2, expout_ptr + 10);
+      expout = (struct expression *)
+       xrealloc (expout, (sizeof (struct expression)
+                          + (expout_size * sizeof (union exp_element))));
+    }
+  bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
+  ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+  write_exp_elt_longcst ((LONGEST) len);
+}
+\f
+/* During parsing of a C expression, the pointer to the next character
+   is in this variable.  */
+
+static char *lexptr;
+
+/* Tokens that refer to names do so with explicit pointer and length,
+   so they can share the storage that lexptr is parsing.
+
+   When it is necessary to pass a name to a function that expects
+   a null-terminated string, the substring is copied out
+   into a block of storage that namecopy points to.
+
+   namecopy is allocated once, guaranteed big enough, for each parsing.  */
+
+static char *namecopy;
+
+/* Current depth in parentheses within the expression.  */
+
+static int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses).  */
+
+static int comma_terminates;
+
+/* Take care of parsing a number (anything that starts with a digit).
+   Set yylval and return the token type; update lexptr.
+   LEN is the number of characters in it.  */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+     register char *p;
+     register int len;
+     int parsed_float;
+     YYSTYPE *putithere;
+{
+  register LONGEST n = 0;
+  register int i;
+  register int c;
+  register int base = input_radix;
+  int unsigned_p = 0;
+
+  extern double atof ();
+
+  if (parsed_float)
+    {
+      /* It's a float since it contains a point or an exponent.  */
+      putithere->dval = atof (p);
+      return FLOAT;
+    }
+
+  /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+  if (p[0] == '0')
+    switch (p[1])
+      {
+      case 'x':
+      case 'X':
+       if (len >= 3)
+         {
+           p += 2;
+           base = 16;
+           len -= 2;
+         }
+       break;
+
+      case 't':
+      case 'T':
+      case 'd':
+      case 'D':
+       if (len >= 3)
+         {
+           p += 2;
+           base = 10;
+           len -= 2;
+         }
+       break;
+
+      default:
+       base = 8;
+       break;
+      }
+
+  while (len-- > 0)
+    {
+      c = *p++;
+      if (c >= 'A' && c <= 'Z')
+       c += 'a' - 'A';
+      if (c != 'l' && c != 'u')
+       n *= base;
+      if (c >= '0' && c <= '9')
+       n += i = c - '0';
+      else
+       {
+         if (base > 10 && c >= 'a' && c <= 'f')
+           n += i = c - 'a' + 10;
+         else if (len == 0 && c == 'l')
+           ;
+         else if (len == 0 && c == 'u')
+           unsigned_p = 1;
+         else
+           return ERROR;       /* Char not a digit */
+       }
+      if (i >= base)
+       return ERROR;           /* Invalid digit in this base */
+    }
+
+  if (unsigned_p)
+    {
+      putithere->ulval = n;
+      return UINT;
+    }
+  else
+    {
+      putithere->lval = n;
+      return INT;
+    }
+}
+
+struct token
+{
+  char *operator;
+  int token;
+  enum exp_opcode opcode;
+};
+
+static struct token tokentab3[] =
+  {
+    {">>=", ASSIGN_MODIFY, BINOP_RSH},
+    {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+  };
+
+static struct token tokentab2[] =
+  {
+    {"+=", ASSIGN_MODIFY, BINOP_ADD},
+    {"-=", ASSIGN_MODIFY, BINOP_SUB},
+    {"*=", ASSIGN_MODIFY, BINOP_MUL},
+    {"/=", ASSIGN_MODIFY, BINOP_DIV},
+    {"%=", ASSIGN_MODIFY, BINOP_REM},
+    {"|=", ASSIGN_MODIFY, BINOP_LOGIOR},
+    {"&=", ASSIGN_MODIFY, BINOP_LOGAND},
+    {"^=", ASSIGN_MODIFY, BINOP_LOGXOR},
+    {"++", INCREMENT, BINOP_END},
+    {"--", DECREMENT, BINOP_END},
+    {"->", ARROW, BINOP_END},
+    {"&&", AND, BINOP_END},
+    {"||", OR, BINOP_END},
+    {"::", COLONCOLON, BINOP_END},
+    {"<<", LSH, BINOP_END},
+    {">>", RSH, BINOP_END},
+    {"==", EQUAL, BINOP_END},
+    {"!=", NOTEQUAL, BINOP_END},
+    {"<=", LEQ, BINOP_END},
+    {">=", GEQ, BINOP_END}
+  };
+
+/* assign machine-independent names to certain registers 
+ * (unless overridden by the REGISTER_NAMES table)
+ */
+struct std_regs {
+       char *name;
+       int regnum;
+} std_regs[] = {
+#ifdef PC_REGNUM
+       { "pc", PC_REGNUM },
+#endif
+#ifdef FP_REGNUM
+       { "fp", FP_REGNUM },
+#endif
+#ifdef SP_REGNUM
+       { "sp", SP_REGNUM },
+#endif
+#ifdef PS_REGNUM
+       { "ps", PS_REGNUM },
+#endif
+};
+
+#define NUM_STD_REGS (sizeof std_regs / sizeof std_regs[0])
+
+/* Read one token, getting characters through lexptr.  */
+
+static int
+yylex ()
+{
+  register int c;
+  register int namelen;
+  register unsigned i;
+  register char *tokstart;
+
+ retry:
+
+  tokstart = lexptr;
+  /* See if it is a special token of length 3.  */
+  for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+    if (!strncmp (tokstart, tokentab3[i].operator, 3))
+      {
+       lexptr += 3;
+       yylval.opcode = tokentab3[i].opcode;
+       return tokentab3[i].token;
+      }
+
+  /* See if it is a special token of length 2.  */
+  for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+    if (!strncmp (tokstart, tokentab2[i].operator, 2))
+      {
+       lexptr += 2;
+       yylval.opcode = tokentab2[i].opcode;
+       return tokentab2[i].token;
+      }
+
+  switch (c = *tokstart)
+    {
+    case 0:
+      return 0;
+
+    case ' ':
+    case '\t':
+    case '\n':
+      lexptr++;
+      goto retry;
+
+    case '\'':
+      lexptr++;
+      c = *lexptr++;
+      if (c == '\\')
+       c = parse_escape (&lexptr);
+      yylval.lval = c;
+      c = *lexptr++;
+      if (c != '\'')
+       error ("Invalid character constant.");
+      return CHAR;
+
+    case '(':
+      paren_depth++;
+      lexptr++;
+      return c;
+
+    case ')':
+      if (paren_depth == 0)
+       return 0;
+      paren_depth--;
+      lexptr++;
+      return c;
+
+    case ',':
+      if (comma_terminates && paren_depth == 0)
+       return 0;
+      lexptr++;
+      return c;
+
+    case '.':
+      /* Might be a floating point number.  */
+      if (lexptr[1] < '0' || lexptr[1] > '9')
+       goto symbol;            /* Nope, must be a symbol. */
+      /* FALL THRU into number case.  */
+
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      {
+       /* It's a number.  */
+       int got_dot = 0, got_e = 0, toktype;
+       register char *p = tokstart;
+       int hex = input_radix > 10;
+
+       if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+         {
+           p += 2;
+           hex = 1;
+         }
+       else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+         {
+           p += 2;
+           hex = 0;
+         }
+
+       for (;; ++p)
+         {
+           if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+             got_dot = got_e = 1;
+           else if (!hex && !got_dot && *p == '.')
+             got_dot = 1;
+           else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+                    && (*p == '-' || *p == '+'))
+             /* This is the sign of the exponent, not the end of the
+                number.  */
+             continue;
+           /* We will take any letters or digits.  parse_number will
+              complain if past the radix, or if L or U are not final.  */
+           else if ((*p < '0' || *p > '9')
+                    && ((*p < 'a' || *p > 'z')
+                                 && (*p < 'A' || *p > 'Z')))
+             break;
+         }
+       toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
+        if (toktype == ERROR)
+         {
+           char *err_copy = (char *) alloca (p - tokstart + 1);
+
+           bcopy (tokstart, err_copy, p - tokstart);
+           err_copy[p - tokstart] = 0;
+           error ("Invalid number \"%s\".", err_copy);
+         }
+       lexptr = p;
+       return toktype;
+      }
+
+    case '+':
+    case '-':
+    case '*':
+    case '/':
+    case '%':
+    case '|':
+    case '&':
+    case '^':
+    case '~':
+    case '!':
+    case '@':
+    case '<':
+    case '>':
+    case '[':
+    case ']':
+    case '?':
+    case ':':
+    case '=':
+    case '{':
+    case '}':
+    symbol:
+      lexptr++;
+      return c;
+
+    case '"':
+      for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++)
+       if (c == '\\')
+         {
+           c = tokstart[++namelen];
+           if (c >= '0' && c <= '9')
+             {
+               c = tokstart[++namelen];
+               if (c >= '0' && c <= '9')
+                 c = tokstart[++namelen];
+             }
+         }
+      yylval.sval.ptr = tokstart + 1;
+      yylval.sval.length = namelen - 1;
+      lexptr += namelen + 1;
+      return STRING;
+    }
+
+  if (!(c == '_' || c == '$'
+       || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+    /* We must have come across a bad character (e.g. ';').  */
+    error ("Invalid character '%c' in expression.", c);
+
+  /* It's a name.  See how long it is.  */
+  namelen = 0;
+  for (c = tokstart[namelen];
+       (c == '_' || c == '$' || (c >= '0' && c <= '9')
+       || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+       c = tokstart[++namelen])
+    ;
+
+  /* The token "if" terminates the expression and is NOT 
+     removed from the input stream.  */
+  if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+    {
+      return 0;
+    }
+
+  lexptr += namelen;
+
+  /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+     and $$digits (equivalent to $<-digits> if you could type that).
+     Make token type LAST, and put the number (the digits) in yylval.  */
+
+  if (*tokstart == '$')
+    {
+      register int negate = 0;
+      c = 1;
+      /* Double dollar means negate the number and add -1 as well.
+        Thus $$ alone means -1.  */
+      if (namelen >= 2 && tokstart[1] == '$')
+       {
+         negate = 1;
+         c = 2;
+       }
+      if (c == namelen)
+       {
+         /* Just dollars (one or two) */
+         yylval.lval = - negate;
+         return LAST;
+       }
+      /* Is the rest of the token digits?  */
+      for (; c < namelen; c++)
+       if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
+         break;
+      if (c == namelen)
+       {
+         yylval.lval = atoi (tokstart + 1 + negate);
+         if (negate)
+           yylval.lval = - yylval.lval;
+         return LAST;
+       }
+    }
+
+  /* Handle tokens that refer to machine registers:
+     $ followed by a register name.  */
+
+  if (*tokstart == '$') {
+    for (c = 0; c < NUM_REGS; c++)
+      if (namelen - 1 == strlen (reg_names[c])
+         && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+       {
+         yylval.lval = c;
+         return REGNAME;
+       }
+    for (c = 0; c < NUM_STD_REGS; c++)
+     if (namelen - 1 == strlen (std_regs[c].name)
+        && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+       {
+        yylval.lval = std_regs[c].regnum;
+        return REGNAME;
+       }
+  }
+  /* Catch specific keywords.  Should be done with a data structure.  */
+  switch (namelen)
+    {
+    case 8:
+      if (!strncmp (tokstart, "unsigned", 8))
+       return UNSIGNED;
+      break;
+    case 6:
+      if (!strncmp (tokstart, "struct", 6))
+       return STRUCT;
+      if (!strncmp (tokstart, "signed", 6))
+       return SIGNED;
+      if (!strncmp (tokstart, "sizeof", 6))      
+       return SIZEOF;
+      break;
+    case 5:
+      if (!strncmp (tokstart, "union", 5))
+       return UNION;
+      if (!strncmp (tokstart, "short", 5))
+       return SHORT;
+      break;
+    case 4:
+      if (!strncmp (tokstart, "enum", 4))
+       return ENUM;
+      if (!strncmp (tokstart, "long", 4))
+       return LONG;
+      if (!strncmp (tokstart, "this", 4))
+       {
+         static const char this_name[] =
+                                { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
+
+         if (lookup_symbol (this_name, expression_context_block,
+                            VAR_NAMESPACE, 0, NULL))
+           return THIS;
+       }
+      break;
+    case 3:
+      if (!strncmp (tokstart, "int", 3))
+       return INT_KEYWORD;
+      break;
+    default:
+      break;
+    }
+
+  yylval.sval.ptr = tokstart;
+  yylval.sval.length = namelen;
+
+  /* Any other names starting in $ are debugger internal variables.  */
+
+  if (*tokstart == '$')
+    {
+      yylval.ivar =  lookup_internalvar (copy_name (yylval.sval) + 1);
+      return VARIABLE;
+    }
+
+  /* Use token-type BLOCKNAME for symbols that happen to be defined as
+     functions or symtabs.  If this is not so, then ...
+     Use token-type TYPENAME for symbols that happen to be defined
+     currently as names of types; NAME for other symbols.
+     The caller is not constrained to care about the distinction.  */
+  {
+    char *tmp = copy_name (yylval.sval);
+    struct symbol *sym;
+    int is_a_field_of_this = 0;
+    int hextype;
+
+    sym = lookup_symbol (tmp, expression_context_block,
+                        VAR_NAMESPACE, &is_a_field_of_this, NULL);
+    if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
+        lookup_partial_symtab (tmp))
+      {
+       yylval.ssym.sym = sym;
+       yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+       return BLOCKNAME;
+      }
+    if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+        {
+         yylval.tsym.type = SYMBOL_TYPE (sym);
+         return TYPENAME;
+        }
+    if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+       return TYPENAME;
+
+    /* Input names that aren't symbols but ARE valid hex numbers,
+       when the input radix permits them, can be names or numbers
+       depending on the parse.  Note we support radixes > 16 here.  */
+    if (!sym && 
+        ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
+         (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+      {
+       YYSTYPE newlval;        /* Its value is ignored.  */
+       hextype = parse_number (tokstart, namelen, 0, &newlval);
+       if (hextype == INT)
+         {
+           yylval.ssym.sym = sym;
+           yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+           return NAME_OR_INT;
+         }
+       if (hextype == UINT)
+         {
+           yylval.ssym.sym = sym;
+           yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+           return NAME_OR_UINT;
+         }
+      }
+
+    /* Any other kind of symbol */
+    yylval.ssym.sym = sym;
+    yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+    return NAME;
+  }
+}
+
+static void
+yyerror (msg)
+     char *msg;
+{
+  error ("Invalid syntax in expression.");
+}
+
+/* Return a null-terminated temporary copy of the name
+   of a string token.  */
+
+static char *
+copy_name (token)
+     struct stoken token;
+{
+  bcopy (token.ptr, namecopy, token.length);
+  namecopy[token.length] = 0;
+  return namecopy;
+}
+\f
+/* Reverse an expression from suffix form (in which it is constructed)
+   to prefix form (in which we can conveniently print or execute it).  */
+
+static void prefixify_subexp ();
+
+static void
+prefixify_expression (expr)
+     register struct expression *expr;
+{
+  register int len = sizeof (struct expression) +
+                                   expr->nelts * sizeof (union exp_element);
+  register struct expression *temp;
+  register int inpos = expr->nelts, outpos = 0;
+
+  temp = (struct expression *) alloca (len);
+
+  /* Copy the original expression into temp.  */
+  bcopy (expr, temp, len);
+
+  prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the subexpression of EXPR
+   whose last exp_element is at index ENDPOS - 1 in EXPR.  */
+
+static int
+length_of_subexp (expr, endpos)
+     register struct expression *expr;
+     register int endpos;
+{
+  register int oplen = 1;
+  register int args = 0;
+  register int i;
+
+  if (endpos < 0)
+    error ("?error in length_of_subexp");
+
+  i = (int) expr->elts[endpos - 1].opcode;
+
+  switch (i)
+    {
+      /* C++  */
+    case OP_SCOPE:
+      oplen = 4 + ((expr->elts[endpos - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+      break;
+
+    case OP_LONG:
+    case OP_DOUBLE:
+      oplen = 4;
+      break;
+
+    case OP_VAR_VALUE:
+    case OP_LAST:
+    case OP_REGISTER:
+    case OP_INTERNALVAR:
+      oplen = 3;
+      break;
+
+    case OP_FUNCALL:
+      oplen = 3;
+      args = 1 + expr->elts[endpos - 2].longconst;
+      break;
+
+    case UNOP_CAST:
+    case UNOP_MEMVAL:
+      oplen = 3;
+      args = 1;
+      break;
+
+    case STRUCTOP_STRUCT:
+    case STRUCTOP_PTR:
+      args = 1;
+    case OP_STRING:
+      oplen = 3 + ((expr->elts[endpos - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+      break;
+
+    case TERNOP_COND:
+      args = 3;
+      break;
+
+    case BINOP_ASSIGN_MODIFY:
+      oplen = 3;
+      args = 2;
+      break;
+
+      /* C++ */
+    case OP_THIS:
+      oplen = 2;
+      break;
+
+    default:
+      args = 1 + (i < (int) BINOP_END);
+    }
+
+  while (args > 0)
+    {
+      oplen += length_of_subexp (expr, endpos - oplen);
+      args--;
+    }
+
+  return oplen;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+   into OUTEXPR, starting at index OUTBEG.
+   In the process, convert it from suffix to prefix form.  */
+
+static void
+prefixify_subexp (inexpr, outexpr, inend, outbeg)
+     register struct expression *inexpr;
+     struct expression *outexpr;
+     register int inend;
+     int outbeg;
+{
+  register int oplen = 1;
+  register int args = 0;
+  register int i;
+  int *arglens;
+  enum exp_opcode opcode;
+
+  /* Compute how long the last operation is (in OPLEN),
+     and also how many preceding subexpressions serve as
+     arguments for it (in ARGS).  */
+
+  opcode = inexpr->elts[inend - 1].opcode;
+  switch (opcode)
+    {
+      /* C++  */
+    case OP_SCOPE:
+      oplen = 4 + ((inexpr->elts[inend - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+      break;
+
+    case OP_LONG:
+    case OP_DOUBLE:
+      oplen = 4;
+      break;
+
+    case OP_VAR_VALUE:
+    case OP_LAST:
+    case OP_REGISTER:
+    case OP_INTERNALVAR:
+      oplen = 3;
+      break;
+
+    case OP_FUNCALL:
+      oplen = 3;
+      args = 1 + inexpr->elts[inend - 2].longconst;
+      break;
+
+    case UNOP_CAST:
+    case UNOP_MEMVAL:
+      oplen = 3;
+      args = 1;
+      break;
+
+    case STRUCTOP_STRUCT:
+    case STRUCTOP_PTR:
+      args = 1;
+    case OP_STRING:
+      oplen = 3 + ((inexpr->elts[inend - 2].longconst
+                   + sizeof (union exp_element))
+                  / sizeof (union exp_element));
+                  
+      break;
+
+    case TERNOP_COND:
+      args = 3;
+      break;
+
+    case BINOP_ASSIGN_MODIFY:
+      oplen = 3;
+      args = 2;
+      break;
+
+      /* C++ */
+    case OP_THIS:
+      oplen = 2;
+      break;
+
+    default:
+      args = 1 + ((int) opcode < (int) BINOP_END);
+    }
+
+  /* Copy the final operator itself, from the end of the input
+     to the beginning of the output.  */
+  inend -= oplen;
+  bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg],
+        oplen * sizeof (union exp_element));
+  outbeg += oplen;
+
+  /* Find the lengths of the arg subexpressions.  */
+  arglens = (int *) alloca (args * sizeof (int));
+  for (i = args - 1; i >= 0; i--)
+    {
+      oplen = length_of_subexp (inexpr, inend);
+      arglens[i] = oplen;
+      inend -= oplen;
+    }
+
+  /* Now copy each subexpression, preserving the order of
+     the subexpressions, but prefixifying each one.
+     In this loop, inend starts at the beginning of
+     the expression this level is working on
+     and marches forward over the arguments.
+     outbeg does similarly in the output.  */
+  for (i = 0; i < args; i++)
+    {
+      oplen = arglens[i];
+      inend += oplen;
+      prefixify_subexp (inexpr, outexpr, inend, outbeg);
+      outbeg += oplen;
+    }
+}
+\f
+/* This page contains the two entry points to this file.  */
+
+/* Read a C expression from the string *STRINGPTR points to,
+   parse it, and return a pointer to a  struct expression  that we malloc.
+   Use block BLOCK as the lexical context for variable names;
+   if BLOCK is zero, use the block of the selected stack frame.
+   Meanwhile, advance *STRINGPTR to point after the expression,
+   at the first nonwhite character that is not part of the expression
+   (possibly a null character).
+
+   If COMMA is nonzero, stop if a comma is reached.  */
+
+struct expression *
+parse_c_1 (stringptr, block, comma)
+     char **stringptr;
+     struct block *block;
+     int comma;
+{
+  struct cleanup *old_chain;
+
+  lexptr = *stringptr;
+
+  paren_depth = 0;
+  type_stack_depth = 0;
+
+  comma_terminates = comma;
+
+  if (lexptr == 0 || *lexptr == 0)
+    error_no_arg ("expression to compute");
+
+  old_chain = make_cleanup (free_funcalls, 0);
+  funcall_chain = 0;
+
+  expression_context_block = block ? block : get_selected_block ();
+
+  namecopy = (char *) alloca (strlen (lexptr) + 1);
+  expout_size = 10;
+  expout_ptr = 0;
+  expout = (struct expression *)
+    xmalloc (sizeof (struct expression)
+            + expout_size * sizeof (union exp_element));
+  make_cleanup (free_current_contents, &expout);
+  if (yyparse ())
+    yyerror (NULL);
+  discard_cleanups (old_chain);
+  expout->nelts = expout_ptr;
+  expout = (struct expression *)
+    xrealloc (expout,
+             sizeof (struct expression)
+             + expout_ptr * sizeof (union exp_element));
+  prefixify_expression (expout);
+  *stringptr = lexptr;
+  return expout;
+}
+
+/* Parse STRING as an expression, and complain if this fails
+   to use up all of the contents of STRING.  */
+
+struct expression *
+parse_c_expression (string)
+     char *string;
+{
+  register struct expression *exp;
+  exp = parse_c_1 (&string, 0, 0);
+  if (*string)
+    error ("Junk after end of expression.");
+  return exp;
+}
+
+static void 
+push_type (tp)
+     enum type_pieces tp;
+{
+  if (type_stack_depth == type_stack_size)
+    {
+      type_stack_size *= 2;
+      type_stack = (enum type_pieces *)
+       xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces));
+    }
+  type_stack[type_stack_depth++] = tp;
+}
+
+static enum type_pieces 
+pop_type ()
+{
+  if (type_stack_depth)
+    return type_stack[--type_stack_depth];
+  return tp_end;
+}
+
+void
+_initialize_expread ()
+{
+  type_stack_size = 80;
+  type_stack_depth = 0;
+  type_stack = (enum type_pieces *)
+    xmalloc (type_stack_size * sizeof (enum type_pieces));
+}
diff --git a/gdb/expression.h b/gdb/expression.h
new file mode 100644 (file)
index 0000000..b7a6fff
--- /dev/null
@@ -0,0 +1,200 @@
+/* Definitions for expressions stored in reversed prefix form, for GDB.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Definitions for saved C expressions.  */
+
+/* An expression is represented as a vector of union exp_element's.
+   Each exp_element is an opcode, except that some opcodes cause
+   the following exp_element to be treated as a long or double constant
+   or as a variable.  The opcodes are obeyed, using a stack for temporaries.
+   The value is left on the temporary stack at the end.  */
+
+/* When it is necessary to include a string,
+   it can occupy as many exp_elements as it needs.
+   We find the length of the string using strlen,
+   divide to find out how many exp_elements are used up,
+   and skip that many.  Strings, like numbers, are indicated
+   by the preceding opcode.  */
+
+enum exp_opcode
+{
+/* BINOP_... operate on two values computed by following subexpressions,
+   replacing them by one result value.  They take no immediate arguments.  */
+  BINOP_ADD,           /* + */
+  BINOP_SUB,           /* - */
+  BINOP_MUL,           /* * */
+  BINOP_DIV,           /* / */
+  BINOP_REM,           /* % */
+  BINOP_LSH,           /* << */
+  BINOP_RSH,           /* >> */
+  BINOP_AND,           /* && */
+  BINOP_OR,            /* || */
+  BINOP_LOGAND,                /* & */
+  BINOP_LOGIOR,                /* | */
+  BINOP_LOGXOR,                /* ^ */
+  BINOP_EQUAL,         /* == */
+  BINOP_NOTEQUAL,      /* != */
+  BINOP_LESS,          /* < */
+  BINOP_GTR,           /* > */
+  BINOP_LEQ,           /* <= */
+  BINOP_GEQ,           /* >= */
+  BINOP_REPEAT,                /* @ */
+  BINOP_ASSIGN,                /* = */
+  BINOP_COMMA,         /* , */
+  BINOP_SUBSCRIPT,     /* x[y] */
+  BINOP_EXP,           /* Exponentiation */
+
+/* C++.  */
+  BINOP_MIN,           /* <? */
+  BINOP_MAX,           /* >? */
+  BINOP_SCOPE,         /* :: */
+
+  /* STRUCTOP_MEMBER is used for pointer-to-member constructs.
+     X . * Y translates into X STRUCTOP_MEMBER Y.  */
+  STRUCTOP_MEMBER,
+  /* STRUCTOP_MPTR is used for pointer-to-member constructs
+     when X is a pointer instead of an aggregate.  */
+  STRUCTOP_MPTR,
+/* end of C++.  */
+
+  BINOP_END,
+
+  BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
+                          The following exp_element is another opcode,
+                          a BINOP_, saying how to modify.
+                          Then comes another BINOP_ASSIGN_MODIFY,
+                          making three exp_elements in total.  */
+
+/* Operates on three values computed by following subexpressions.  */
+  TERNOP_COND,         /* ?: */
+
+/* The OP_... series take immediate following arguments.
+   After the arguments come another OP_... (the same one)
+   so that the grouping can be recognized from the end.  */
+
+/* OP_LONG is followed by a type pointer in the next exp_element
+   and the long constant value in the following exp_element.
+   Then comes another OP_LONG.
+   Thus, the operation occupies four exp_elements.  */
+
+  OP_LONG,
+/* OP_DOUBLE is similar but takes a double constant instead of a long one.  */
+  OP_DOUBLE,
+/* OP_VAR_VALUE takes one struct symbol * in the following exp_element,
+   followed by another OP_VAR_VALUE, making three exp_elements.  */
+  OP_VAR_VALUE,
+/* OP_LAST is followed by an integer in the next exp_element.
+   The integer is zero for the last value printed,
+   or it is the absolute number of a history element.
+   With another OP_LAST at the end, this makes three exp_elements.  */
+  OP_LAST,
+/* OP_REGISTER is followed by an integer in the next exp_element.
+   This is the number of a register to fetch (as an int).
+   With another OP_REGISTER at the end, this makes three exp_elements.  */
+  OP_REGISTER,
+/* OP_INTERNALVAR is followed by an internalvar ptr in the next exp_element.
+   With another OP_INTERNALVAR at the end, this makes three exp_elements.  */
+  OP_INTERNALVAR,
+/* OP_FUNCALL is followed by an integer in the next exp_element.
+   The integer is the number of args to the function call.
+   That many plus one values from following subexpressions
+   are used, the first one being the function.
+   The integer is followed by a repeat of OP_FUNCALL,
+   making three exp_elements.  */
+  OP_FUNCALL,
+/* OP_STRING represents a string constant.
+   Its format is the same as that of a STRUCTOP, but the string
+   data is just made into a string constant when the operation
+   is executed.  */
+  OP_STRING,
+
+/* UNOP_CAST is followed by a type pointer in the next exp_element.
+   With another UNOP_CAST at the end, this makes three exp_elements.
+   It casts the value of the following subexpression.  */
+  UNOP_CAST,
+/* UNOP_MEMVAL is followed by a type pointer in the next exp_element
+   With another UNOP_MEMVAL at the end, this makes three exp_elements.
+   It casts the contents of the word addressed by the value of the
+   following subexpression.  */
+  UNOP_MEMVAL,
+/* UNOP_... operate on one value from a following subexpression
+   and replace it with a result.  They take no immediate arguments.  */
+  UNOP_NEG,            /* Unary - */
+  UNOP_ZEROP,          /* Unary ! */
+  UNOP_LOGNOT,         /* Unary ~ */
+  UNOP_IND,            /* Unary * */
+  UNOP_ADDR,           /* Unary & */
+  UNOP_PREINCREMENT,   /* ++ before an expression */
+  UNOP_POSTINCREMENT,  /* ++ after an expression */
+  UNOP_PREDECREMENT,   /* -- before an expression */
+  UNOP_POSTDECREMENT,  /* -- after an expression */
+  UNOP_SIZEOF,         /* Unary sizeof (followed by expression) */
+
+/* STRUCTOP_... operate on a value from a following subexpression
+   by extracting a structure component specified by a string
+   that appears in the following exp_elements (as many as needed).
+   STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->".
+   They differ only in the error message given in case the value is
+   not suitable or the structure component specified is not found.
+
+   The length of the string follows in the next exp_element,
+   (after the string), followed by another STRUCTOP_... code.  */
+  STRUCTOP_STRUCT,
+  STRUCTOP_PTR,
+
+/* C++ */
+  /* OP_THIS is just a placeholder for the class instance variable.
+     It just comes in a tight (OP_THIS, OP_THIS) pair.  */
+  OP_THIS,
+
+  /* OP_SCOPE surrounds a type name and a field name.  The type
+     name is encoded as one element, but the field name stays as
+     a string, which, of course, is variable length.  */
+  OP_SCOPE,
+
+};
+
+union exp_element
+{
+  enum exp_opcode opcode;
+  struct symbol *symbol;
+  LONGEST longconst;
+  double doubleconst;
+  char string;
+  struct type *type;
+  struct internalvar *internalvar;
+};
+
+struct expression
+{
+  int nelts;
+  union exp_element elts[1];
+};
+
+/* From expread.y.  */
+struct expression *parse_c_expression ();
+struct expression *parse_c_1 ();
+
+/* The innermost context required by the stack and register variables
+   we've encountered so far.  To use this, set it to NULL, then call
+   parse_c_<whatever>, then look at it.  */
+extern struct block *innermost_block;
+
+/* From expprint.c.  */
+void print_expression ();
diff --git a/gdb/findvar.c b/gdb/findvar.c
new file mode 100644 (file)
index 0000000..c674a54
--- /dev/null
@@ -0,0 +1,684 @@
+/* Find a variable's value in memory, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "inferior.h"
+#include "target.h"
+
+#if !defined (GET_SAVED_REGISTER)
+
+/* Return the address in which frame FRAME's value of register REGNUM
+   has been saved in memory.  Or return zero if it has not been saved.
+   If REGNUM specifies the SP, the value we return is actually
+   the SP value, not an address where it was saved.  */
+
+CORE_ADDR
+find_saved_register (frame, regnum)
+     FRAME frame;
+     int regnum;
+{
+  struct frame_info *fi;
+  struct frame_saved_regs saved_regs;
+
+  register FRAME frame1 = 0;
+  register CORE_ADDR addr = 0;
+
+  if (frame == 0)              /* No regs saved if want current frame */
+    return 0;
+
+#ifdef HAVE_REGISTER_WINDOWS
+  /* We assume that a register in a register window will only be saved
+     in one place (since the name changes and/or disappears as you go
+     towards inner frames), so we only call get_frame_saved_regs on
+     the current frame.  This is directly in contradiction to the
+     usage below, which assumes that registers used in a frame must be
+     saved in a lower (more interior) frame.  This change is a result
+     of working on a register window machine; get_frame_saved_regs
+     always returns the registers saved within a frame, within the
+     context (register namespace) of that frame. */
+
+  /* However, note that we don't want this to return anything if
+     nothing is saved (if there's a frame inside of this one).  Also,
+     callers to this routine asking for the stack pointer want the
+     stack pointer saved for *this* frame; this is returned from the
+     next frame.  */
+     
+
+  if (REGISTER_IN_WINDOW_P(regnum))
+    {
+      frame1 = get_next_frame (frame);
+      if (!frame1) return 0;   /* Registers of this frame are
+                                  active.  */
+      
+      /* Get the SP from the next frame in; it will be this
+        current frame.  */
+      if (regnum != SP_REGNUM)
+       frame1 = frame; 
+         
+      fi = get_frame_info (frame1);
+      get_frame_saved_regs (fi, &saved_regs);
+      return saved_regs.regs[regnum];  /* ... which might be zero */
+    }
+#endif /* HAVE_REGISTER_WINDOWS */
+
+  /* Note that this next routine assumes that registers used in
+     frame x will be saved only in the frame that x calls and
+     frames interior to it.  This is not true on the sparc, but the
+     above macro takes care of it, so we should be all right. */
+  while (1)
+    {
+      QUIT;
+      frame1 = get_prev_frame (frame1);
+      if (frame1 == 0 || frame1 == frame)
+       break;
+      fi = get_frame_info (frame1);
+      get_frame_saved_regs (fi, &saved_regs);
+      if (saved_regs.regs[regnum])
+       addr = saved_regs.regs[regnum];
+    }
+
+  return addr;
+}
+
+/* Find register number REGNUM relative to FRAME and put its
+   (raw) contents in *RAW_BUFFER.  Set *OPTIMIZED if the variable
+   was optimized out (and thus can't be fetched).  Set *LVAL to
+   lval_memory, lval_register, or not_lval, depending on whether the
+   value was fetched from memory, from a register, or in a strange
+   and non-modifiable way (e.g. a frame pointer which was calculated
+   rather than fetched).  Set *ADDRP to the address, either in memory
+   on as a REGISTER_BYTE offset into the registers array.
+
+   Note that this implementation never sets *LVAL to not_lval.  But
+   it can be replaced by defining GET_SAVED_REGISTER and supplying
+   your own.
+
+   The argument RAW_BUFFER must point to aligned memory.  */
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+     char *raw_buffer;
+     int *optimized;
+     CORE_ADDR *addrp;
+     FRAME frame;
+     int regnum;
+     enum lval_type *lval;
+{
+  CORE_ADDR addr;
+  /* Normal systems don't optimize out things with register numbers.  */
+  if (optimized != NULL)
+    *optimized = 0;
+  addr = find_saved_register (frame, regnum);
+  if (addr != NULL)
+    {
+      if (lval != NULL)
+       *lval = lval_memory;
+      if (regnum == SP_REGNUM)
+       {
+         if (raw_buffer != NULL)
+           *(CORE_ADDR *)raw_buffer = addr;
+         if (addrp != NULL)
+           *addrp = 0;
+         return;
+       }
+      if (raw_buffer != NULL)
+       read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
+    }
+  else
+    {
+      if (lval != NULL)
+       *lval = lval_register;
+      addr = REGISTER_BYTE (regnum);
+      if (raw_buffer != NULL)
+       read_register_gen (regnum, raw_buffer);
+    }
+  if (addrp != NULL)
+    *addrp = addr;
+}
+#endif /* GET_SAVED_REGISTER.  */
+
+/* Copy the bytes of register REGNUM, relative to the current stack frame,
+   into our memory at MYADDR, in target byte order.
+   The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
+
+   Returns 1 if could not be read, 0 if could.  */
+
+int
+read_relative_register_raw_bytes (regnum, myaddr)
+     int regnum;
+     char *myaddr;
+{
+  int optim;
+  if (regnum == FP_REGNUM && selected_frame)
+    {
+      bcopy (&FRAME_FP(selected_frame), myaddr, sizeof (CORE_ADDR));
+      SWAP_TARGET_AND_HOST (myaddr, sizeof (CORE_ADDR)); /* in target order */
+      return 0;
+    }
+
+  get_saved_register (myaddr, &optim, (CORE_ADDR) NULL, selected_frame,
+                      regnum, (enum lval_type *)NULL);
+  return optim;
+}
+
+/* Return a `value' with the contents of register REGNUM
+   in its virtual format, with the type specified by
+   REGISTER_VIRTUAL_TYPE.  */
+
+value
+value_of_register (regnum)
+     int regnum;
+{
+  CORE_ADDR addr;
+  int optim;
+  register value val;
+  char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+  enum lval_type lval;
+
+  get_saved_register (raw_buffer, &optim, &addr,
+                     selected_frame, regnum, &lval);
+
+  target_convert_to_virtual (regnum, raw_buffer, virtual_buffer);
+  val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+  bcopy (virtual_buffer, VALUE_CONTENTS_RAW (val),
+        REGISTER_VIRTUAL_SIZE (regnum));
+  VALUE_LVAL (val) = lval;
+  VALUE_ADDRESS (val) = addr;
+  VALUE_REGNO (val) = regnum;
+  VALUE_OPTIMIZED_OUT (val) = optim;
+  return val;
+}
+\f
+/* Low level examining and depositing of registers.
+
+   The caller is responsible for making
+   sure that the inferior is stopped before calling the fetching routines,
+   or it will get garbage.  (a change from GDB version 3, in which
+   the caller got the value from the last stop).  */
+
+/* Contents of the registers in target byte order.
+   We allocate some extra slop since we do a lot of bcopy's around `registers',
+   and failing-soft is better than failing hard.  */
+char registers[REGISTER_BYTES + /* SLOP */ 256];
+
+/* Nonzero if that register has been fetched.  */
+char register_valid[NUM_REGS];
+
+/* Indicate that registers may have changed, so invalidate the cache.  */
+void
+registers_changed ()
+{
+  int i;
+  for (i = 0; i < NUM_REGS; i++)
+    register_valid[i] = 0;
+}
+
+/* Indicate that all registers have been fetched, so mark them all valid.  */
+void
+registers_fetched ()
+{
+  int i;
+  for (i = 0; i < NUM_REGS; i++)
+    register_valid[i] = 1;
+}
+
+/* Copy LEN bytes of consecutive data from registers
+   starting with the REGBYTE'th byte of register data
+   into memory at MYADDR.  */
+
+void
+read_register_bytes (regbyte, myaddr, len)
+     int regbyte;
+     char *myaddr;
+     int len;
+{
+  /* Fetch all registers.  */
+  int i;
+  for (i = 0; i < NUM_REGS; i++)
+    if (!register_valid[i])
+      {
+       target_fetch_registers (-1);
+       break;
+      }
+  if (myaddr != NULL)
+    bcopy (&registers[regbyte], myaddr, len);
+}
+
+/* Read register REGNO into memory at MYADDR, which must be large enough
+   for REGISTER_RAW_BYTES (REGNO).  If the register is known to be the
+   size of a CORE_ADDR or smaller, read_register can be used instead.  */
+void
+read_register_gen (regno, myaddr)
+     int regno;
+     char *myaddr;
+{
+  if (!register_valid[regno])
+    target_fetch_registers (regno);
+  bcopy (&registers[REGISTER_BYTE (regno)], myaddr, REGISTER_RAW_SIZE (regno));
+}
+
+/* Copy LEN bytes of consecutive data from memory at MYADDR
+   into registers starting with the REGBYTE'th byte of register data.  */
+
+void
+write_register_bytes (regbyte, myaddr, len)
+     int regbyte;
+     char *myaddr;
+     int len;
+{
+  /* Make sure the entire registers array is valid.  */
+  read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
+  bcopy (myaddr, &registers[regbyte], len);
+  target_store_registers (-1);
+}
+
+/* Return the contents of register REGNO, regarding it as an integer.  */
+
+CORE_ADDR
+read_register (regno)
+     int regno;
+{
+  int reg;
+  if (!register_valid[regno])
+    target_fetch_registers (regno);
+  /* FIXME, this loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  reg = *(int *) &registers[REGISTER_BYTE (regno)];
+  SWAP_TARGET_AND_HOST (&reg, sizeof (int));
+  return reg;
+}
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store VALUE in the register number REGNO, regarded as an integer.  */
+
+void
+write_register (regno, val)
+     int regno, val;
+{
+  /* On the sparc, writing %g0 is a no-op, so we don't even want to change
+     the registers array if something writes to this register.  */
+  if (CANNOT_STORE_REGISTER (regno))
+    return;
+
+  SWAP_TARGET_AND_HOST (&val, sizeof (int));
+
+  target_prepare_to_store ();
+
+  register_valid [regno] = 1;
+  /* FIXME, this loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  /* FIXME, this depends on REGISTER_BYTE (regno) being aligned for host */
+  *(int *) &registers[REGISTER_BYTE (regno)] = val;
+
+  target_store_registers (regno);
+}
+
+/* Record that register REGNO contains VAL.
+   This is used when the value is obtained from the inferior or core dump,
+   so there is no need to store the value there.  */
+
+void
+supply_register (regno, val)
+     int regno;
+     char *val;
+{
+  register_valid[regno] = 1;
+  bcopy (val, &registers[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno));
+}
+\f
+/* Given a struct symbol for a variable,
+   and a stack frame id, read the value of the variable
+   and return a (pointer to a) struct value containing the value. 
+   If the variable cannot be found, return a zero pointer.  */
+
+value
+read_var_value (var, frame)
+     register struct symbol *var;
+     FRAME frame;
+{
+  register value v;
+  struct frame_info *fi;
+  struct type *type = SYMBOL_TYPE (var);
+  CORE_ADDR addr;
+  int val;
+  register int len;
+
+  v = allocate_value (type);
+  VALUE_LVAL (v) = lval_memory;        /* The most likely possibility.  */
+  len = TYPE_LENGTH (type);
+
+  if (frame == 0) frame = selected_frame;
+
+  switch (SYMBOL_CLASS (var))
+    {
+    case LOC_CONST:
+      val = SYMBOL_VALUE (var);
+      bcopy (&val, VALUE_CONTENTS_RAW (v), len);
+      SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (v), len);
+      VALUE_LVAL (v) = not_lval;
+      return v;
+
+    case LOC_LABEL:
+      addr = SYMBOL_VALUE_ADDRESS (var);
+      bcopy (&addr, VALUE_CONTENTS_RAW (v), len);
+      SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (v), len);
+      VALUE_LVAL (v) = not_lval;
+      return v;
+
+    case LOC_CONST_BYTES:
+      addr = SYMBOL_VALUE_ADDRESS (var);
+      bcopy (addr, VALUE_CONTENTS_RAW (v), len);
+      VALUE_LVAL (v) = not_lval;
+      return v;
+
+    case LOC_STATIC:
+    case LOC_EXTERNAL:
+      addr = SYMBOL_VALUE_ADDRESS (var);
+      break;
+
+/* Nonzero if a struct which is located in a register or a LOC_ARG
+   really contains
+   the address of the struct, not the struct itself.  GCC_P is nonzero
+   if the function was compiled with GCC.  */
+#if !defined (REG_STRUCT_HAS_ADDR)
+#define REG_STRUCT_HAS_ADDR(gcc_p) 0
+#endif
+
+    case LOC_ARG:
+      fi = get_frame_info (frame);
+      addr = FRAME_ARGS_ADDRESS (fi);
+      if (!addr) {
+       return 0;
+      }
+      addr += SYMBOL_VALUE (var);
+      break;
+      
+    case LOC_REF_ARG:
+      fi = get_frame_info (frame);
+      addr = FRAME_ARGS_ADDRESS (fi);
+      if (!addr) {
+       return 0;
+      }
+      addr += SYMBOL_VALUE (var);
+      addr = read_memory_integer (addr, sizeof (CORE_ADDR));
+      break;
+      
+    case LOC_LOCAL:
+    case LOC_LOCAL_ARG:
+      fi = get_frame_info (frame);
+      addr = SYMBOL_VALUE (var) + FRAME_LOCALS_ADDRESS (fi);
+      break;
+
+    case LOC_TYPEDEF:
+      error ("Cannot look up value of a typedef");
+      break;
+
+    case LOC_BLOCK:
+      VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+      return v;
+
+    case LOC_REGISTER:
+    case LOC_REGPARM:
+      {
+       struct block *b = get_frame_block (frame);
+
+       v = value_from_register (type, SYMBOL_VALUE (var), frame);
+
+       if (REG_STRUCT_HAS_ADDR(b->gcc_compile_flag)
+           && TYPE_CODE (type) == TYPE_CODE_STRUCT)
+         addr = *(CORE_ADDR *)VALUE_CONTENTS (v);
+       else
+         return v;
+      }
+      break;
+
+    default:
+      error ("Cannot look up value of a botched symbol.");
+      break;
+    }
+
+  VALUE_ADDRESS (v) = addr;
+  VALUE_LAZY (v) = 1;
+  return v;
+}
+
+/* Return a value of type TYPE, stored in register REGNUM, in frame
+   FRAME. */
+
+value
+value_from_register (type, regnum, frame)
+     struct type *type;
+     int regnum;
+     FRAME frame;
+{
+  char raw_buffer [MAX_REGISTER_RAW_SIZE];
+  char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+  CORE_ADDR addr;
+  int optim;
+  value v = allocate_value (type);
+  int len = TYPE_LENGTH (type);
+  char *value_bytes = 0;
+  int value_bytes_copied = 0;
+  int num_storage_locs;
+  enum lval_type lval;
+
+  VALUE_REGNO (v) = regnum;
+
+  num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
+                     ((len - 1) / REGISTER_RAW_SIZE (regnum)) + 1 :
+                     1);
+
+  if (num_storage_locs > 1)
+    {
+      /* Value spread across multiple storage locations.  */
+      
+      int local_regnum;
+      int mem_stor = 0, reg_stor = 0;
+      int mem_tracking = 1;
+      CORE_ADDR last_addr = 0;
+      CORE_ADDR first_addr;
+
+      value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE);
+
+      /* Copy all of the data out, whereever it may be.  */
+
+      for (local_regnum = regnum;
+          value_bytes_copied < len;
+          (value_bytes_copied += REGISTER_RAW_SIZE (local_regnum),
+           ++local_regnum))
+       {
+         get_saved_register (value_bytes + value_bytes_copied,
+                             &optim,
+                             &addr,
+                             frame,
+                             local_regnum,
+                             &lval);
+         if (lval == lval_register)
+           reg_stor++;
+         else
+           {
+             mem_stor++;
+
+             if (regnum == local_regnum)
+               first_addr = addr;
+             
+             mem_tracking =
+               (mem_tracking
+                && (regnum == local_regnum
+                    || addr == last_addr));
+           }
+         last_addr = addr;
+       }
+
+      if ((reg_stor && mem_stor)
+         || (mem_stor && !mem_tracking))
+       /* Mixed storage; all of the hassle we just went through was
+          for some good purpose.  */
+       {
+         VALUE_LVAL (v) = lval_reg_frame_relative;
+         VALUE_FRAME (v) = FRAME_FP (frame);
+         VALUE_FRAME_REGNUM (v) = regnum;
+       }
+      else if (mem_stor)
+       {
+         VALUE_LVAL (v) = lval_memory;
+         VALUE_ADDRESS (v) = first_addr;
+       }
+      else if (reg_stor)
+       {
+         VALUE_LVAL (v) = lval_register;
+         VALUE_ADDRESS (v) = first_addr;
+       }
+      else
+       fatal ("value_from_register: Value not stored anywhere!");
+
+      VALUE_OPTIMIZED_OUT (v) = optim;
+
+      /* Any structure stored in more than one register will always be
+        an integral number of registers.  Otherwise, you'd need to do
+        some fiddling with the last register copied here for little
+        endian machines.  */
+
+      /* Copy into the contents section of the value.  */
+      bcopy (value_bytes, VALUE_CONTENTS_RAW (v), len);
+
+      return v;
+    }
+
+  /* Data is completely contained within a single register.  Locate the
+     register's contents in a real register or in core;
+     read the data in raw format.  */
+
+  get_saved_register (raw_buffer, &optim, &addr, frame, regnum, &lval);
+  VALUE_OPTIMIZED_OUT (v) = optim;
+  VALUE_LVAL (v) = lval;
+  VALUE_ADDRESS (v) = addr;
+  
+  /* Convert the raw contents to virtual contents.
+     (Just copy them if the formats are the same.)  */
+  
+  target_convert_to_virtual (regnum, raw_buffer, virtual_buffer);
+  
+  if (REGISTER_CONVERTIBLE (regnum))
+    {
+      /* When the raw and virtual formats differ, the virtual format
+        corresponds to a specific data type.  If we want that type,
+        copy the data into the value.
+        Otherwise, do a type-conversion.  */
+      
+      if (type != REGISTER_VIRTUAL_TYPE (regnum))
+       {
+         /* eg a variable of type `float' in a 68881 register
+            with raw type `extended' and virtual type `double'.
+            Fetch it as a `double' and then convert to `float'.  */
+         v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+         bcopy (virtual_buffer, VALUE_CONTENTS_RAW (v), len);
+         v = value_cast (type, v);
+       }
+      else
+       bcopy (virtual_buffer, VALUE_CONTENTS_RAW (v), len);
+    }
+  else
+    {
+      /* Raw and virtual formats are the same for this register.  */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+      if (len < REGISTER_RAW_SIZE (regnum))
+       {
+         /* Big-endian, and we want less than full size.  */
+         VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
+       }
+#endif
+
+      bcopy (virtual_buffer + VALUE_OFFSET (v),
+            VALUE_CONTENTS_RAW (v), len);
+    }
+  
+  return v;
+}
+\f
+/* Given a struct symbol for a variable,
+   and a stack frame id, 
+   return a (pointer to a) struct value containing the variable's address.  */
+
+value
+locate_var_value (var, frame)
+     register struct symbol *var;
+     FRAME frame;
+{
+  CORE_ADDR addr = 0;
+  struct type *type = SYMBOL_TYPE (var);
+  struct type *result_type;
+  value lazy_value;
+
+  /* Evaluate it first; if the result is a memory address, we're fine.
+     Lazy evaluation pays off here. */
+
+  lazy_value = read_var_value (var, frame);
+  if (lazy_value == 0)
+    error ("Address of \"%s\" is unknown.", SYMBOL_NAME (var));
+
+  if (VALUE_LAZY (lazy_value))
+    {
+      addr = VALUE_ADDRESS (lazy_value);
+
+      /* C++: The "address" of a reference should yield the address
+       * of the object pointed to. So force an extra de-reference. */
+
+      if (TYPE_CODE (type) == TYPE_CODE_REF)
+       {
+         char *buf = alloca (TYPE_LENGTH (type));
+         read_memory (addr, buf, TYPE_LENGTH (type));
+         addr = unpack_long (type, buf);
+         type = TYPE_TARGET_TYPE (type);
+       }
+
+      /* Address of an array is of the type of address of it's elements.  */
+      result_type =
+       lookup_pointer_type (TYPE_CODE (type) == TYPE_CODE_ARRAY ?
+                            TYPE_TARGET_TYPE (type) : type);
+
+      return value_cast (result_type,
+                        value_from_long (builtin_type_long, (LONGEST) addr));
+    }
+
+  /* Not a memory address; check what the problem was.  */
+  switch (VALUE_LVAL (lazy_value)) 
+    {
+    case lval_register:
+    case lval_reg_frame_relative:
+      error ("Address requested for identifier \"%s\" which is in a register.",
+            SYMBOL_NAME (var));
+      break;
+
+    default:
+      error ("Can't take address of \"%s\" which isn't an lvalue.",
+            SYMBOL_NAME (var));
+      break;
+    }
+  return 0;  /* For lint -- never reached */
+}
diff --git a/gdb/frame.h b/gdb/frame.h
new file mode 100644 (file)
index 0000000..5c98c9c
--- /dev/null
@@ -0,0 +1,128 @@
+/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (FRAME_H)
+#define FRAME_H 1
+#include "param.h"
+
+/*
+ * FRAME is the type of the identifier of a specific stack frame.  It
+ * is a pointer to the frame cache item corresponding to this frame.
+ * Please note that frame id's are *not* constant over calls to the
+ * inferior.  Use frame addresses, which are.
+ *
+ * FRAME_ADDR is the type of the address of a specific frame.  I
+ * cannot imagine a case in which this would not be CORE_ADDR, so
+ * maybe it's silly to give it it's own type.  Life's rough.
+ *
+ * FRAME_FP is a macro which converts from a frame identifier into a
+ * frame_address.
+ *
+ * FRAME_INFO_ID is a macro which "converts" from a frame info pointer
+ * to a frame id.  This is here in case I or someone else decides to
+ * change the FRAME type again.
+ *
+ * This file and blockframe.c are the only places which are allowed to
+ * use the equivalence between FRAME and struct frame_info *.  EXCEPTION:
+ * value.h uses CORE_ADDR instead of FRAME_ADDR because the compiler
+ * will accept that in the absense of this file.
+ */
+typedef struct frame_info *FRAME;
+typedef CORE_ADDR      FRAME_ADDR;
+#define FRAME_FP(fr)   ((fr)->frame)
+#define FRAME_INFO_ID(f)       (f)
+
+/*
+ * Caching structure for stack frames.  This is also the structure
+ * used for extended info about stack frames.  May add more to this
+ * structure as it becomes necessary.
+ *
+ * Note that the first entry in the cache will always refer to the
+ * innermost executing frame.  This value should be set (is it?
+ * Check) in something like normal_stop.
+ */
+struct frame_info
+  {
+    /* Nominal address of the frame described.  */
+    FRAME_ADDR frame;
+    /* Address at which execution is occurring in this frame.
+       For the innermost frame, it's the current pc.
+       For other frames, it is a pc saved in the next frame.  */
+    CORE_ADDR pc;
+    /* The frame called by the frame we are describing, or 0.
+       This may be set even if there isn't a frame called by the one
+       we are describing (.->next == 0); in that case it is simply the
+       bottom of this frame */
+    FRAME_ADDR next_frame;
+    /* Anything extra for this structure that may have been defined
+       in the machine depedent files. */
+#ifdef EXTRA_FRAME_INFO
+    EXTRA_FRAME_INFO
+#endif
+    /* Pointers to the next and previous frame_info's in this stack.  */
+    FRAME next, prev;
+  };
+
+/* Describe the saved registers of a frame.  */
+
+struct frame_saved_regs
+  {
+    /* For each register, address of where it was saved on entry to the frame,
+       or zero if it was not saved on entry to this frame.  */
+    CORE_ADDR regs[NUM_REGS];
+  };
+
+/* The stack frame that the user has specified for commands to act on.
+   Note that one cannot assume this is the address of valid data.  */
+
+extern FRAME selected_frame;
+
+extern struct frame_info *get_frame_info ();
+extern struct frame_info *get_prev_frame_info ();
+
+extern FRAME create_new_frame ();
+extern void  flush_cached_frames ();
+
+extern void get_frame_saved_regs ();
+
+extern void  set_current_frame ();
+extern FRAME get_prev_frame ();
+extern FRAME get_current_frame ();
+extern FRAME get_next_frame ();
+
+extern struct block *get_frame_block ();
+extern struct block *get_current_block ();
+extern struct block *get_selected_block ();
+extern struct symbol *get_frame_function ();
+extern CORE_ADDR get_frame_pc ();
+extern CORE_ADDR get_pc_function_start ();
+struct block *block_for_pc ();
+
+int frameless_look_for_prologue ();
+
+void print_frame_args ();
+
+/* In stack.c */
+extern FRAME find_relative_frame ();
+extern void print_selected_frame ();
+extern void print_sel_frame ();
+extern void select_frame ();
+extern void record_selected_frame ();
+
+#endif /* frame.h not already included.  */
diff --git a/gdb/gdb-int.texinfo b/gdb/gdb-int.texinfo
new file mode 100755 (executable)
index 0000000..cc1b188
--- /dev/null
@@ -0,0 +1,242 @@
+\input texinfo
+@setfilename gdb-internals
+@ifinfo
+This file documents the internals of the GNU debugger GDB.
+
+Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+Contributed by Cygnus Support.  Written by John Gilmore.
+
+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 or distribute modified versions of this
+manual under the terms of the GPL (for which purpose this text may be
+regarded as a program in the language TeX).
+@end ifinfo
+
+@setchapternewpage odd
+@settitle GDB Internals
+@titlepage
+@title{Working in GDB}
+@subtitle{A guide to the internals of the GNU debugger}
+@author John Gilmore
+@author Cygnus Support
+@page
+@tex
+\def\$#1${{#1}}  % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision$}  % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1990, 1991 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.
+
+@end titlepage
+
+@node Top, Cleanups, (dir), (dir)
+
+@menu
+* Cleanups::                   Cleanups
+* Wrapping::                   Wrapping output lines
+* Releases::                   Configuring GDB for release
+* README::                     The README file
+* New Architectures::          Defining a new host or target architecture
+* Host versus Targt::          What features are in which files
+
+@end menu
+
+@node Cleanups, Wrapping, Top, Top
+@chapter Cleanups
+
+Cleanups are a structured way to deal with things that need to be done
+later.  When your code does something (like malloc some memory, or open
+a file) that needs to be undone later (e.g. free the memory or close
+the file), it can make a cleanup.  The cleanup will be done at some
+future point:  when the command is finished, when an error occurs, or
+when your code decides it's time to do cleanups.
+
+You can also discard cleanups, that is, throw them away without doing
+what they say.  This is only done if you ask that it be done.
+
+Syntax:
+
+@table @code
+@item old_chain = make_cleanup (function, arg);
+This makes a cleanup which will cause FUNCTION to be called with ARG
+(a char *) later.  The result, OLD_CHAIN, is a handle that can be
+passed to do_cleanups or discard_cleanups later.  Unless you are
+going to call do_cleanups or discard_cleanups yourself,
+you can ignore the result from make_cleanup.
+
+
+@item do_cleanups (old_chain);
+Performs all cleanups done since make_cleanup returned OLD_CHAIN.
+E.g.:   make_cleanup (a, 0); old = make_cleanup (b, 0); do_cleanups (old);
+will call b() but will not call a().  The cleanup that calls a() will remain
+in the cleanup chain, and will be done later unless otherwise discarded.
+
+@item discard_cleanups (old_chain);
+Same as do_cleanups except that it just removes the cleanups from the
+chain and does not call the specified functions.
+
+@end table
+
+Some functions, e.g. @code{fputs_filtered()} or @code{error()}, specify that they
+``should not be called when cleanups are not in place''.  This means
+that any actions you need to reverse in the case of an error or
+interruption must be on the cleanup chain before you call these functions,
+since they might never return to your code (they @samp{longjmp} instead).
+
+
+@node Wrapping, Releases, Cleanups, Top
+@chapter Wrapping output lines
+
+Output that goes through printf_filtered or fputs_filtered or
+fputs_demangled needs only to have calls to wrap_here() added 
+in places that would be good breaking points.  The utility routines
+will take care of actually wrapping if the line width is exceeded.
+
+The argument to wrap_here() is an indentation string which is printed
+ONLY if the line breaks there.  This argument is saved away and used
+later.  It must remain valid until the next call to wrap_here() or
+until a newline has been printed through the *_filtered functions.
+Don't pass in a local variable and then return!
+
+It is usually best to call wrap_here() after printing a comma or space.
+If you call it before printing a space, make sure that your indentation
+properly accounts for the leading space that will print if the line wraps
+there.
+
+Any function or set of functions that produce filtered output must finish
+by printing a newline, to flush the wrap buffer, before switching to
+unfiltered ("printf") output.  Symbol reading routines that print
+warnings are a good example.
+
+
+@node Releases, README, Wrapping, Top
+@chapter Configuring GDB for release
+
+
+GDB should be released after doing @samp{config.gdb none} in the top level
+directory.  This will leave a makefile there, but no tm- or xm- files.
+The makefile is needed, for example, for @samp{make gdb.tar.Z}@dots{}  If you
+have tm- or xm-files in the main source directory, C's include rules
+cause them to be used in preference to tm- and xm-files in the 
+subdirectories where the user will actually configure and build the
+binaries.
+
+@samp{config.gdb none} is also a good way to rebuild the top level Makefile
+after changing Makefile.dist, alldeps.mak, etc.
+
+
+
+@node README, New Architectures, Releases, Top
+@chapter The README file
+
+
+Check the README file, it often has useful information that does not
+appear anywhere else in the directory.
+
+
+
+@node New Architectures, Host versus Target, README, Top
+@chapter Defining a new host or target architecture
+
+
+When building support for a new host and/or target, this will help you
+organize where to put the various parts.  @var{ARCH} stands for the
+architecture involved.
+
+Object files needed when the host system is an @var{ARCH} are listed in
+the file @file{xconfig/@var{ARCH}}, in the Makefile macro @samp{XDEPFILES
+= }@dots{}.  You can also define XXXXXX in there.
+
+There are some ``generic'' versions of routines that can be used by
+various host systems.  If these routines work for the @var{ARCH} host,
+you can just include the generic file's name (with .o, not .c) in
+@code{XDEPFILES}.  Otherwise, you will need to write routines that
+perform the same functions as the generic file, put them into
+@code{@var{ARCH}-xdep.c}, and put @code{@var{ARCH}-xdep.o} into
+@code{XDEPFILES}.  These generic host support files include:
+
+@example
+       coredep.c, coredep.o
+@end example
+
+@table @code
+@item fetch_core_registers()
+Support for reading registers out of a core file.  This routine calls
+@code{register_addr(}), see below.
+
+@item register_addr()
+If your @code{xm-@var{ARCH}.h} file defines the macro @code{REGISTER_U_ADDR(reg)} to be the
+offset within the @samp{user} struct of a register (represented as a GDB
+register number), @file{coredep.c} will define the @code{register_addr()} function
+and use the macro in it.  If you do not define @code{REGISTER_U_ADDR}, but
+you are using the standard @code{fetch_core_registers}, you
+will need to define your own version of @code{register_addr}, put it into
+your @code{@var{ARCH}-xdep.c} file, and be sure @code{@var{ARCH}-xdep.o} is in the @code{XDEPFILES} list.
+If you have your own @code{fetch_core_registers}, you only need to define
+@code{register_addr} if your @code{fetch_core_registers} calls it.  Many custom
+@code{fetch_core_registers} implementations simply locate the registers
+themselves.
+@end table
+
+Files needed when the target system is an @var{ARCH} are listed in the file
+@file{tconfig/@var{ARCH}}, in the @code{Makefile} macro @samp{TDEPFILES = }@dots{}.  You can also
+define XXXXXX in there.
+
+Similar generic support files for target systems are:
+
+@example
+       exec.c, exec.o:
+@end example
+
+This file defines functions for accessing files that are executable
+on the target system.  These functions open and examine an exec file,
+extract data from one, write data to one, print information about one,
+etc.  Now that executable files are handled with BFD, every architecture
+should be able to use the generic exec.c rather than its own custom code.
+
+@node Host versus Target, , README, Top
+@chapter What is considered ``host-dependent'' versus ``target-dependent''?
+
+The xconfig/*, xm-*.h and *-xdep.c files are for host support.  The
+question is, what features or aspects of a debugging or cross-debugging
+environment are considered to be ``host'' support.
+
+Defines and include files needed to build on the host are host support.
+Examples are tty support, system defined types, host byte order, host
+float format.
+
+Unix child process support is considered an aspect of the host.  Since
+when you fork on the host you are still on the host, the various macros
+needed for finding the registers in the upage, running ptrace, and such
+are all in the host-dependent files.
+
+This is still somewhat of a grey area; I (John Gilmore) didn't do the
+xm- and tm- split for gdb (it was done by Jim Kingdon) so I have had to
+figure out the grounds on which it was split, and make my own choices
+as I evolve it.  I have moved many things out of the xdep files
+actually, partly as a result of BFD and partly by removing duplicated
+code.
+
+@contents
+@bye
+
diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h
new file mode 100644 (file)
index 0000000..39151f5
--- /dev/null
@@ -0,0 +1,63 @@
+/* Header file for GDB-specific command-line stuff.
+   Copyright (C) 1986, 1989, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "command.h"
+
+/* Chain containing all defined commands.  */
+
+extern struct cmd_list_element *cmdlist;
+
+/* Chain containing all defined info subcommands.  */
+
+extern struct cmd_list_element *infolist;
+
+/* Chain containing all defined enable subcommands. */
+
+extern struct cmd_list_element *enablelist;
+
+/* Chain containing all defined disable subcommands. */
+
+extern struct cmd_list_element *disablelist;
+
+/* Chain containing all defined delete subcommands. */
+
+extern struct cmd_list_element *deletelist;
+
+/* Chain containing all defined "enable breakpoint" subcommands. */
+
+extern struct cmd_list_element *enablebreaklist;
+
+/* Chain containing all defined set subcommands */
+
+extern struct cmd_list_element *setlist;
+
+/* Chain containing all defined show subcommands.  */
+extern struct cmd_list_element *showlist;
+
+/* Chain containing all defined \"set history\".  */
+
+extern struct cmd_list_element *sethistlist;
+
+/* Chain containing all defined \"show history\".  */
+extern struct cmd_list_element *showhistlist;
+
+/* Chain containing all defined \"unset history\".  */
+
+extern struct cmd_list_element *unsethistlist;
+
+void execute_command ();
+char **noop_completer ();
diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h
new file mode 100644 (file)
index 0000000..991ce64
--- /dev/null
@@ -0,0 +1,82 @@
+/* Machine independent variables that describe the core file under GDB.
+   Copyright (C) 1986, 1987, 1989, 1990  Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Interface routines for core, executable, etc.  */
+
+#include "bfd.h"               /* Binary File Description */
+
+/* Return the name of the executable file as a string.
+   ERR nonzero means get error if there is none specified;
+   otherwise return 0 in that case.  */
+char *get_exec_file ();
+
+/* Nonzero if there is a core file.  */
+int have_core_file_p ();
+
+/* Read "memory data" from whatever target or inferior we have. 
+   Returns zero if successful, errno value if not.  EIO is used
+   for address out of bounds.  If breakpoints are inserted, returns
+   shadow contents, not the breakpoints themselves.  From breakpoint.c.  */
+int read_memory_nobpt ();
+
+/* Report a memory error with error().  */
+
+void memory_error ();
+
+/* Like target_read_memory, but report an error if can't read.  */
+void read_memory ();
+
+/* Read an integer from debugged memory, given address and number of bytes.  */
+long read_memory_integer ();
+
+/* Hook for `exec_file_command' command to call.  */
+
+extern void (*exec_file_display_hook) ();
+   
+/* Binary File Diddlers for the exec and core files */
+extern bfd *core_bfd;
+extern bfd *exec_bfd;
+
+void core_file_command ();
+void exec_file_command ();
+void validate_files ();
+unsigned int register_addr ();
+int xfer_core_file ();
+void fetch_core_registers ();
+void registers_fetched ();
+
+#if !defined (KERNEL_U_ADDR)
+extern CORE_ADDR kernel_u_addr;
+#define KERNEL_U_ADDR kernel_u_addr
+#endif
+
+/* Struct section_table maps address ranges to file sections.  It is
+   mostly used with BFD files, but can be used without (e.g. for handling
+   raw disks, or files not in formats handled by BFD).  */
+
+struct section_table {
+  CORE_ADDR addr;              /* Lowest address in section */
+  CORE_ADDR endaddr;           /* 1+highest address in section */
+  sec_ptr   sec_ptr;           /* BFD section pointer */
+};
+
+/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
+   Returns 0 if OK, 1 on error.  */
+
+int build_section_table ();    
diff --git a/gdb/getpagesize.h b/gdb/getpagesize.h
new file mode 100755 (executable)
index 0000000..32adae6
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef BSD
+#ifndef BSD4_1
+#define HAVE_GETPAGESIZE
+#endif
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+
+#include <sys/param.h>
+
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#define getpagesize() NBPC
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+
+#endif /* not HAVE_GETPAGESIZE */
+
diff --git a/gdb/gmalloc.c b/gdb/gmalloc.c
new file mode 100755 (executable)
index 0000000..0468551
--- /dev/null
@@ -0,0 +1,1116 @@
+
+/* gmalloc.c - THIS FILE IS AUTOMAGICALLY GENERATED SO DON'T EDIT IT. */
+
+/* Single-file skeleton for GNU malloc.
+   Copyright 1989 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#define __ONEFILE
+
+/* DO NOT DELETE THIS LINE -- ansidecl.h INSERTED HERE. */
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library 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 1, or (at your option)
+any later version.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+       Macros
+               PTR             - Generic pointer type
+               LONG_DOUBLE     - `long double' type
+               CONST           - `const' keyword
+               VOLATILE        - `volatile' keyword
+               SIGNED          - `signed' keyword
+               PTRCONST        - Generic const pointer (void *const)
+
+       EXFUN(name, prototype)          - declare external function NAME
+                                         with prototype PROTOTYPE
+       DEFUN(name, arglist, args)      - define function NAME with
+                                         args ARGLIST of types in ARGS
+       DEFUN_VOID(name)                - define function NAME with no args
+       AND                             - argument separator for ARGS
+       NOARGS                          - null arglist
+       DOTS                            - `...' in args
+
+    For example:
+       extern int EXFUN(printf, (CONST char *format DOTS));
+       int DEFUN(fprintf, (stream, format),
+                 FILE *stream AND CONST char *format DOTS) { ... }
+       void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef        _ANSIDECL_H
+
+#define        _ANSIDECL_H     1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#ifdef __STDC__
+
+#define        PTR             void *
+#define        PTRCONST        void *CONST
+#define        LONG_DOUBLE     long double
+
+#define        AND             ,
+#define        NOARGS          void
+#define        CONST           const
+#define        VOLATILE        volatile
+#define        SIGNED          signed
+#define        DOTS            , ...
+
+#define        EXFUN(name, proto)              name proto
+#define        DEFUN(name, arglist, args)      name(args)
+#define        DEFUN_VOID(name)                name(NOARGS)
+
+#else  /* Not ANSI C.  */
+
+#define        PTR             char *
+#define        PTRCONST        PTR
+#define        LONG_DOUBLE     double
+
+#define        AND             ;
+#define        NOARGS
+#define        CONST
+#define        VOLATILE
+#define        SIGNED
+#define        DOTS
+
+#define        EXFUN(name, proto)              name()
+#define        DEFUN(name, arglist, args)      name arglist args;
+#define        DEFUN_VOID(name)                name()
+
+#endif /* ANSI C.  */
+
+
+#endif /* ansidecl.h   */
+
+#ifdef __STDC__
+#include <limits.h>
+#else
+/* DO NOT DELETE THIS LINE -- limits.h INSERTED HERE. */
+/* Number of bits in a `char'.  */
+#define CHAR_BIT 8
+
+/* No multibyte characters supported yet.  */
+#define MB_LEN_MAX 1
+
+/* Minimum and maximum values a `signed char' can hold.  */
+#define SCHAR_MIN -128
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold.  (Minimum is 0).  */
+#define UCHAR_MAX 255U
+
+/* Minimum and maximum values a `char' can hold.  */
+#ifdef __CHAR_UNSIGNED__
+#define CHAR_MIN 0
+#define CHAR_MAX 255U
+#else
+#define CHAR_MIN -128
+#define CHAR_MAX 127
+#endif
+
+/* Minimum and maximum values a `signed short int' can hold.  */
+#define SHRT_MIN -32768
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short int' can hold.  (Minimum is 0).  */
+#define USHRT_MAX 65535U
+
+/* Minimum and maximum values a `signed int' can hold.  */
+#define INT_MIN -2147483648
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold.  (Minimum is 0).  */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long int' can hold.
+   (Same as `int').  */
+#define LONG_MIN (-LONG_MAX-1)
+#define LONG_MAX 2147483647
+
+/* Maximum value an `unsigned long int' can hold.  (Minimum is 0).  */
+#define ULONG_MAX 4294967295U
+#endif
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+/* DO NOT DELETE THIS LINE -- stddef.h INSERTED HERE. */
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+/* Signed type of difference of two pointers.  */
+
+typedef long ptrdiff_t;
+
+/* Unsigned type of `sizeof' something.  */
+
+#ifndef _SIZE_T        /* in case <sys/types.h> has defined it. */
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif /* _SIZE_T */
+
+/* A null pointer constant.  */
+
+#undef NULL            /* in case <stdio.h> has defined it. */
+#define NULL 0
+
+/* Offset of member MEMBER in a struct of type TYPE.  */
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* _STDDEF_H */
+#endif
+
+/* DO NOT DELETE THIS LINE -- stdlib.h INSERTED HERE. */
+/* Fake stdlib.h supplying the stuff needed by malloc. */
+
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern void EXFUN(abort, (void));
+extern void EXFUN(free, (PTR));
+extern PTR EXFUN(malloc, (size_t));
+extern PTR EXFUN(realloc, (PTR, size_t));
+
+/* DO NOT DELETE THIS LINE -- string.h INSERTED HERE. */
+/* Fake string.h supplying stuff used by malloc. */
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern PTR EXFUN(memcpy, (PTR, PTR, size_t));
+extern PTR EXFUN(memset, (PTR, int, size_t));
+#define memmove memcpy
+
+#define _MALLOC_INTERNAL
+/* DO NOT DELETE THIS LINE -- malloc.h INSERTED HERE. */
+/* Declarations for `malloc' and friends.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H      1
+
+#ifndef __ONEFILE
+#define        __need_NULL
+#define        __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+#endif
+
+#ifdef _MALLOC_INTERNAL
+
+#ifndef __ONEFILE
+#include <limits.h>
+#endif
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.  */
+#define INT_BIT                (CHAR_BIT * sizeof(int))
+#define BLOCKLOG       (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE      (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit).  */
+#define HEAP           (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system.  */
+#define FINAL_FREE_BLOCKS      8
+
+/* Where to start searching the free list when looking for new memory.
+   The two possible values are 0 and _heapindex.  Starting at 0 seems
+   to reduce total memory usage, while starting at _heapindex seems to
+   run faster.  */
+#define MALLOC_SEARCH_START    _heapindex
+
+/* Data structure giving per-block information.  */
+typedef union
+  {
+    /* Heap information for a busy block.  */
+    struct
+      {
+       /* Zero for a large block, or positive giving the
+          logarithm to the base two of the fragment size.  */
+       int type;
+       union
+         {
+           struct
+             {
+               size_t nfree;   /* Free fragments in a fragmented block.  */
+               size_t first;   /* First free fragment of the block.  */
+             } frag;
+           /* Size (in blocks) of a large cluster.  */
+           size_t size;
+         } info;
+      } busy;
+    /* Heap information for a free block (that may be the first of
+       a free cluster).  */
+    struct
+      {
+       size_t size;            /* Size (in blocks) of a free cluster.  */
+       size_t next;            /* Index of next free cluster.  */
+       size_t prev;            /* Index of previous free cluster.  */
+      } free;
+  } malloc_info;
+
+/* Pointer to first block of the heap.  */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information.  */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa.  */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table.  */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments.  */
+struct list
+  {
+    struct list *next;
+    struct list *prev;
+  };
+
+/* Free list headers for each fragment size.  */
+extern struct list _fraghead[];
+
+/* Instrumentation.  */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of free() used in morecore(). */
+extern void EXFUN(__free, (PTR __ptr));
+
+#endif  /* _MALLOC_INTERNAL.  */
+
+/* Underlying allocation function; successive calls should
+   return contiguous pieces of memory.  */
+extern PTR EXFUN((*__morecore), (ptrdiff_t __size));
+
+/* Default value of previous.  */
+extern PTR EXFUN(__default_morecore, (ptrdiff_t __size));
+
+/* Flag whether malloc has been called.  */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions.  */
+extern void EXFUN((*__free_hook), (PTR __ptr));
+extern PTR EXFUN((*__malloc_hook), (size_t __size));
+extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks.  */
+extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
+
+/* Statistics available to the user.  */
+struct mstats
+  {
+    size_t bytes_total;                /* Total size of the heap. */
+    size_t chunks_used;                /* Chunks allocated by the user. */
+    size_t bytes_used;         /* Byte total of user-allocated chunks. */
+    size_t chunks_free;                /* Chunks in the free list. */
+    size_t bytes_free;         /* Byte total of chunks in the free list. */
+  };
+
+/* Pick up the current statistics. */
+extern struct mstats EXFUN(mstats, (NOARGS));
+
+#endif /* malloc.h  */
+
+/* DO NOT DELETE THIS LINE -- free.c INSERTED HERE. */
+/* Free a block of memory allocated by `malloc'.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* Debugging hook for free.  */
+void EXFUN((*__free_hook), (PTR __ptr));
+
+/* Return memory to the heap.  Like free() but don't call a __free_hook
+   if there is one.  */
+void
+DEFUN(__free, (ptr), PTR ptr)
+{
+  int type;
+  size_t block, blocks;
+  register size_t i;
+  struct list *prev, *next;
+
+  block = BLOCK(ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Get as many statistics as early as we can.  */
+      --_chunks_used;
+      _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+      _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+      /* Find the free cluster previous to this one in the free list.
+        Start searching at the last block referenced; this may benefit
+        programs with locality of allocation.  */
+      i = _heapindex;
+      if (i > block)
+       while (i > block)
+         i = _heapinfo[i].free.prev;
+      else
+       {
+         do
+           i = _heapinfo[i].free.next;
+         while (i > 0 && i < block);
+         i = _heapinfo[i].free.prev;
+       }
+
+      /* Determine how to link this block into the free list.  */
+      if (block == i + _heapinfo[i].free.size)
+       {
+         /* Coalesce this block with its predecessor.  */
+         _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+         block = i;
+       }
+      else
+       {
+         /* Really link this block back into the free list.  */
+         _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+         _heapinfo[block].free.next = _heapinfo[i].free.next;
+         _heapinfo[block].free.prev = i;
+         _heapinfo[i].free.next = block;
+         _heapinfo[_heapinfo[block].free.next].free.prev = block;
+         ++_chunks_free;
+       }
+
+      /* Now that the block is linked in, see if we can coalesce it
+        with its successor (by deleting its successor from the list
+        and adding in its size).  */
+      if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+       {
+         _heapinfo[block].free.size
+           += _heapinfo[_heapinfo[block].free.next].free.size;
+         _heapinfo[block].free.next
+           = _heapinfo[_heapinfo[block].free.next].free.next;
+         _heapinfo[_heapinfo[block].free.next].free.prev = block;
+         --_chunks_free;
+       }
+
+      /* Now see if we can return stuff to the system.  */
+      blocks = _heapinfo[block].free.size;
+      if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+         && (*__morecore)(0) == ADDRESS(block + blocks))
+       {
+         register size_t bytes = blocks * BLOCKSIZE;
+         _heaplimit -= blocks;
+         (*__morecore)(- bytes);
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapinfo[block].free.next;
+         _heapinfo[_heapinfo[block].free.next].free.prev
+           = _heapinfo[block].free.prev;
+         block = _heapinfo[block].free.prev;
+         --_chunks_free;
+         _bytes_free -= bytes;
+       }
+
+      /* Set the next search to begin at this block.  */
+      _heapindex = block;
+      break;
+
+    default:
+      /* Do some of the statistics.  */
+      --_chunks_used;
+      _bytes_used -= 1 << type;
+      ++_chunks_free;
+      _bytes_free += 1 << type;
+
+      /* Get the address of the first free fragment in this block.  */
+      prev = (struct list *) ((char *) ADDRESS(block) +
+                             (_heapinfo[block].busy.info.frag.first << type));
+
+      if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+       {
+         /* If all fragments of this block are free, remove them
+            from the fragment list and free the whole block.  */
+         next = prev;
+         for (i = 1; i < BLOCKSIZE >> type; ++i)
+           next = next->next;
+         prev->prev->next = next;
+         if (next != NULL)
+           next->prev = prev->prev;
+         _heapinfo[block].busy.type = 0;
+         _heapinfo[block].busy.info.size = 1;
+
+         /* Keep the statistics accurate.  */
+         ++_chunks_used;
+         _bytes_used += BLOCKSIZE;
+         _chunks_free -= BLOCKSIZE >> type;
+         _bytes_free -= BLOCKSIZE;
+
+         free(ADDRESS(block));
+       }
+      else if (_heapinfo[block].busy.info.frag.nfree != 0)
+       {
+         /* If some fragments of this block are free, link this
+            fragment into the fragment list after the first free
+            fragment of this block. */
+         next = (struct list *) ptr;
+         next->next = prev->next;
+         next->prev = prev;
+         prev->next = next;
+         if (next->next != NULL)
+           next->next->prev = next;
+         ++_heapinfo[block].busy.info.frag.nfree;
+       }
+      else
+       {
+         /* No fragments of this block are free, so link this
+            fragment into the fragment list and announce that
+            it is the first free fragment of this block. */
+         prev = (struct list *) ptr;
+         _heapinfo[block].busy.info.frag.nfree = 1;
+         _heapinfo[block].busy.info.frag.first = (unsigned int)
+           (((char *) ptr - (char *) NULL) % BLOCKSIZE >> type);
+         prev->next = _fraghead[type].next;
+         prev->prev = &_fraghead[type];
+         prev->prev->next = prev;
+         if (prev->next != NULL)
+           prev->next->prev = prev;
+       }
+      break;
+    }
+}
+
+/* Return memory to the heap.  */
+void
+DEFUN(free, (ptr), PTR ptr)
+{
+  if (ptr == NULL)
+    return;
+
+  if (__free_hook != NULL)
+    (*__free_hook)(ptr);
+  else
+    __free (ptr);
+}
+
+/* DO NOT DELETE THIS LINE -- malloc.c INSERTED HERE. */
+/* Memory allocator `malloc'.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* How to really get more memory.  */
+PTR EXFUN((*__morecore), (ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'.  */
+PTR EXFUN((*__malloc_hook), (size_t __size));
+
+/* Pointer to the base of the first block.  */
+char *_heapbase;
+
+/* Block information table.  Allocated with align/__free (not malloc/free).  */
+malloc_info *_heapinfo;
+
+/* Number of info entries.  */
+static size_t heapsize;
+
+/* Search index in the info table.  */
+size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+size_t _heaplimit;
+
+/* Free lists for each fragment size.  */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation.  */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced?  */
+int __malloc_initialized;
+
+/* Aligned allocation.  */
+static PTR
+DEFUN(align, (size), size_t size)
+{
+  PTR result;
+  unsigned int adj;
+
+  result = (*__morecore)(size);
+  adj = (unsigned int) ((char *) result - (char *) NULL) % BLOCKSIZE;
+  if (adj != 0)
+    {
+      adj = BLOCKSIZE - adj;
+      (void) (*__morecore)(adj);
+      result = (char *) result + adj;
+    }
+  return result;
+}
+
+/* Set everything up and remember that we have.  */
+static int
+DEFUN_VOID(initialize)
+{
+  heapsize = HEAP / BLOCKSIZE;
+  _heapinfo = (malloc_info *) align(heapsize * sizeof(malloc_info));
+  if (_heapinfo == NULL)
+    return 0;
+  memset(_heapinfo, 0, heapsize * sizeof(malloc_info));
+  _heapinfo[0].free.size = 0;
+  _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+  _heapindex = 0;
+  _heapbase = (char *) _heapinfo;
+  __malloc_initialized = 1;
+  return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+   growing the heap info table as necessary. */
+static PTR
+DEFUN(morecore, (size), size_t size)
+{
+  PTR result;
+  malloc_info *newinfo, *oldinfo;
+  size_t newsize;
+
+  result = align(size);
+  if (result == NULL)
+    return NULL;
+
+  /* Check if we need to grow the info table.  */
+  if (BLOCK((char *) result + size) > heapsize)
+    {
+      newsize = heapsize;
+      while (BLOCK((char *) result + size) > newsize)
+       newsize *= 2;
+      newinfo = (malloc_info *) align(newsize * sizeof(malloc_info));
+      if (newinfo == NULL)
+       {
+         (*__morecore)(- size);
+         return NULL;
+       }
+      memset(newinfo, 0, newsize * sizeof(malloc_info));
+      memcpy(newinfo, _heapinfo, heapsize * sizeof(malloc_info));
+      oldinfo = _heapinfo;
+      newinfo[BLOCK(oldinfo)].busy.type = 0;
+      newinfo[BLOCK(oldinfo)].busy.info.size
+       = BLOCKIFY(heapsize * sizeof(malloc_info));
+      _heapinfo = newinfo;
+      __free(oldinfo);
+      heapsize = newsize;
+    }
+
+  _heaplimit = BLOCK((char *) result + size);
+  return result;
+}
+
+/* Allocate memory from the heap.  */
+PTR
+DEFUN(malloc, (size), size_t size)
+{
+  PTR result;
+  size_t block, blocks, lastblocks, start;
+  register size_t i;
+  struct list *next;
+
+  if (size == 0)
+    return NULL;
+
+  if (__malloc_hook != NULL)
+    return (*__malloc_hook)(size);
+
+  if (!__malloc_initialized)
+    if (!initialize())
+      return NULL;
+
+  if (size < sizeof(struct list))
+    size = sizeof(struct list);
+
+  /* Determine the allocation policy based on the request size.  */
+  if (size <= BLOCKSIZE / 2)
+    {
+      /* Small allocation to receive a fragment of a block.
+        Determine the logarithm to base two of the fragment size. */
+      register size_t log = 1;
+      --size;
+      while ((size /= 2) != 0)
+       ++log;
+
+      /* Look in the fragment lists for a
+        free fragment of the desired size. */
+      next = _fraghead[log].next;
+      if (next != NULL)
+       {
+         /* There are free fragments of this size.
+            Pop a fragment out of the fragment list and return it.
+            Update the block's nfree and first counters. */
+         result = (PTR) next;
+         next->prev->next = next->next;
+         if (next->next != NULL)
+           next->next->prev = next->prev;
+         block = BLOCK(result);
+         if (--_heapinfo[block].busy.info.frag.nfree != 0)
+           _heapinfo[block].busy.info.frag.first = (unsigned int)
+             (((char *) next->next - (char *) NULL) % BLOCKSIZE) >> log;
+
+         /* Update the statistics.  */
+         ++_chunks_used;
+         _bytes_used += 1 << log;
+         --_chunks_free;
+         _bytes_free -= 1 << log;
+       }
+      else
+       {
+         /* No free fragments of the desired size, so get a new block
+            and break it into fragments, returning the first.  */
+         result = malloc(BLOCKSIZE);
+         if (result == NULL)
+           return NULL;
+
+         /* Link all fragments but the first into the free list.  */
+         for (i = 1; i < BLOCKSIZE >> log; ++i)
+           {
+             next = (struct list *) ((char *) result + (i << log));
+             next->next = _fraghead[log].next;
+             next->prev = &_fraghead[log];
+             next->prev->next = next;
+             if (next->next != NULL)
+               next->next->prev = next;
+           }
+
+         /* Initialize the nfree and first counters for this block.  */
+         block = BLOCK(result);
+         _heapinfo[block].busy.type = log;
+         _heapinfo[block].busy.info.frag.nfree = i - 1;
+         _heapinfo[block].busy.info.frag.first = i - 1;
+
+         _chunks_free += (BLOCKSIZE >> log) - 1;
+         _bytes_free += BLOCKSIZE - (1 << log);
+       }
+    }
+  else
+    {
+      /* Large allocation to receive one or more blocks.
+        Search the free list in a circle starting at the last place visited.
+        If we loop completely around without finding a large enough
+        space we will have to get more memory from the system.  */
+      blocks = BLOCKIFY(size);
+      start = block = MALLOC_SEARCH_START;
+      while (_heapinfo[block].free.size < blocks)
+       {
+         block = _heapinfo[block].free.next;
+         if (block == start)
+           {
+             /* Need to get more from the system.  Check to see if
+                the new core will be contiguous with the final free
+                block; if so we don't need to get as much.  */
+             block = _heapinfo[0].free.prev;
+             lastblocks = _heapinfo[block].free.size;
+             if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+                 (*__morecore)(0) == ADDRESS(block + lastblocks) &&
+                 (morecore((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+               {
+                 _heapinfo[block].free.size = blocks;
+                 _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+                 continue;
+               }
+             result = morecore(blocks * BLOCKSIZE);
+             if (result == NULL)
+               return NULL;
+             block = BLOCK(result);
+             _heapinfo[block].busy.type = 0;
+             _heapinfo[block].busy.info.size = blocks;
+             ++_chunks_used;
+             _bytes_used += blocks * BLOCKSIZE;
+             return result;
+           }
+       }
+
+      /* At this point we have found a suitable free list entry.
+        Figure out how to remove what we need from the list. */
+      result = ADDRESS(block);
+      if (_heapinfo[block].free.size > blocks)
+       {
+         /* The block we found has a bit left over,
+            so relink the tail end back into the free list. */
+         _heapinfo[block + blocks].free.size
+           = _heapinfo[block].free.size - blocks;
+         _heapinfo[block + blocks].free.next
+           = _heapinfo[block].free.next;
+         _heapinfo[block + blocks].free.prev
+           = _heapinfo[block].free.prev;
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapinfo[_heapinfo[block].free.next].free.prev
+             = _heapindex = block + blocks;
+       }
+      else
+       {
+         /* The block exactly matches our requirements,
+            so just remove it from the list. */
+         _heapinfo[_heapinfo[block].free.next].free.prev
+           = _heapinfo[block].free.prev;
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapindex = _heapinfo[block].free.next;
+         --_chunks_free;
+       }
+
+      _heapinfo[block].busy.type = 0;
+      _heapinfo[block].busy.info.size = blocks;
+      ++_chunks_used;
+      _bytes_used += blocks * BLOCKSIZE;
+      _bytes_free -= blocks * BLOCKSIZE;
+    }
+
+  return result;
+}
+
+/* DO NOT DELETE THIS LINE -- realloc.c INSERTED HERE. */
+/* Change the size of a block allocated by `malloc'.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc.  */
+PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+   to the (possibly moved) region.  This is optimized for speed;
+   some benchmarks seem to indicate that greater compactness is
+   achieved by unconditionally allocating and copying to a
+   new region.  This module has incestuous knowledge of the
+   internals of both free and malloc. */
+PTR
+DEFUN(realloc, (ptr, size), PTR ptr AND size_t size)
+{
+  PTR result;
+  int type;
+  size_t block, blocks, oldlimit;
+
+  if (size == 0)
+    {
+      free(ptr);
+      return NULL;
+    }
+  else if (ptr == NULL)
+    return malloc(size);
+
+  if (__realloc_hook != NULL)
+    return (*__realloc_hook)(ptr, size);
+
+  block = BLOCK(ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Maybe reallocate a large block to a small fragment.  */
+      if (size <= BLOCKSIZE / 2)
+       {
+         result = malloc(size);
+         if (result != NULL)
+           {
+             memcpy(result, ptr, size);
+             free(ptr);
+             return result;
+           }
+       }
+
+      /* The new size is a large allocation as well;
+        see if we can hold it in place. */
+      blocks = BLOCKIFY(size);
+      if (blocks < _heapinfo[block].busy.info.size)
+       {
+         /* The new size is smaller; return
+            excess memory to the free list. */
+         _heapinfo[block + blocks].busy.type = 0;
+         _heapinfo[block + blocks].busy.info.size
+           = _heapinfo[block].busy.info.size - blocks;
+         _heapinfo[block].busy.info.size = blocks;
+         free(ADDRESS(block + blocks));
+         result = ptr;
+       }
+      else if (blocks == _heapinfo[block].busy.info.size)
+       /* No size change necessary.  */
+       result = ptr;
+      else
+       {
+         /* Won't fit, so allocate a new region that will.
+            Free the old region first in case there is sufficient
+            adjacent free space to grow without moving. */
+         blocks = _heapinfo[block].busy.info.size;
+         /* Prevent free from actually returning memory to the system.  */
+         oldlimit = _heaplimit;
+         _heaplimit = 0;
+         free(ptr);
+         _heaplimit = oldlimit;
+         result = malloc(size);
+         if (result == NULL)
+           {
+             (void) malloc(blocks * BLOCKSIZE);
+             return NULL;
+           }
+         if (ptr != result)
+           memmove(result, ptr, blocks * BLOCKSIZE);
+       }
+      break;
+
+    default:
+      /* Old size is a fragment; type is logarithm
+        to base two of the fragment size.  */
+      if (size > 1 << (type - 1) && size <= 1 << type)
+       /* The new size is the same kind of fragment.  */
+       result = ptr;
+      else
+       {
+         /* The new size is different; allocate a new space,
+            and copy the lesser of the new size and the old. */
+         result = malloc(size);
+         if (result == NULL)
+           return NULL;
+         memcpy(result, ptr, MIN(size, 1 << type));
+         free(ptr);
+       }
+      break;
+    }
+
+  return result;
+}
+
+/* DO NOT DELETE THIS LINE -- unix.c INSERTED HERE. */
+/* unix.c - get more memory with a UNIX system call.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+extern PTR EXFUN(sbrk, (ptrdiff_t size));
+
+PTR
+DEFUN(__default_morecore, (size), ptrdiff_t size)
+{
+  PTR result;
+
+  result = sbrk(size);
+  if (result == (PTR) -1)
+    return NULL;
+  return result;
+}
+
+#define __getpagesize getpagesize
+/* DO NOT DELETE THIS LINE -- valloc.c INSERTED HERE. */
+/* Allocate memory on a page boundary.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#endif /* __ONEFILE */
+
+extern size_t EXFUN(__getpagesize, (NOARGS));
+
+static size_t pagesize;
+
+PTR
+DEFUN(valloc, (size), size_t size)
+{
+  PTR result;
+  unsigned int adj;
+
+  if (pagesize == 0)
+    pagesize = __getpagesize();
+
+  result = malloc(size + pagesize);
+  if (result == NULL)
+    return NULL;
+  adj = (unsigned int) ((char *) result - (char *) NULL) % pagesize;
+  if (adj != 0)
+    result = (char *) result + pagesize - adj;
+  return result;
+}
diff --git a/gdb/gmalloc.h b/gdb/gmalloc.h
new file mode 100755 (executable)
index 0000000..8718e80
--- /dev/null
@@ -0,0 +1,161 @@
+/* Declarations for `malloc' and friends.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H      1
+
+#ifndef __ONEFILE
+#define        __need_NULL
+#define        __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+#endif
+
+#ifdef _MALLOC_INTERNAL
+
+#ifndef __ONEFILE
+#include <limits.h>
+#endif
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.  */
+#define INT_BIT                (CHAR_BIT * sizeof(int))
+#define BLOCKLOG       (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE      (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit).  */
+#define HEAP           (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system.  */
+#define FINAL_FREE_BLOCKS      8
+
+/* Where to start searching the free list when looking for new memory.
+   The two possible values are 0 and _heapindex.  Starting at 0 seems
+   to reduce total memory usage, while starting at _heapindex seems to
+   run faster.  */
+#define MALLOC_SEARCH_START    _heapindex
+
+/* Data structure giving per-block information.  */
+typedef union
+  {
+    /* Heap information for a busy block.  */
+    struct
+      {
+       /* Zero for a large block, or positive giving the
+          logarithm to the base two of the fragment size.  */
+       int type;
+       union
+         {
+           struct
+             {
+               size_t nfree;   /* Free fragments in a fragmented block.  */
+               size_t first;   /* First free fragment of the block.  */
+             } frag;
+           /* Size (in blocks) of a large cluster.  */
+           size_t size;
+         } info;
+      } busy;
+    /* Heap information for a free block (that may be the first of
+       a free cluster).  */
+    struct
+      {
+       size_t size;            /* Size (in blocks) of a free cluster.  */
+       size_t next;            /* Index of next free cluster.  */
+       size_t prev;            /* Index of previous free cluster.  */
+      } free;
+  } malloc_info;
+
+/* Pointer to first block of the heap.  */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information.  */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa.  */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table.  */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments.  */
+struct list
+  {
+    struct list *next;
+    struct list *prev;
+  };
+
+/* Free list headers for each fragment size.  */
+extern struct list _fraghead[];
+
+/* Instrumentation.  */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of free() used in morecore(). */
+extern void EXFUN(__free, (PTR __ptr));
+
+#endif  /* _MALLOC_INTERNAL.  */
+
+/* Underlying allocation function; successive calls should
+   return contiguous pieces of memory.  */
+extern PTR EXFUN((*__morecore), (ptrdiff_t __size));
+
+/* Default value of previous.  */
+extern PTR EXFUN(__default_morecore, (ptrdiff_t __size));
+
+/* Flag whether malloc has been called.  */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions.  */
+extern void EXFUN((*__free_hook), (PTR __ptr));
+extern PTR EXFUN((*__malloc_hook), (size_t __size));
+extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks.  */
+extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
+
+/* Statistics available to the user.  */
+struct mstats
+  {
+    size_t bytes_total;                /* Total size of the heap. */
+    size_t chunks_used;                /* Chunks allocated by the user. */
+    size_t bytes_used;         /* Byte total of user-allocated chunks. */
+    size_t chunks_free;                /* Chunks in the free list. */
+    size_t bytes_free;         /* Byte total of chunks in the free list. */
+  };
+
+/* Pick up the current statistics. */
+extern struct mstats EXFUN(mstats, (NOARGS));
+
+#endif /* malloc.h  */
diff --git a/gdb/gould-pinsn.c b/gdb/gould-pinsn.c
new file mode 100644 (file)
index 0000000..b655f26
--- /dev/null
@@ -0,0 +1,294 @@
+/* Print GOULD RISC instructions for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "gdbcore.h"
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#if defined GOULD_PN
+#include "pn-opcode.h"
+#else
+#include "np1-opcode.h"
+#endif
+
+/* GOULD RISC instructions are never longer than this many bytes.  */
+#define MAXLEN 4
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof gld_opcodes / sizeof gld_opcodes[0])
+
+\f
+/* Print the GOULD instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn (memaddr, stream)
+       CORE_ADDR memaddr;
+       FILE *stream;
+{
+       unsigned char buffer[MAXLEN];
+       register int i;
+       register char *d;
+       register int bestmask;
+       unsigned best;
+       int temp, index, bestlen;
+
+       read_memory (memaddr, buffer, MAXLEN);
+
+       bestmask = 0;
+       index = -1;
+       best = 0xffffffff;
+       for (i = 0; i < NOPCODES; i++)
+       {
+               register unsigned int opcode = gld_opcodes[i].opcode;
+               register unsigned int mask = gld_opcodes[i].mask;
+               register unsigned int len = gld_opcodes[i].length;
+               register unsigned int test;
+
+               /* Get possible opcode bytes into integer */
+               test = buffer[0] << 24;
+               test |= buffer[1] << 16;
+               test |= buffer[2] << 8;
+               test |= buffer[3];
+
+               /* Mask with opcode and see if match */
+               if ((opcode & mask) == (test & mask))
+               {
+                       /* See if second or third match */
+                       if (index >= 0)
+                       {
+                               /* Take new one if it looks good */
+                               if (bestlen == MAXLEN && len == MAXLEN)
+                               {
+                                       /* See if lower bits matched */
+                                       if (((bestmask & 3) == 0) &&
+                                           ((mask & 3) != 0))
+                                       {
+                                               bestmask = mask;
+                                               bestlen = len;
+                                               best = test;
+                                               index = i;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               /* First match, save it */
+                               bestmask = mask;
+                               bestlen = len;
+                               best = test;
+                               index = i;
+                       }
+               }
+       }
+
+       /* Handle undefined instructions.  */
+       if (index < 0)
+       {
+               fprintf (stream, "undefined   0%o",(buffer[0]<<8)+buffer[1]);
+               return 2;
+       }
+
+       /* Print instruction name */
+       fprintf (stream, "%-12s", gld_opcodes[index].name);
+
+       /* Adjust if short instruction */
+       if (gld_opcodes[index].length < 4)
+       {
+               best >>= 16;
+               i = 0;
+       }
+       else
+       {
+               i = 16;
+       }
+
+       /* Dump out instruction arguments */
+       for (d = gld_opcodes[index].args; *d; ++d)
+       {
+           switch (*d)
+           {
+               case 'f':
+                   fprintf (stream, "%d",  (best >> (7 + i)) & 7);
+                   break;
+               case 'r':
+                   fprintf (stream, "r%d", (best >> (7 + i)) & 7);
+                   break;
+               case 'R':
+                   fprintf (stream, "r%d", (best >> (4 + i)) & 7);
+                   break;
+               case 'b':
+                   fprintf (stream, "b%d", (best >> (7 + i)) & 7);
+                   break;
+               case 'B':
+                   fprintf (stream, "b%d", (best >> (4 + i)) & 7);
+                   break;
+               case 'v':
+                   fprintf (stream, "b%d", (best >> (7 + i)) & 7);
+                   break;
+               case 'V':
+                   fprintf (stream, "b%d", (best >> (4 + i)) & 7);
+                   break;
+               case 'X':
+                   temp = (best >> 20) & 7;
+                   if (temp)
+                       fprintf (stream, "r%d", temp);
+                   else
+                       putc ('0', stream);
+                   break;
+               case 'A':
+                   temp = (best >> 16) & 7;
+                   if (temp)
+                       fprintf (stream, "(b%d)", temp);
+                   break;
+               case 'S':
+                   fprintf (stream, "#%d", best & 0x1f);
+                   break;
+               case 'I':
+                   fprintf (stream, "#%x", best & 0xffff);
+                   break;
+               case 'O':
+                   fprintf (stream, "%x", best & 0xffff);
+                   break;
+               case 'h':
+                   fprintf (stream, "%d", best & 0xfffe);
+                   break;
+               case 'd':
+                   fprintf (stream, "%d", best & 0xfffc);
+                   break;
+               case 'T':
+                   fprintf (stream, "%d", (best >> 8) & 0xff);
+                   break;
+               case 'N':
+                   fprintf (stream, "%d", best & 0xff);
+                   break;
+               default:
+                   putc (*d, stream);
+                   break;
+           }
+       }
+
+       /* Return length of instruction */
+       return (gld_opcodes[index].length);
+}
+
+/*
+ * Find the number of arguments to a function.
+ */
+findarg(frame)
+       struct frame_info *frame;
+{
+       register struct symbol *func;
+       register unsigned pc;
+
+#ifdef notdef
+       /* find starting address of frame function */
+       pc = get_pc_function_start (frame->pc);
+
+       /* find function symbol info */
+       func = find_pc_function (pc);
+
+       /* call blockframe code to look for match */
+       if (func != NULL)
+                return (func->value.block->nsyms / sizeof(int));
+#endif
+
+        return (-1);
+} 
+
+/*
+ * In the case of the NPL, the frame's norminal address is Br2 and the 
+ * previous routines frame is up the stack X bytes.  Finding out what
+ * 'X' is can be tricky.
+ *
+ *    1.) stored in the code function header xA(Br1).
+ *    2.) must be careful of recurssion.
+ */
+FRAME_ADDR
+findframe(thisframe)
+    FRAME thisframe;
+{
+    register FRAME_ADDR pointer;
+    FRAME_ADDR framechain();
+#if 0    
+    struct frame_info *frame;
+
+    /* Setup toplevel frame structure */
+    frame->pc = read_pc();
+    frame->next_frame = 0;
+    frame->frame = read_register (SP_REGNUM);  /* Br2 */
+
+    /* Search for this frame (start at current Br2) */
+    do
+    {
+       pointer = framechain(frame);
+       frame->next_frame = frame->frame;
+       frame->frame = pointer;
+       frame->pc = FRAME_SAVED_PC(frame);
+    }
+    while (frame->next_frame != thisframe);
+#endif
+
+    pointer = framechain (thisframe);
+
+    /* stop gap for now, end at __base3 */
+    if (thisframe->pc == 0)
+       return 0;
+
+    return pointer;
+}
+
+/*
+ * Gdb front-end and internal framechain routine.
+ * Go back up stack one level.  Tricky...
+ */
+FRAME_ADDR
+framechain(frame)
+    register struct frame_info *frame;
+{
+    register CORE_ADDR func, prevsp;
+    register unsigned value;
+
+    /* Get real function start address from internal frame address */
+    func = get_pc_function_start(frame->pc);
+
+    /* If no stack given, read register Br1 "(sp)" */
+    if (!frame->frame)
+       prevsp = read_register (SP_REGNUM);
+    else
+       prevsp = frame->frame;
+
+    /* Check function header, case #2 */
+    value = read_memory_integer (func, 4);
+    if (value)
+    {
+       /* 32bit call push value stored in function header */
+       prevsp += value;
+    }
+    else
+    {
+       /* read half-word from suabr at start of function */
+       prevsp += read_memory_integer (func + 10, 2);
+    }
+
+    return (prevsp);
+}
diff --git a/gdb/gould-xdep.c b/gdb/gould-xdep.c
new file mode 100644 (file)
index 0000000..c3aec0d
--- /dev/null
@@ -0,0 +1,132 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+       struct user u;
+       int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name (filename);
+       data_start = exec_data_start;
+
+       data_end = data_start + NBPG * u.u_dsize;
+       stack_start = stack_end - NBPG * u.u_ssize;
+       data_offset = NBPG * UPAGES;
+       stack_offset = NBPG * (UPAGES + u.u_dsize);
+       reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+
+       /* I don't know where to find this info.
+          So, for now, mark it as not available.  */
+       core_aouthdr.a_magic = 0;
+
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < NUM_REGS; regno++)
+           {
+             char buf[MAX_REGISTER_RAW_SIZE];
+
+             val = lseek (corechan, register_addr (regno, reg_offset), 0);
+             if (val < 0)
+               perror_with_name (filename);
+
+             val = myread (corechan, buf, sizeof buf);
+             if (val < 0)
+               perror_with_name (filename);
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
diff --git a/gdb/hp300hpux-xdep.c b/gdb/hp300hpux-xdep.c
new file mode 100755 (executable)
index 0000000..f7f1cf0
--- /dev/null
@@ -0,0 +1,230 @@
+/* HP/UX interface for HP 300's, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+/* Defining this means some system include files define some extra stuff.  */
+#define WOPR
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <sys/trap.h>
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#define INFERIOR_AR0(u)                                                        \
+  ((ptrace                                                             \
+    (PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0))   \
+   - KERNEL_U_ADDR)
+
+static void
+fetch_inferior_register (regno, regaddr)
+     register int regno;
+     register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+  if (regno == PS_REGNUM)
+    {
+      union { int i; short s[2]; } ps_val;
+      int regval;
+      
+      ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+      regval = ps_val.s[0];
+      supply_register (regno, &regval);
+    }
+  else
+#endif /* not HPUX_VERSION_5 */
+    {
+      char buf[MAX_REGISTER_RAW_SIZE];
+      register int i;
+      
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       {
+         *(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
+         regaddr += sizeof (int);
+       }
+      supply_register (regno, buf);
+    }
+  return;
+}
+
+static void
+store_inferior_register_1 (regno, regaddr, value)
+     int regno;
+     unsigned int regaddr;
+     int value;
+{
+  errno = 0;
+  ptrace (PT_WUAREA, inferior_pid, regaddr, value);
+#if 0
+  /* HP-UX randomly sets errno to non-zero for regno == 25.
+     However, the value is correctly written, so ignore errno. */
+  if (errno != 0)
+    {
+      char string_buf[64];
+      
+      sprintf (string_buf, "writing register number %d", regno);
+      perror_with_name (string_buf);
+    }
+#endif
+  return;
+}
+
+static void
+store_inferior_register (regno, regaddr)
+     register int regno;
+     register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+  if (regno == PS_REGNUM)
+    {
+      union { int i; short s[2]; } ps_val;
+      
+      ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+      ps_val.s[0] = (read_register (regno));
+      store_inferior_register_1 (regno, regaddr, ps_val.i);
+    }
+  else
+#endif /* not HPUX_VERSION_5 */
+    {
+      char buf[MAX_REGISTER_RAW_SIZE];
+      register int i;
+      extern char registers[];
+      
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       {
+         store_inferior_register_1
+           (regno, regaddr,
+            (*(int *) &registers[(REGISTER_BYTE (regno)) + i]));
+         regaddr += sizeof (int);
+       }
+    }
+  return;
+}
+
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+  struct user u;
+  register int regno;
+  register unsigned int ar0_offset;
+  
+  ar0_offset = (INFERIOR_AR0 (u));
+  if (regno == -1)
+    {
+      for (regno = 0; (regno < FP0_REGNUM); regno++)
+       fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+      for (; (regno < NUM_REGS); regno++)
+       fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+    }
+  else
+    fetch_inferior_register (regno,
+                            (regno < FP0_REGNUM
+                             ? REGISTER_ADDR (ar0_offset, regno)
+                             : FP_REGISTER_ADDR (u, regno)));
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     register int regno;
+{
+  struct user u;
+  register unsigned int ar0_offset;
+  extern char registers[];
+
+  if (regno >= FP0_REGNUM)
+    {
+      store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+      return;
+    }
+  
+  ar0_offset = (INFERIOR_AR0 (u));
+  if (regno >= 0)
+    {
+      store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+      return;
+    }
+
+  for (regno = 0; (regno < FP0_REGNUM); regno++)
+    store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+  for (; (regno < NUM_REGS); regno++)
+    store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+  return;
+}
+
+\f
+/* Take the register values out of a core file and store
+   them where `read_register' will find them.  */
+
+#ifdef HPUX_VERSION_5
+#define e_PS e_regs[PS]
+#define e_PC e_regs[PC]
+#endif /* HPUX_VERSION_5 */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which)
+     char *core_reg_sect;
+     int core_reg_size;
+     int which;
+{
+  int val, regno;
+  struct user u;
+  struct exception_stack *pes = (struct exception_stack *) core_reg_sect;
+#define es (*pes)
+  char *buf;
+
+  if (which == 0) {
+    if (core_reg_size < 
+                 ((char *) &es.e_offset - (char *) &es.e_regs[R0]))
+         error ("Not enough registers in core file");
+    for (regno = 0; (regno < PS_REGNUM); regno++)
+      supply_register (regno, &es.e_regs[regno + R0]);
+    val = es.e_PS;
+    supply_register (regno++, &val);
+    supply_register (regno++, &es.e_PC);
+
+  } else if (which == 2) {
+
+    /* FIXME: This may not work if the float regs and control regs are
+       discontinuous.  */
+    for (regno = FP0_REGNUM, buf = core_reg_sect;
+        (regno < NUM_REGS);
+        buf += REGISTER_RAW_SIZE (regno), regno++)
+      {
+       supply_register (regno, buf);
+      }
+  }
+}
diff --git a/gdb/i386-pinsn.c b/gdb/i386-pinsn.c
new file mode 100644 (file)
index 0000000..50cf14b
--- /dev/null
@@ -0,0 +1,1834 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual.  Usually, there is a capital letter, followed
+ * by a small letter.  The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size.  Refer to 
+ * the Intel manual for details.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0
+#define Mp OP_E, 0             /* ? */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rw OP_rm, w_mode
+#define Rd OP_rm, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode      /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define ONE OP_ONE, 0
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, lptr
+#define Av OP_DIR, v_mode
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSSI, b_mode
+#define Xv OP_DSSI, v_mode
+#define Yb OP_ESDI, b_mode
+#define Yv OP_ESDI, v_mode
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
+int OP_J(), OP_SEG();
+int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
+int OP_D(), OP_T(), OP_rm();
+
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+#define eAX_reg 107
+#define eCX_reg 108
+#define eDX_reg 109
+#define eBX_reg 110
+#define eSP_reg 111
+#define eBP_reg 112
+#define eSI_reg 113
+#define eDI_reg 114
+
+#define lptr 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define GRP1b NULL, NULL, 0
+#define GRP1S NULL, NULL, 1
+#define GRP1Ss NULL, NULL, 2
+#define GRP2b NULL, NULL, 3
+#define GRP2S NULL, NULL, 4
+#define GRP2b_one NULL, NULL, 5
+#define GRP2S_one NULL, NULL, 6
+#define GRP2b_cl NULL, NULL, 7
+#define GRP2S_cl NULL, NULL, 8
+#define GRP3b NULL, NULL, 9
+#define GRP3S NULL, NULL, 10
+#define GRP4  NULL, NULL, 11
+#define GRP5  NULL, NULL, 12
+#define GRP6  NULL, NULL, 13
+#define GRP7 NULL, NULL, 14
+#define GRP8 NULL, NULL, 15
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE
+
+struct dis386 {
+  char *name;
+  int (*op1)();
+  int bytemode1;
+  int (*op2)();
+  int bytemode2;
+  int (*op3)();
+  int bytemode3;
+};
+
+struct dis386 dis386[] = {
+  /* 00 */
+  { "addb",    Eb, Gb },
+  { "addS",    Ev, Gv },
+  { "addb",    Gb, Eb },
+  { "addS",    Gv, Ev },
+  { "addb",    AL, Ib },
+  { "addS",    eAX, Iv },
+  { "pushl",   es },
+  { "popl",    es },
+  /* 08 */
+  { "orb",     Eb, Gb },
+  { "orS",     Ev, Gv },
+  { "orb",     Gb, Eb },
+  { "orS",     Gv, Ev },
+  { "orb",     AL, Ib },
+  { "orS",     eAX, Iv },
+  { "pushl",   cs },
+  { "(bad)" }, /* 0x0f extended opcode escape */
+  /* 10 */
+  { "adcb",    Eb, Gb },
+  { "adcS",    Ev, Gv },
+  { "adcb",    Gb, Eb },
+  { "adcS",    Gv, Ev },
+  { "adcb",    AL, Ib },
+  { "adcS",    eAX, Iv },
+  { "pushl",   ss },
+  { "popl",    ss },
+  /* 18 */
+  { "sbbb",    Eb, Gb },
+  { "sbbS",    Ev, Gv },
+  { "sbbb",    Gb, Eb },
+  { "sbbS",    Gv, Ev },
+  { "sbbb",    AL, Ib },
+  { "sbbS",    eAX, Iv },
+  { "pushl",   ds },
+  { "popl",    ds },
+  /* 20 */
+  { "andb",    Eb, Gb },
+  { "andS",    Ev, Gv },
+  { "andb",    Gb, Eb },
+  { "andS",    Gv, Ev },
+  { "andb",    AL, Ib },
+  { "andS",    eAX, Iv },
+  { "(bad)" },                 /* SEG ES prefix */
+  { "daa" },
+  /* 28 */
+  { "subb",    Eb, Gb },
+  { "subS",    Ev, Gv },
+  { "subb",    Gb, Eb },
+  { "subS",    Gv, Ev },
+  { "subb",    AL, Ib },
+  { "subS",    eAX, Iv },
+  { "(bad)" },                 /* SEG CS prefix */
+  { "das" },
+  /* 30 */
+  { "xorb",    Eb, Gb },
+  { "xorS",    Ev, Gv },
+  { "xorb",    Gb, Eb },
+  { "xorS",    Gv, Ev },
+  { "xorb",    AL, Ib },
+  { "xorS",    eAX, Iv },
+  { "(bad)" },                 /* SEG SS prefix */
+  { "aaa" },
+  /* 38 */
+  { "cmpb",    Eb, Gb },
+  { "cmpS",    Ev, Gv },
+  { "cmpb",    Gb, Eb },
+  { "cmpS",    Gv, Ev },
+  { "cmpb",    AL, Ib },
+  { "cmpS",    eAX, Iv },
+  { "(bad)" },                 /* SEG DS prefix */
+  { "aas" },
+  /* 40 */
+  { "incS",    eAX },
+  { "incS",    eCX },
+  { "incS",    eDX },
+  { "incS",    eBX },
+  { "incS",    eSP },
+  { "incS",    eBP },
+  { "incS",    eSI },
+  { "incS",    eDI },
+  /* 48 */
+  { "decS",    eAX },
+  { "decS",    eCX },
+  { "decS",    eDX },
+  { "decS",    eBX },
+  { "decS",    eSP },
+  { "decS",    eBP },
+  { "decS",    eSI },
+  { "decS",    eDI },
+  /* 50 */
+  { "pushS",   eAX },
+  { "pushS",   eCX },
+  { "pushS",   eDX },
+  { "pushS",   eBX },
+  { "pushS",   eSP },
+  { "pushS",   eBP },
+  { "pushS",   eSI },
+  { "pushS",   eDI },
+  /* 58 */
+  { "popS",    eAX },
+  { "popS",    eCX },
+  { "popS",    eDX },
+  { "popS",    eBX },
+  { "popS",    eSP },
+  { "popS",    eBP },
+  { "popS",    eSI },
+  { "popS",    eDI },
+  /* 60 */
+  { "pusha" },
+  { "popa" },
+  { "boundS",  Gv, Ma },
+  { "arpl",    Ew, Gw },
+  { "(bad)" },                 /* seg fs */
+  { "(bad)" },                 /* seg gs */
+  { "(bad)" },                 /* op size prefix */
+  { "(bad)" },                 /* adr size prefix */
+  /* 68 */
+  { "pushS",   Iv },           /* 386 book wrong */
+  { "imulS",   Gv, Ev, Iv },
+  { "pushl",   sIb },          /* push of byte really pushes 4 bytes */
+  { "imulS",   Gv, Ev, Ib },
+  { "insb",    Yb, indirDX },
+  { "insS",    Yv, indirDX },
+  { "outsb",   indirDX, Xb },
+  { "outsS",   indirDX, Xv },
+  /* 70 */
+  { "jo",              Jb },
+  { "jno",     Jb },
+  { "jb",              Jb },
+  { "jae",     Jb },
+  { "je",              Jb },
+  { "jne",     Jb },
+  { "jbe",     Jb },
+  { "ja",              Jb },
+  /* 78 */
+  { "js",              Jb },
+  { "jns",     Jb },
+  { "jp",              Jb },
+  { "jnp",     Jb },
+  { "jl",              Jb },
+  { "jnl",     Jb },
+  { "jle",     Jb },
+  { "jg",              Jb },
+  /* 80 */
+  { GRP1b },
+  { GRP1S },
+  { "(bad)" },
+  { GRP1Ss },
+  { "testb",   Eb, Gb },
+  { "testS",   Ev, Gv },
+  { "xchgb",   Eb, Gb },
+  { "xchgS",   Ev, Gv },
+  /* 88 */
+  { "movb",    Eb, Gb },
+  { "movS",    Ev, Gv },
+  { "movb",    Gb, Eb },
+  { "movS",    Gv, Ev },
+  { "movw",    Ew, Sw },
+  { "leaS",    Gv, M },
+  { "movw",    Sw, Ew },
+  { "popS",    Ev },
+  /* 90 */
+  { "nop" },
+  { "xchgS",   eCX, eAX },
+  { "xchgS",   eDX, eAX },
+  { "xchgS",   eBX, eAX },
+  { "xchgS",   eSP, eAX },
+  { "xchgS",   eBP, eAX },
+  { "xchgS",   eSI, eAX },
+  { "xchgS",   eDI, eAX },
+  /* 98 */
+  { "cwtl" },
+  { "cltd" },
+  { "lcall",   Ap },
+  { "(bad)" },         /* fwait */
+  { "pushf" },
+  { "popf" },
+  { "sahf" },
+  { "lahf" },
+  /* a0 */
+  { "movb",    AL, Ob },
+  { "movS",    eAX, Ov },
+  { "movb",    Ob, AL },
+  { "movS",    Ov, eAX },
+  { "movsb",   Yb, Xb },
+  { "movsS",   Yv, Xv },
+  { "cmpsb",   Yb, Xb },
+  { "cmpsS",   Yv, Xv },
+  /* a8 */
+  { "testb",   AL, Ib },
+  { "testS",   eAX, Iv },
+  { "stosb",   Yb, AL },
+  { "stosS",   Yv, eAX },
+  { "lodsb",   AL, Xb },
+  { "lodsS",   eAX, Xv },
+  { "scasb",   AL, Xb },
+  { "scasS",   eAX, Xv },
+  /* b0 */
+  { "movb",    AL, Ib },
+  { "movb",    CL, Ib },
+  { "movb",    DL, Ib },
+  { "movb",    BL, Ib },
+  { "movb",    AH, Ib },
+  { "movb",    CH, Ib },
+  { "movb",    DH, Ib },
+  { "movb",    BH, Ib },
+  /* b8 */
+  { "movS",    eAX, Iv },
+  { "movS",    eCX, Iv },
+  { "movS",    eDX, Iv },
+  { "movS",    eBX, Iv },
+  { "movS",    eSP, Iv },
+  { "movS",    eBP, Iv },
+  { "movS",    eSI, Iv },
+  { "movS",    eDI, Iv },
+  /* c0 */
+  { GRP2b },
+  { GRP2S },
+  { "ret",     Iw },
+  { "ret" },
+  { "lesS",    Gv, Mp },
+  { "ldsS",    Gv, Mp },
+  { "movb",    Eb, Ib },
+  { "movS",    Ev, Iv },
+  /* c8 */
+  { "enter",   Iw, Ib },
+  { "leave" },
+  { "lret",    Iw },
+  { "lret" },
+  { "int3" },
+  { "int",     Ib },
+  { "into" },
+  { "iret" },
+  /* d0 */
+  { GRP2b_one },
+  { GRP2S_one },
+  { GRP2b_cl },
+  { GRP2S_cl },
+  { "aam",     Ib },
+  { "aad",     Ib },
+  { "(bad)" },
+  { "xlat" },
+  /* d8 */
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  /* e0 */
+  { "loopne",  Jb },
+  { "loope",   Jb },
+  { "loop",    Jb },
+  { "jCcxz",   Jb },
+  { "inb",     AL, Ib },
+  { "inS",     eAX, Ib },
+  { "outb",    Ib, AL },
+  { "outS",    Ib, eAX },
+  /* e8 */
+  { "call",    Av },
+  { "jmp",     Jv },
+  { "ljmp",    Ap },
+  { "jmp",     Jb },
+  { "inb",     AL, indirDX },
+  { "inS",     eAX, indirDX },
+  { "outb",    indirDX, AL },
+  { "outS",    indirDX, eAX },
+  /* f0 */
+  { "(bad)" },                 /* lock prefix */
+  { "(bad)" },
+  { "(bad)" },                 /* repne */
+  { "(bad)" },                 /* repz */
+  { "hlt" },
+  { "cmc" },
+  { GRP3b },
+  { GRP3S },
+  /* f8 */
+  { "clc" },
+  { "stc" },
+  { "cli" },
+  { "sti" },
+  { "cld" },
+  { "std" },
+  { GRP4 },
+  { GRP5 },
+};
+
+struct dis386 dis386_twobyte[] = {
+  /* 00 */
+  { GRP6 },
+  { GRP7 },
+  { "larS", Gv, Ew },
+  { "lslS", Gv, Ew },  
+  { "(bad)" },
+  { "(bad)" },
+  { "clts" },
+  { "(bad)" },  
+  /* 08 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 10 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 18 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 20 */
+  /* these are all backward in appendix A of the intel book */
+  { "movl", Rd, Cd },
+  { "movl", Rd, Dd },
+  { "movl", Cd, Rd },
+  { "movl", Dd, Rd },  
+  { "movl", Rd, Td },
+  { "(bad)" },
+  { "movl", Td, Rd },
+  { "(bad)" },  
+  /* 28 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 30 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 38 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 40 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 48 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 50 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 58 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 60 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 68 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 70 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 78 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* 80 */
+  { "jo", Jv },
+  { "jno", Jv },
+  { "jb", Jv },
+  { "jae", Jv },  
+  { "je", Jv },
+  { "jne", Jv },
+  { "jbe", Jv },
+  { "ja", Jv },  
+  /* 88 */
+  { "js", Jv },
+  { "jns", Jv },
+  { "jp", Jv },
+  { "jnp", Jv },  
+  { "jl", Jv },
+  { "jge", Jv },
+  { "jle", Jv },
+  { "jg", Jv },  
+  /* 90 */
+  { "seto", Eb },
+  { "setno", Eb },
+  { "setb", Eb },
+  { "setae", Eb },
+  { "sete", Eb },
+  { "setne", Eb },
+  { "setbe", Eb },
+  { "seta", Eb },
+  /* 98 */
+  { "sets", Eb },
+  { "setns", Eb },
+  { "setp", Eb },
+  { "setnp", Eb },
+  { "setl", Eb },
+  { "setge", Eb },
+  { "setle", Eb },
+  { "setg", Eb },  
+  /* a0 */
+  { "pushl", fs },
+  { "popl", fs },
+  { "(bad)" },
+  { "btS", Ev, Gv },  
+  { "shldS", Ev, Gv, Ib },
+  { "shldS", Ev, Gv, CL },
+  { "(bad)" },
+  { "(bad)" },  
+  /* a8 */
+  { "pushl", gs },
+  { "popl", gs },
+  { "(bad)" },
+  { "btsS", Ev, Gv },  
+  { "shrdS", Ev, Gv, Ib },
+  { "shrdS", Ev, Gv, CL },
+  { "(bad)" },
+  { "imulS", Gv, Ev },  
+  /* b0 */
+  { "(bad)" },
+  { "(bad)" },
+  { "lssS", Gv, Mp },  /* 386 lists only Mp */
+  { "btrS", Ev, Gv },  
+  { "lfsS", Gv, Mp },  /* 386 lists only Mp */
+  { "lgsS", Gv, Mp },  /* 386 lists only Mp */
+  { "movzbS", Gv, Eb },
+  { "movzwS", Gv, Ew },  
+  /* b8 */
+  { "(bad)" },
+  { "(bad)" },
+  { GRP8 },
+  { "btcS", Ev, Gv },  
+  { "bsfS", Gv, Ev },
+  { "bsrS", Gv, Ev },
+  { "movsbS", Gv, Eb },
+  { "movswS", Gv, Ew },  
+  /* c0 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* c8 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* d0 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* d8 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* e0 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* e8 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* f0 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  /* f8 */
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *codep;
+static int mod;
+static int rm;
+static int reg;
+static void oappend ();
+
+static char *names32[]={
+  "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static char *names16[] = {
+  "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static char *names8[] = {
+  "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static char *names_seg[] = {
+  "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+
+struct dis386 grps[][8] = {
+  /* GRP1b */
+  {
+    { "addb",  Eb, Ib },
+    { "orb",   Eb, Ib },
+    { "adcb",  Eb, Ib },
+    { "sbbb",  Eb, Ib },
+    { "andb",  Eb, Ib },
+    { "subb",  Eb, Ib },
+    { "xorb",  Eb, Ib },
+    { "cmpb",  Eb, Ib }
+  },
+  /* GRP1S */
+  {
+    { "addS",  Ev, Iv },
+    { "orS",   Ev, Iv },
+    { "adcS",  Ev, Iv },
+    { "sbbS",  Ev, Iv },
+    { "andS",  Ev, Iv },
+    { "subS",  Ev, Iv },
+    { "xorS",  Ev, Iv },
+    { "cmpS",  Ev, Iv }
+  },
+  /* GRP1Ss */
+  {
+    { "addS",  Ev, sIb },
+    { "orS",   Ev, sIb },
+    { "adcS",  Ev, sIb },
+    { "sbbS",  Ev, sIb },
+    { "andS",  Ev, sIb },
+    { "subS",  Ev, sIb },
+    { "xorS",  Ev, sIb },
+    { "cmpS",  Ev, sIb }
+  },
+  /* GRP2b */
+  {
+    { "rolb",  Eb, Ib },
+    { "rorb",  Eb, Ib },
+    { "rclb",  Eb, Ib },
+    { "rcrb",  Eb, Ib },
+    { "shlb",  Eb, Ib },
+    { "shrb",  Eb, Ib },
+    { "(bad)" },
+    { "sarb",  Eb, Ib },
+  },
+  /* GRP2S */
+  {
+    { "rolS",  Ev, Ib },
+    { "rorS",  Ev, Ib },
+    { "rclS",  Ev, Ib },
+    { "rcrS",  Ev, Ib },
+    { "shlS",  Ev, Ib },
+    { "shrS",  Ev, Ib },
+    { "(bad)" },
+    { "sarS",  Ev, Ib },
+  },
+  /* GRP2b_one */
+  {
+    { "rolb",  Eb },
+    { "rorb",  Eb },
+    { "rclb",  Eb },
+    { "rcrb",  Eb },
+    { "shlb",  Eb },
+    { "shrb",  Eb },
+    { "(bad)" },
+    { "sarb",  Eb },
+  },
+  /* GRP2S_one */
+  {
+    { "rolS",  Ev },
+    { "rorS",  Ev },
+    { "rclS",  Ev },
+    { "rcrS",  Ev },
+    { "shlS",  Ev },
+    { "shrS",  Ev },
+    { "(bad)" },
+    { "sarS",  Ev },
+  },
+  /* GRP2b_cl */
+  {
+    { "rolb",  Eb, CL },
+    { "rorb",  Eb, CL },
+    { "rclb",  Eb, CL },
+    { "rcrb",  Eb, CL },
+    { "shlb",  Eb, CL },
+    { "shrb",  Eb, CL },
+    { "(bad)" },
+    { "sarb",  Eb, CL },
+  },
+  /* GRP2S_cl */
+  {
+    { "rolS",  Ev, CL },
+    { "rorS",  Ev, CL },
+    { "rclS",  Ev, CL },
+    { "rcrS",  Ev, CL },
+    { "shlS",  Ev, CL },
+    { "shrS",  Ev, CL },
+    { "(bad)" },
+    { "sarS",  Ev, CL }
+  },
+  /* GRP3b */
+  {
+    { "testb", Eb, Ib },
+    { "(bad)", Eb },
+    { "notb",  Eb },
+    { "negb",  Eb },
+    { "mulb",  AL, Eb },
+    { "imulb", AL, Eb },
+    { "divb",  AL, Eb },
+    { "idivb", AL, Eb }
+  },
+  /* GRP3S */
+  {
+    { "testS", Ev, Iv },
+    { "(bad)" },
+    { "notS",  Ev },
+    { "negS",  Ev },
+    { "mulS",  eAX, Ev },
+    { "imulS", eAX, Ev },
+    { "divS",  eAX, Ev },
+    { "idivS", eAX, Ev },
+  },
+  /* GRP4 */
+  {
+    { "incb", Eb },
+    { "decb", Eb },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* GRP5 */
+  {
+    { "incS",  Ev },
+    { "decS",  Ev },
+    { "call",  indirEv },
+    { "lcall", indirEv },
+    { "jmp",   indirEv },
+    { "ljmp",  indirEv },
+    { "pushS", Ev },
+    { "(bad)" },
+  },
+  /* GRP6 */
+  {
+    { "sldt",  Ew },
+    { "str",   Ew },
+    { "lldt",  Ew },
+    { "ltr",   Ew },
+    { "verr",  Ew },
+    { "verw",  Ew },
+    { "(bad)" },
+    { "(bad)" }
+  },
+  /* GRP7 */
+  {
+    { "sgdt", Ew },
+    { "sidt", Ew },
+    { "lgdt", Ew },
+    { "lidt", Ew },
+    { "smsw", Ew },
+    { "(bad)" },
+    { "lmsw", Ew },
+    { "(bad)" },
+  },
+  /* GRP8 */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "btS",   Ev, Ib },
+    { "btsS",  Ev, Ib },
+    { "btrS",  Ev, Ib },
+    { "btcS",  Ev, Ib },
+  }
+};
+
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADR 0x400
+#define PREFIX_FWAIT 0x800
+
+static int prefixes;
+
+ckprefix ()
+{
+  prefixes = 0;
+  while (1)
+    {
+      switch (*codep)
+       {
+       case 0xf3:
+         prefixes |= PREFIX_REPZ;
+         break;
+       case 0xf2:
+         prefixes |= PREFIX_REPNZ;
+         break;
+       case 0xf0:
+         prefixes |= PREFIX_LOCK;
+         break;
+       case 0x2e:
+         prefixes |= PREFIX_CS;
+         break;
+       case 0x36:
+         prefixes |= PREFIX_SS;
+         break;
+       case 0x3e:
+         prefixes |= PREFIX_DS;
+         break;
+       case 0x26:
+         prefixes |= PREFIX_ES;
+         break;
+       case 0x64:
+         prefixes |= PREFIX_FS;
+         break;
+       case 0x65:
+         prefixes |= PREFIX_GS;
+         break;
+       case 0x66:
+         prefixes |= PREFIX_DATA;
+         break;
+       case 0x67:
+         prefixes |= PREFIX_ADR;
+         break;
+       case 0x9b:
+         prefixes |= PREFIX_FWAIT;
+         break;
+       default:
+         return;
+       }
+      codep++;
+    }
+}
+
+static int dflag;
+static int aflag;              
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_address[3], op_ad, op_index[3];
+static int start_pc;
+extern void fputs_filtered ();
+
+/*
+ * disassemble the first instruction in 'inbuf'.  You have to make
+ *   sure all of the bytes of the instruction are filled in.
+ *   On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ *   (see topic "Redundant prefixes" in the "Differences from 8086"
+ *   section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ *   be used to print the target address if this is a relative jump or call
+ * 'outbuf' gets filled in with the disassembled instruction.  it should
+ *   be long enough to hold the longest disassembled instruction.
+ *   100 bytes is certainly enough, unless symbol printing is added later
+ * The function returns the length of this instruction in bytes.
+ */
+i386dis (pc, inbuf, stream)
+     int pc;
+     unsigned char *inbuf;
+     FILE *stream;
+{
+  struct dis386 *dp;
+  char *p;
+  int i;
+  int enter_instruction;
+  char *first, *second, *third;
+  int needcomma;
+  
+  obuf[0] = 0;
+  op1out[0] = 0;
+  op2out[0] = 0;
+  op3out[0] = 0;
+
+  op_index[0] = op_index[1] = op_index[2] = -1;
+  
+  start_pc = pc;
+  start_codep = inbuf;
+  codep = inbuf;
+  
+  ckprefix ();
+  
+  if (*codep == 0xc8)
+    enter_instruction = 1;
+  else
+    enter_instruction = 0;
+  
+  obufp = obuf;
+  
+  if (prefixes & PREFIX_REPZ)
+    oappend ("repz ");
+  if (prefixes & PREFIX_REPNZ)
+    oappend ("repnz ");
+  if (prefixes & PREFIX_LOCK)
+    oappend ("lock ");
+  
+  if ((prefixes & PREFIX_FWAIT)
+      && ((*codep < 0xd8) || (*codep > 0xdf)))
+    {
+      /* fwait not followed by floating point instruction */
+      fputs_filtered ("fwait", stream);
+      return (1);
+    }
+  
+  /* these would be initialized to 0 if disassembling for 8086 or 286 */
+  dflag = 1;
+  aflag = 1;
+  
+  if (prefixes & PREFIX_DATA)
+    dflag ^= 1;
+  
+  if (prefixes & PREFIX_ADR)
+    {
+      aflag ^= 1;
+      oappend ("addr16 ");
+    }
+  
+  if (*codep == 0x0f)
+    dp = &dis386_twobyte[*++codep];
+  else
+    dp = &dis386[*codep];
+  codep++;
+  mod = (*codep >> 6) & 3;
+  reg = (*codep >> 3) & 7;
+  rm = *codep & 7;
+  
+  if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+    {
+      dofloat ();
+    }
+  else
+    {
+      if (dp->name == NULL)
+       dp = &grps[dp->bytemode1][reg];
+      
+      putop (dp->name);
+      
+      obufp = op1out;
+      op_ad = 2;
+      if (dp->op1)
+       (*dp->op1)(dp->bytemode1);
+      
+      obufp = op2out;
+      op_ad = 1;
+      if (dp->op2)
+       (*dp->op2)(dp->bytemode2);
+      
+      obufp = op3out;
+      op_ad = 0;
+      if (dp->op3)
+       (*dp->op3)(dp->bytemode3);
+    }
+  
+  obufp = obuf + strlen (obuf);
+  for (i = strlen (obuf); i < 6; i++)
+    oappend (" ");
+  oappend (" ");
+  fputs_filtered (obuf, stream);
+  
+  /* enter instruction is printed with operands in the
+   * same order as the intel book; everything else
+   * is printed in reverse order 
+   */
+  if (enter_instruction)
+    {
+      first = op1out;
+      second = op2out;
+      third = op3out;
+      op_ad = op_index[0];
+      op_index[0] = op_index[2];
+      op_index[2] = op_ad;
+    }
+  else
+    {
+      first = op3out;
+      second = op2out;
+      third = op1out;
+    }
+  needcomma = 0;
+  if (*first)
+    {
+      if (op_index[0] != -1)
+       print_address (op_address[op_index[0]], stream);
+      else
+       fputs_filtered (first, stream);
+      needcomma = 1;
+    }
+  if (*second)
+    {
+      if (needcomma)
+       fputs_filtered (",", stream);
+      if (op_index[1] != -1)
+       print_address (op_address[op_index[1]], stream);
+      else
+       fputs_filtered (second, stream);
+      needcomma = 1;
+    }
+  if (*third)
+    {
+      if (needcomma)
+       fputs_filtered (",", stream);
+      if (op_index[2] != -1)
+       print_address (op_address[op_index[2]], stream);
+      else
+       fputs_filtered (third, stream);
+    }
+  return (codep - inbuf);
+}
+
+char *float_mem[] = {
+  /* d8 */
+  "fadds",
+  "fmuls",
+  "fcoms",
+  "fcomps",
+  "fsubs",
+  "fsubrs",
+  "fdivs",
+  "fdivrs",
+  /*  d9 */
+  "flds",
+  "(bad)",
+  "fsts",
+  "fstps",
+  "fldenv",
+  "fldcw",
+  "fNstenv",
+  "fNstcw",
+  /* da */
+  "fiaddl",
+  "fimull",
+  "ficoml",
+  "ficompl",
+  "fisubl",
+  "fisubrl",
+  "fidivl",
+  "fidivrl",
+  /* db */
+  "fildl",
+  "(bad)",
+  "fistl",
+  "fistpl",
+  "(bad)",
+  "fldt",
+  "(bad)",
+  "fstpt",
+  /* dc */
+  "faddl",
+  "fmull",
+  "fcoml",
+  "fcompl",
+  "fsubl",
+  "fsubrl",
+  "fdivl",
+  "fdivrl",
+  /* dd */
+  "fldl",
+  "(bad)",
+  "fstl",
+  "fstpl",
+  "frstor",
+  "(bad)",
+  "fNsave",
+  "fNstsw",
+  /* de */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* df */
+  "fild",
+  "(bad)",
+  "fist",
+  "fistp",
+  "fbld",
+  "fildll",
+  "fbstp",
+  "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+int OP_ST(), OP_STi();
+
+#define FGRPd9_2 NULL, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1
+#define FGRPd9_5 NULL, NULL, 2
+#define FGRPd9_6 NULL, NULL, 3
+#define FGRPd9_7 NULL, NULL, 4
+#define FGRPda_5 NULL, NULL, 5
+#define FGRPdb_4 NULL, NULL, 6
+#define FGRPde_3 NULL, NULL, 7
+#define FGRPdf_4 NULL, NULL, 8
+
+struct dis386 float_reg[][8] = {
+  /* d8 */
+  {
+    { "fadd",  ST, STi },
+    { "fmul",  ST, STi },
+    { "fcom",  STi },
+    { "fcomp", STi },
+    { "fsub",  ST, STi },
+    { "fsubr", ST, STi },
+    { "fdiv",  ST, STi },
+    { "fdivr", ST, STi },
+  },
+  /* d9 */
+  {
+    { "fld",   STi },
+    { "fxch",  STi },
+    { FGRPd9_2 },
+    { "(bad)" },
+    { FGRPd9_4 },
+    { FGRPd9_5 },
+    { FGRPd9_6 },
+    { FGRPd9_7 },
+  },
+  /* da */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { FGRPda_5 },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* db */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { FGRPdb_4 },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* dc */
+  {
+    { "fadd",  STi, ST },
+    { "fmul",  STi, ST },
+    { "(bad)" },
+    { "(bad)" },
+    { "fsub",  STi, ST },
+    { "fsubr", STi, ST },
+    { "fdiv",  STi, ST },
+    { "fdivr", STi, ST },
+  },
+  /* dd */
+  {
+    { "ffree", STi },
+    { "(bad)" },
+    { "fst",   STi },
+    { "fstp",  STi },
+    { "fucom", STi },
+    { "fucomp",        STi },
+    { "(bad)" },
+    { "(bad)" },
+  },
+  /* de */
+  {
+    { "faddp", STi, ST },
+    { "fmulp", STi, ST },
+    { "(bad)" },
+    { FGRPde_3 },
+    { "fsubp", STi, ST },
+    { "fsubrp",        STi, ST },
+    { "fdivp", STi, ST },
+    { "fdivrp",        STi, ST },
+  },
+  /* df */
+  {
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+    { FGRPdf_4 },
+    { "(bad)" },
+    { "(bad)" },
+    { "(bad)" },
+  },
+};
+
+
+char *fgrps[][8] = {
+  /* d9_2  0 */
+  {
+    "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* d9_4  1 */
+  {
+    "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+  },
+
+  /* d9_5  2 */
+  {
+    "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+  },
+
+  /* d9_6  3 */
+  {
+    "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+  },
+
+  /* d9_7  4 */
+  {
+    "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+  },
+
+  /* da_5  5 */
+  {
+    "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* db_4  6 */
+  {
+    "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+    "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+  },
+
+  /* de_3  7 */
+  {
+    "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* df_4  8 */
+  {
+    "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+};
+
+
+dofloat ()
+{
+  struct dis386 *dp;
+  unsigned char floatop;
+  
+  floatop = codep[-1];
+  
+  if (mod != 3)
+    {
+      putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+      obufp = op1out;
+      OP_E (v_mode);
+      return;
+    }
+  codep++;
+  
+  dp = &float_reg[floatop - 0xd8][reg];
+  if (dp->name == NULL)
+    {
+      putop (fgrps[dp->bytemode1][rm]);
+      /* instruction fnstsw is only one with strange arg */
+      if (floatop == 0xdf && *codep == 0xe0)
+       strcpy (op1out, "%eax");
+    }
+  else
+    {
+      putop (dp->name);
+      obufp = op1out;
+      if (dp->op1)
+       (*dp->op1)(dp->bytemode1);
+      obufp = op2out;
+      if (dp->op2)
+       (*dp->op2)(dp->bytemode2);
+    }
+}
+
+/* ARGSUSED */
+OP_ST (ignore)
+{
+  oappend ("%st");
+}
+
+/* ARGSUSED */
+OP_STi (ignore)
+{
+  sprintf (scratchbuf, "%%st(%d)", rm);
+  oappend (scratchbuf);
+}
+
+
+/* capital letters in template are macros */
+putop (template)
+     char *template;
+{
+  char *p;
+  
+  for (p = template; *p; p++)
+    {
+      switch (*p)
+       {
+       default:
+         *obufp++ = *p;
+         break;
+       case 'C':               /* For jcxz/jecxz */
+         if (aflag == 0)
+           *obufp++ = 'e';
+         break;
+       case 'N':
+         if ((prefixes & PREFIX_FWAIT) == 0)
+           *obufp++ = 'n';
+         break;
+       case 'S':
+         /* operand size flag */
+         if (dflag)
+           *obufp++ = 'l';
+         else
+           *obufp++ = 'w';
+         break;
+       }
+    }
+  *obufp = 0;
+}
+
+static void
+oappend (s)
+char *s;
+{
+  strcpy (obufp, s);
+  obufp += strlen (s);
+  *obufp = 0;
+}
+
+append_prefix ()
+{
+  if (prefixes & PREFIX_CS)
+    oappend ("%cs:");
+  if (prefixes & PREFIX_DS)
+    oappend ("%ds:");
+  if (prefixes & PREFIX_SS)
+    oappend ("%ss:");
+  if (prefixes & PREFIX_ES)
+    oappend ("%es:");
+  if (prefixes & PREFIX_FS)
+    oappend ("%fs:");
+  if (prefixes & PREFIX_GS)
+    oappend ("%gs:");
+}
+
+OP_indirE (bytemode)
+{
+  oappend ("*");
+  OP_E (bytemode);
+}
+
+OP_E (bytemode)
+{
+  int disp;
+  int havesib;
+  int didoutput = 0;
+  int base;
+  int index;
+  int scale;
+  int havebase;
+  
+  /* skip mod/rm byte */
+  codep++;
+  
+  havesib = 0;
+  havebase = 0;
+  disp = 0;
+  
+  if (mod == 3)
+    {
+      switch (bytemode)
+       {
+       case b_mode:
+         oappend (names8[rm]);
+         break;
+       case w_mode:
+         oappend (names16[rm]);
+         break;
+       case v_mode:
+         if (dflag)
+           oappend (names32[rm]);
+         else
+           oappend (names16[rm]);
+         break;
+       default:
+         oappend ("<bad dis table>");
+         break;
+       }
+      return;
+    }
+  
+  append_prefix ();
+  if (rm == 4)
+    {
+      havesib = 1;
+      havebase = 1;
+      scale = (*codep >> 6) & 3;
+      index = (*codep >> 3) & 7;
+      base = *codep & 7;
+      codep++;
+    }
+  
+  switch (mod)
+    {
+    case 0:
+      switch (rm)
+       {
+       case 4:
+         /* implies havesib and havebase */
+         if (base == 5) {
+           havebase = 0;
+           disp = get32 ();
+         }
+         break;
+       case 5:
+         disp = get32 ();
+         break;
+       default:
+         havebase = 1;
+         base = rm;
+         break;
+       }
+      break;
+    case 1:
+      disp = *(char *)codep++;
+      if (rm != 4)
+       {
+         havebase = 1;
+         base = rm;
+       }
+      break;
+    case 2:
+      disp = get32 ();
+      if (rm != 4)
+       {
+         havebase = 1;
+         base = rm;
+       }
+      break;
+    }
+  
+  if (mod != 0 || rm == 5 || (havesib && base == 5))
+    {
+      sprintf (scratchbuf, "%d", disp);
+      oappend (scratchbuf);
+    }
+  
+  if (havebase || havesib) 
+    {
+      oappend ("(");
+      if (havebase)
+       oappend (names32[base]);
+      if (havesib) 
+       {
+         if (index != 4) 
+           {
+             sprintf (scratchbuf, ",%s", names32[index]);
+             oappend (scratchbuf);
+           }
+         sprintf (scratchbuf, ",%d", 1 << scale);
+         oappend (scratchbuf);
+       }
+      oappend (")");
+    }
+}
+
+OP_G (bytemode)
+{
+  switch (bytemode) 
+    {
+    case b_mode:
+      oappend (names8[reg]);
+      break;
+    case w_mode:
+      oappend (names16[reg]);
+      break;
+    case d_mode:
+      oappend (names32[reg]);
+      break;
+    case v_mode:
+      if (dflag)
+       oappend (names32[reg]);
+      else
+       oappend (names16[reg]);
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      break;
+    }
+}
+
+get32 ()
+{
+  int x = 0;
+  
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  x |= (*codep++ & 0xff) << 16;
+  x |= (*codep++ & 0xff) << 24;
+  return (x);
+}
+
+get16 ()
+{
+  int x = 0;
+  
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  return (x);
+}
+
+set_op (op)
+int op;
+{
+  op_index[op_ad] = op_ad;
+  op_address[op_ad] = op;
+}
+
+OP_REG (code)
+{
+  char *s;
+  
+  switch (code) 
+    {
+    case indir_dx_reg: s = "(%dx)"; break;
+       case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+       case sp_reg: case bp_reg: case si_reg: case di_reg:
+               s = names16[code - ax_reg];
+               break;
+       case es_reg: case ss_reg: case cs_reg:
+       case ds_reg: case fs_reg: case gs_reg:
+               s = names_seg[code - es_reg];
+               break;
+       case al_reg: case ah_reg: case cl_reg: case ch_reg:
+       case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+               s = names8[code - al_reg];
+               break;
+       case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+       case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+      if (dflag)
+       s = names32[code - eAX_reg];
+      else
+       s = names16[code - eAX_reg];
+      break;
+    default:
+      s = "<internal disassembler error>";
+      break;
+    }
+  oappend (s);
+}
+
+OP_I (bytemode)
+{
+  int op;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      op = *codep++ & 0xff;
+      break;
+    case v_mode:
+      if (dflag)
+       op = get32 ();
+      else
+       op = get16 ();
+      break;
+    case w_mode:
+      op = get16 ();
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return;
+    }
+  sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+}
+
+OP_sI (bytemode)
+{
+  int op;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      op = *(char *)codep++;
+      break;
+    case v_mode:
+      if (dflag)
+       op = get32 ();
+      else
+       op = (short)get16();
+      break;
+    case w_mode:
+      op = (short)get16 ();
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return;
+    }
+  sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+}
+
+OP_J (bytemode)
+{
+  int disp;
+  int mask = -1;
+  
+  switch (bytemode) 
+    {
+    case b_mode:
+      disp = *(char *)codep++;
+      break;
+    case v_mode:
+      if (dflag)
+       disp = get32 ();
+      else
+       {
+         disp = (short)get16 ();
+         /* for some reason, a data16 prefix on a jump instruction
+            means that the pc is masked to 16 bits after the
+            displacement is added!  */
+         mask = 0xffff;
+       }
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      return;
+    }
+  disp = (start_pc + codep - start_codep + disp) & mask;
+  set_op (disp);
+  sprintf (scratchbuf, "0x%x", disp);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_SEG (dummy)
+{
+  static char *sreg[] = {
+    "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+  };
+
+  oappend (sreg[reg]);
+}
+
+OP_DIR (size)
+{
+  int seg, offset;
+  
+  switch (size) 
+    {
+    case lptr:
+      if (aflag) 
+       {
+         offset = get32 ();
+         seg = get16 ();
+       } 
+      else 
+       {
+         offset = get16 ();
+         seg = get16 ();
+       }
+      sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+      oappend (scratchbuf);
+      break;
+    case v_mode:
+      if (aflag)
+       offset = get32 ();
+      else
+       offset = (short)get16 ();
+      
+      offset = start_pc + codep - start_codep + offset;
+      set_op (offset);
+      sprintf (scratchbuf, "0x%x", offset);
+      oappend (scratchbuf);
+      break;
+    default:
+      oappend ("<internal disassembler error>");
+      break;
+    }
+}
+
+/* ARGSUSED */
+OP_OFF (bytemode)
+{
+  int off;
+  
+  if (aflag)
+    off = get32 ();
+  else
+    off = get16 ();
+  
+  sprintf (scratchbuf, "0x%x", off);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_ESDI (dummy)
+{
+  oappend ("%es:(");
+  oappend (aflag ? "%edi" : "%di");
+  oappend (")");
+}
+
+/* ARGSUSED */
+OP_DSSI (dummy)
+{
+  oappend ("%ds:(");
+  oappend (aflag ? "%esi" : "%si");
+  oappend (")");
+}
+
+/* ARGSUSED */
+OP_ONE (dummy)
+{
+  oappend ("1");
+}
+
+/* ARGSUSED */
+OP_C (dummy)
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%cr%d", reg);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_D (dummy)
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%db%d", reg);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_T (dummy)
+{
+  codep++; /* skip mod/rm */
+  sprintf (scratchbuf, "%%tr%d", reg);
+  oappend (scratchbuf);
+}
+
+OP_rm (bytemode)
+{
+  switch (bytemode) 
+    {
+    case d_mode:
+      oappend (names32[rm]);
+      break;
+    case w_mode:
+      oappend (names16[rm]);
+      break;
+    }
+}
+       
+/* GDB interface */
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#define MAXLEN 20
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  unsigned char buffer[MAXLEN];
+  
+  read_memory (memaddr, buffer, MAXLEN);
+  
+  return (i386dis ((int)memaddr, buffer, stream));
+}
+
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
new file mode 100644 (file)
index 0000000..d621fa3
--- /dev/null
@@ -0,0 +1,494 @@
+/* Intel 386 stuff.
+   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#ifndef N_SET_MAGIC
+#ifdef COFF_FORMAT
+#define N_SET_MAGIC(exec, val) ((exec).magic = (val))
+#else
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+#endif
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* I don't know whether this is right for cross-debugging even if you
+   do somehow manage to get the right include file.  */
+#if defined (USE_MACHINE_REG_H)
+#include <machine/reg.h>
+#else
+#include <sys/reg.h>
+#endif
+
+/* helper functions for m-i386.h */
+
+/* stdio style buffering to minimize calls to ptrace */
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[sizeof (int)];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() (codestream_addr + codestream_off)
+#define codestream_peek() (codestream_cnt == 0 ? \
+                          codestream_fill(1): codestream_buf[codestream_off])
+#define codestream_get() (codestream_cnt-- == 0 ? \
+                        codestream_fill(0) : codestream_buf[codestream_off++])
+
+static unsigned char 
+codestream_fill (peek_flag)
+{
+  codestream_addr = codestream_next_addr;
+  codestream_next_addr += sizeof (int);
+  codestream_off = 0;
+  codestream_cnt = sizeof (int);
+  read_memory (codestream_addr,
+              (unsigned char *)codestream_buf,
+              sizeof (int));
+  
+  if (peek_flag)
+    return (codestream_peek());
+  else
+    return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+{
+  codestream_next_addr = place & -sizeof (int);
+  codestream_cnt = 0;
+  codestream_fill (1);
+  while (codestream_tell() != place)
+    codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+     unsigned char *buf;
+{
+  unsigned char *p;
+  int i;
+  p = buf;
+  for (i = 0; i < count; i++)
+    *p++ = codestream_get ();
+}
+
+/* next instruction is a jump, move to target */
+static
+i386_follow_jump ()
+{
+  int long_delta;
+  short short_delta;
+  char byte_delta;
+  int data16;
+  int pos;
+  
+  pos = codestream_tell ();
+  
+  data16 = 0;
+  if (codestream_peek () == 0x66)
+    {
+      codestream_get ();
+      data16 = 1;
+    }
+  
+  switch (codestream_get ())
+    {
+    case 0xe9:
+      /* relative jump: if data16 == 0, disp32, else disp16 */
+      if (data16)
+       {
+         codestream_read ((unsigned char *)&short_delta, 2);
+         pos += short_delta + 3; /* include size of jmp inst */
+       }
+      else
+       {
+         codestream_read ((unsigned char *)&long_delta, 4);
+         pos += long_delta + 5;
+       }
+      break;
+    case 0xeb:
+      /* relative jump, disp8 (ignore data16) */
+      codestream_read ((unsigned char *)&byte_delta, 1);
+      pos += byte_delta + 2;
+      break;
+    }
+  codestream_seek (pos + data16);
+}
+
+/*
+ * find & return amound a local space allocated, and advance codestream to
+ * first register push (if any)
+ *
+ * if entry sequence doesn't make sense, return -1, and leave 
+ * codestream pointer random
+ */
+static long
+i386_get_frame_setup (pc)
+{
+  unsigned char op;
+  
+  codestream_seek (pc);
+  
+  i386_follow_jump ();
+  
+  op = codestream_get ();
+  
+  if (op == 0x58)              /* popl %eax */
+    {
+      /*
+       * this function must start with
+       * 
+       *    popl %eax            0x58
+       *    xchgl %eax, (%esp)  0x87 0x04 0x24
+       * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
+       *
+       * (the system 5 compiler puts out the second xchg
+       * inst, and the assembler doesn't try to optimize it,
+       * so the 'sib' form gets generated)
+       * 
+       * this sequence is used to get the address of the return
+       * buffer for a function that returns a structure
+       */
+      int pos;
+      unsigned char buf[4];
+      static unsigned char proto1[3] = { 0x87,0x04,0x24 };
+      static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
+      pos = codestream_tell ();
+      codestream_read (buf, 4);
+      if (bcmp (buf, proto1, 3) == 0)
+       pos += 3;
+      else if (bcmp (buf, proto2, 4) == 0)
+       pos += 4;
+      
+      codestream_seek (pos);
+      op = codestream_get (); /* update next opcode */
+    }
+  
+  if (op == 0x55)              /* pushl %ebp */
+    {                  
+      /* check for movl %esp, %ebp - can be written two ways */
+      switch (codestream_get ())
+       {
+       case 0x8b:
+         if (codestream_get () != 0xec)
+           return (-1);
+         break;
+       case 0x89:
+         if (codestream_get () != 0xe5)
+           return (-1);
+         break;
+       default:
+         return (-1);
+       }
+      /* check for stack adjustment 
+       *
+       *  subl $XXX, %esp
+       *
+       * note: you can't subtract a 16 bit immediate
+       * from a 32 bit reg, so we don't have to worry
+       * about a data16 prefix 
+       */
+      op = codestream_peek ();
+      if (op == 0x83)
+       {
+         /* subl with 8 bit immed */
+         codestream_get ();
+         if (codestream_get () != 0xec)
+           /* Some instruction starting with 0x83 other than subl.  */
+           {
+             codestream_seek (codestream_tell () - 2);
+             return 0;
+           }
+         /* subl with signed byte immediate 
+          * (though it wouldn't make sense to be negative)
+          */
+         return (codestream_get());
+       }
+      else if (op == 0x81)
+       {
+         /* subl with 32 bit immed */
+         int locals;
+         codestream_get();
+         if (codestream_get () != 0xec)
+           /* Some instruction starting with 0x81 other than subl.  */
+           {
+             codestream_seek (codestream_tell () - 2);
+             return 0;
+           }
+         /* subl with 32 bit immediate */
+         codestream_read ((unsigned char *)&locals, 4);
+         return (locals);
+       }
+      else
+       {
+         return (0);
+       }
+    }
+  else if (op == 0xc8)
+    {
+      /* enter instruction: arg is 16 bit unsigned immed */
+      unsigned short slocals;
+      codestream_read ((unsigned char *)&slocals, 2);
+      codestream_get (); /* flush final byte of enter instruction */
+      return (slocals);
+    }
+  return (-1);
+}
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+/* on the 386, the instruction following the call could be:
+ *  popl %ecx        -  one arg
+ *  addl $imm, %esp  -  imm/4 args; imm may be 8 or 32 bits
+ *  anything else    -  zero args
+ */
+
+int
+i386_frame_num_args (fi)
+     struct frame_info fi;
+{
+  int retpc;                                           
+  unsigned char op;                                    
+  struct frame_info *pfi;
+
+  int frameless;
+
+  FRAMELESS_FUNCTION_INVOCATION (fi, frameless);
+  if (frameless)
+    /* In the absence of a frame pointer, GDB doesn't get correct values
+       for nameless arguments.  Return -1, so it doesn't print any
+       nameless arguments.  */
+    return -1;
+
+  pfi = get_prev_frame_info ((fi));                    
+  if (pfi == 0)
+    {
+      /* Note:  this can happen if we are looking at the frame for
+        main, because FRAME_CHAIN_VALID won't let us go into
+        start.  If we have debugging symbols, that's not really
+        a big deal; it just means it will only show as many arguments
+        to main as are declared.  */
+      return -1;
+    }
+  else
+    {
+      retpc = pfi->pc;                                 
+      op = read_memory_integer (retpc, 1);                     
+      if (op == 0x59)                                  
+       /* pop %ecx */                         
+       return 1;                               
+      else if (op == 0x83)
+       {
+         op = read_memory_integer (retpc+1, 1);        
+         if (op == 0xc4)                               
+           /* addl $<signed imm 8 bits>, %esp */       
+           return (read_memory_integer (retpc+2,1)&0xff)/4;
+         else
+           return 0;
+       }
+      else if (op == 0x81)
+       { /* add with 32 bit immediate */
+         op = read_memory_integer (retpc+1, 1);        
+         if (op == 0xc4)                               
+           /* addl $<imm 32>, %esp */          
+           return read_memory_integer (retpc+2, 4) / 4;
+         else
+           return 0;
+       }
+      else
+       {
+         return 0;
+       }
+    }
+}
+
+/*
+ * parse the first few instructions of the function to see
+ * what registers were stored.
+ *
+ * We handle these cases:
+ *
+ * The startup sequence can be at the start of the function,
+ * or the function can start with a branch to startup code at the end.
+ *
+ * %ebp can be set up with either the 'enter' instruction, or 
+ * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful,
+ * but was once used in the sys5 compiler)
+ *
+ * Local space is allocated just below the saved %ebp by either the
+ * 'enter' instruction, or by 'subl $<size>, %esp'.  'enter' has
+ * a 16 bit unsigned argument for space to allocate, and the
+ * 'addl' instruction could have either a signed byte, or
+ * 32 bit immediate.
+ *
+ * Next, the registers used by this function are pushed.  In
+ * the sys5 compiler they will always be in the order: %edi, %esi, %ebx
+ * (and sometimes a harmless bug causes it to also save but not restore %eax);
+ * however, the code below is willing to see the pushes in any order,
+ * and will handle up to 8 of them.
+ *
+ * If the setup sequence is at the end of the function, then the
+ * next instruction will be a branch back to the start.
+ */
+
+i386_frame_find_saved_regs (fip, fsrp)
+     struct frame_info *fip;
+     struct frame_saved_regs *fsrp;
+{
+  long locals;
+  unsigned char *p;
+  unsigned char op;
+  CORE_ADDR dummy_bottom;
+  CORE_ADDR adr;
+  int i;
+  
+  bzero (fsrp, sizeof *fsrp);
+  
+  /* if frame is the end of a dummy, compute where the
+   * beginning would be
+   */
+  dummy_bottom = fip->frame - 4 - REGISTER_BYTES - CALL_DUMMY_LENGTH;
+  
+  /* check if the PC is in the stack, in a dummy frame */
+  if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) 
+    {
+      /* all regs were saved by push_call_dummy () */
+      adr = fip->frame;
+      for (i = 0; i < NUM_REGS; i++) 
+       {
+         adr -= REGISTER_RAW_SIZE (i);
+         fsrp->regs[i] = adr;
+       }
+      return;
+    }
+  
+  locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
+  
+  if (locals >= 0) 
+    {
+      adr = fip->frame - 4 - locals;
+      for (i = 0; i < 8; i++) 
+       {
+         op = codestream_get ();
+         if (op < 0x50 || op > 0x57)
+           break;
+         fsrp->regs[op - 0x50] = adr;
+         adr -= 4;
+       }
+    }
+  
+  fsrp->regs[PC_REGNUM] = fip->frame + 4;
+  fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+/* return pc of first real instruction */
+i386_skip_prologue (pc)
+{
+  unsigned char op;
+  int i;
+  
+  if (i386_get_frame_setup (pc) < 0)
+    return (pc);
+  
+  /* found valid frame setup - codestream now points to 
+   * start of push instructions for saving registers
+   */
+  
+  /* skip over register saves */
+  for (i = 0; i < 8; i++)
+    {
+      op = codestream_peek ();
+      /* break if not pushl inst */
+      if (op < 0x50 || op > 0x57) 
+       break;
+      codestream_get ();
+    }
+  
+  i386_follow_jump ();
+  
+  return (codestream_tell ());
+}
+
+i386_push_dummy_frame ()
+{
+  CORE_ADDR sp = read_register (SP_REGNUM);
+  int regnum;
+  char regbuf[MAX_REGISTER_RAW_SIZE];
+  
+  sp = push_word (sp, read_register (PC_REGNUM));
+  sp = push_word (sp, read_register (FP_REGNUM));
+  write_register (FP_REGNUM, sp);
+  for (regnum = 0; regnum < NUM_REGS; regnum++)
+    {
+      read_register_gen (regnum, regbuf);
+      sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
+    }
+  write_register (SP_REGNUM, sp);
+}
+
+i386_pop_frame ()
+{
+  FRAME frame = get_current_frame ();
+  CORE_ADDR fp;
+  int regnum;
+  struct frame_saved_regs fsr;
+  struct frame_info *fi;
+  char regbuf[MAX_REGISTER_RAW_SIZE];
+  
+  fi = get_frame_info (frame);
+  fp = fi->frame;
+  get_frame_saved_regs (fi, &fsr);
+  for (regnum = 0; regnum < NUM_REGS; regnum++) 
+    {
+      CORE_ADDR adr;
+      adr = fsr.regs[regnum];
+      if (adr)
+       {
+         read_memory (adr, regbuf, REGISTER_RAW_SIZE (regnum));
+         write_register_bytes (REGISTER_BYTE (regnum), regbuf,
+                               REGISTER_RAW_SIZE (regnum));
+       }
+    }
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
+  write_register (SP_REGNUM, fp + 8);
+  flush_cached_frames ();
+  set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                       read_pc ()));
+}
diff --git a/gdb/i386-xdep.c b/gdb/i386-xdep.c
new file mode 100644 (file)
index 0000000..dddf22d
--- /dev/null
@@ -0,0 +1,357 @@
+/* Intel 386 stuff.
+   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <sys/reg.h>
+\f
+/* this table must line up with REGISTER_NAMES in m-i386.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int regmap[] = 
+{
+  EAX, ECX, EDX, EBX,
+  UESP, EBP, ESI, EDI,
+  EIP, EFL, CS, SS,
+  DS, ES, FS, GS,
+};
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+i386_register_u_addr (blockend, regnum)
+{
+#if 0
+  /* this will be needed if fp registers are reinstated */
+  /* for now, you can look at them with 'info float'
+   * sys5 wont let you change them with ptrace anyway
+   */
+  if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM) 
+    {
+      int ubase, fpstate;
+      struct user u;
+      ubase = blockend + 4 * (SS + 1) - KSTKSZ;
+      fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
+      return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+    } 
+  else
+#endif
+    return (blockend + 4 * regmap[regnum]);
+  
+}
+
+/* This is broken for cross debugging.  Possible solutions are:
+
+1.  Don't worry about whether the thing compiles for cross-debugging.
+Go ahead and call them from i386-tdep.c.
+1a.  Same thing but use some macros in xm-i386.h so that gdb will
+compile for cross-debugging but just give an error (or some such behavior)
+when you attempt to convert floats.
+
+2.  Write a portable (in the sense of running on any machine; it would
+always be for i387 floating-point formats) extended<->double converter
+(which just deals with the values as arrays of char).
+
+3.  Assume the host machine has *some* IEEE chip.  However, IEEE does
+not standardize formats for extended floats (387 is 10 bytes, 68881 is
+12 bytes), so this won't work.  */
+
+i387_to_double (from, to)
+     char *from;
+     char *to;
+{
+  long *lp;
+  /* push extended mode on 387 stack, then pop in double mode
+   *
+   * first, set exception masks so no error is generated -
+   * number will be rounded to inf or 0, if necessary 
+   */
+  asm ("pushl %eax");          /* grab a stack slot */
+  asm ("fstcw (%esp)");                /* get 387 control word */
+  asm ("movl (%esp),%eax");    /* save old value */
+  asm ("orl $0x3f,%eax");              /* mask all exceptions */
+  asm ("pushl %eax");
+  asm ("fldcw (%esp)");                /* load new value into 387 */
+  
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldt (%eax)");         /* push extended number on 387 stack */
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpl (%eax)");                /* pop double */
+  asm ("fwait");
+  
+  asm ("popl %eax");           /* flush modified control word */
+  asm ("fnclex");                      /* clear exceptions */
+  asm ("fldcw (%esp)");                /* restore original control word */
+  asm ("popl %eax");           /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+     char *from;
+     char *to;
+{
+  /* push double mode on 387 stack, then pop in extended mode
+   * no errors are possible because every 64-bit pattern
+   * can be converted to an extended
+   */
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldl (%eax)");
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpt (%eax)");
+  asm ("fwait");
+}
+
+struct env387 
+{
+  unsigned short control;
+  unsigned short r0;
+  unsigned short status;
+  unsigned short r1;
+  unsigned short tag;
+  unsigned short r2;
+  unsigned long eip;
+  unsigned short code_seg;
+  unsigned short opcode;
+  unsigned long operand;
+  unsigned short operand_seg;
+  unsigned short r3;
+  unsigned char regs[8][10];
+};
+
+static
+print_387_control_word (control)
+unsigned short control;
+{
+  printf ("control 0x%04x: ", control);
+  printf ("compute to ");
+  switch ((control >> 8) & 3) 
+    {
+    case 0: printf ("24 bits; "); break;
+    case 1: printf ("(bad); "); break;
+    case 2: printf ("53 bits; "); break;
+    case 3: printf ("64 bits; "); break;
+    }
+  printf ("round ");
+  switch ((control >> 10) & 3) 
+    {
+    case 0: printf ("NEAREST; "); break;
+    case 1: printf ("DOWN; "); break;
+    case 2: printf ("UP; "); break;
+    case 3: printf ("CHOP; "); break;
+    }
+  if (control & 0x3f) 
+    {
+      printf ("mask:");
+      if (control & 0x0001) printf (" INVALID");
+      if (control & 0x0002) printf (" DENORM");
+      if (control & 0x0004) printf (" DIVZ");
+      if (control & 0x0008) printf (" OVERF");
+      if (control & 0x0010) printf (" UNDERF");
+      if (control & 0x0020) printf (" LOS");
+      printf (";");
+    }
+  printf ("\n");
+  if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
+                               control & 0xe080);
+}
+
+static
+print_387_status_word (status)
+     unsigned short status;
+{
+  printf ("status 0x%04x: ", status);
+  if (status & 0xff) 
+    {
+      printf ("exceptions:");
+      if (status & 0x0001) printf (" INVALID");
+      if (status & 0x0002) printf (" DENORM");
+      if (status & 0x0004) printf (" DIVZ");
+      if (status & 0x0008) printf (" OVERF");
+      if (status & 0x0010) printf (" UNDERF");
+      if (status & 0x0020) printf (" LOS");
+      if (status & 0x0040) printf (" FPSTACK");
+      printf ("; ");
+    }
+  printf ("flags: %d%d%d%d; ",
+         (status & 0x4000) != 0,
+         (status & 0x0400) != 0,
+         (status & 0x0200) != 0,
+         (status & 0x0100) != 0);
+  
+  printf ("top %d\n", (status >> 11) & 7);
+}
+
+static
+print_387_status (status, ep)
+     unsigned short status;
+     struct env387 *ep;
+{
+  int i;
+  int bothstatus;
+  int top;
+  int fpreg;
+  unsigned char *p;
+  
+  bothstatus = ((status != 0) && (ep->status != 0));
+  if (status != 0) 
+    {
+      if (bothstatus)
+       printf ("u: ");
+      print_387_status_word (status);
+    }
+  
+  if (ep->status != 0) 
+    {
+      if (bothstatus)
+       printf ("e: ");
+      print_387_status_word (ep->status);
+    }
+  
+  print_387_control_word (ep->control);
+  printf ("last exception: ");
+  printf ("opcode 0x%x; ", ep->opcode);
+  printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
+  printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
+  
+  top = (ep->status >> 11) & 7;
+  
+  printf ("regno  tag  msb              lsb  value\n");
+  for (fpreg = 7; fpreg >= 0; fpreg--) 
+    {
+      double val;
+      
+      printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
+      
+      switch ((ep->tag >> (fpreg * 2)) & 3) 
+       {
+       case 0: printf ("valid "); break;
+       case 1: printf ("zero  "); break;
+       case 2: printf ("trap  "); break;
+       case 3: printf ("empty "); break;
+       }
+      for (i = 9; i >= 0; i--)
+       printf ("%02x", ep->regs[fpreg][i]);
+      
+      i387_to_double (ep->regs[fpreg], (char *)&val);
+      printf ("  %g\n", val);
+    }
+  if (ep->r0)
+    printf ("warning: reserved0 is 0x%x\n", ep->r0);
+  if (ep->r1)
+    printf ("warning: reserved1 is 0x%x\n", ep->r1);
+  if (ep->r2)
+    printf ("warning: reserved2 is 0x%x\n", ep->r2);
+  if (ep->r3)
+    printf ("warning: reserved3 is 0x%x\n", ep->r3);
+}
+
+#ifndef U_FPSTATE
+#define U_FPSTATE(u) u.u_fpstate
+#endif
+
+i386_float_info ()
+{
+  struct user u; /* just for address computations */
+  int i;
+  /* fpstate defined in <sys/user.h> */
+  struct fpstate *fpstatep;
+  char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
+  unsigned int uaddr;
+  char fpvalid;
+  unsigned int rounded_addr;
+  unsigned int rounded_size;
+  extern int corechan;
+  int skip;
+  
+  uaddr = (char *)&u.u_fpvalid - (char *)&u;
+  if (have_inferior_p()) 
+    {
+      unsigned int data;
+      unsigned int mask;
+      
+      rounded_addr = uaddr & -sizeof (int);
+      data = ptrace (3, inferior_pid, rounded_addr, 0);
+      mask = 0xff << ((uaddr - rounded_addr) * 8);
+      
+      fpvalid = ((data & mask) != 0);
+    } 
+  else 
+    {
+      if (lseek (corechan, uaddr, 0) < 0)
+       perror ("seek on core file");
+      if (myread (corechan, &fpvalid, 1) < 0) 
+       perror ("read on core file");
+      
+    }
+  
+  if (fpvalid == 0) 
+    {
+      printf ("no floating point status saved\n");
+      return;
+    }
+  
+  uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+  if (have_inferior_p ()) 
+    {
+      int *ip;
+      
+      rounded_addr = uaddr & -sizeof (int);
+      rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
+                     sizeof (int) - 1) / sizeof (int);
+      skip = uaddr - rounded_addr;
+      
+      ip = (int *)buf;
+      for (i = 0; i < rounded_size; i++) 
+       {
+         *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
+         rounded_addr += sizeof (int);
+       }
+    } 
+  else 
+    {
+      if (lseek (corechan, uaddr, 0) < 0)
+       perror_with_name ("seek on core file");
+      if (myread (corechan, buf, sizeof (struct fpstate)) < 0) 
+       perror_with_name ("read from core file");
+      skip = 0;
+    }
+  
+  fpstatep = (struct fpstate *)(buf + skip);
+  print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
+}
+
diff --git a/gdb/i960-pinsn.c b/gdb/i960-pinsn.c
new file mode 100644 (file)
index 0000000..ea3fa64
--- /dev/null
@@ -0,0 +1,847 @@
+/* Disassemble i80960 instructions.
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+extern char *reg_names[];
+
+static FILE *stream;           /* Output goes here */
+static void print_addr();
+static void ctrl();
+static void cobr();
+static void reg();
+static int mem();
+static void ea();
+static void dstop();
+static void regop();
+static void invalid();
+static int pinsn();
+static void put_abs();
+
+
+/* Print the i960 instruction at address 'memaddr' in debugged memory,
+   on stream 's'.  Returns length of the instruction, in bytes.  */
+int
+print_insn( memaddr, s )
+    CORE_ADDR memaddr;
+    FILE *s;
+{
+       unsigned int word1, word2;
+
+       stream = s;
+       word1 = read_memory_integer( memaddr, 4 );
+       word2 = read_memory_integer( memaddr+4, 4 );
+       return pinsn( memaddr, word1, word2 );
+}
+
+
+/* Read the i960 instruction at 'memaddr' and return the address of 
+   the next instruction after that, or 0 if 'memaddr' is not the
+   address of a valid instruction.  The first word of the instruction
+   is stored at 'pword1', and the second word, if any, is stored at
+   'pword2'.  */
+
+CORE_ADDR
+next_insn (memaddr, pword1, pword2)
+     unsigned long *pword1, *pword2;
+     CORE_ADDR memaddr;
+{
+  int len;
+  unsigned long buf[2];
+
+  /* Read the two (potential) words of the instruction at once,
+     to eliminate the overhead of two calls to read_memory ().
+     TODO: read more instructions at once and cache them.  */
+
+  read_memory (memaddr, buf, sizeof (buf));
+  *pword1 = buf[0];
+  SWAP_TARGET_AND_HOST (pword1, sizeof (long));
+  *pword2 = buf[1];
+  SWAP_TARGET_AND_HOST (pword2, sizeof (long));
+
+  /* Divide instruction set into classes based on high 4 bits of opcode*/
+
+  switch ((*pword1 >> 28) & 0xf)
+    {
+    case 0x0:
+    case 0x1:  /* ctrl */
+
+    case 0x2:
+    case 0x3:  /* cobr */
+
+    case 0x5:
+    case 0x6:
+    case 0x7:  /* reg */
+      len = 4;
+      break;
+
+    case 0x8:
+    case 0x9:
+    case 0xa:
+    case 0xb:
+    case 0xc:
+      len = mem (memaddr, *pword1, *pword2, 1);
+      break;
+
+    default:   /* invalid instruction */
+      len = 0;
+      break;
+    }
+
+  if (len)
+    return memaddr + len;
+  else
+    return 0;
+}
+\f
+#define IN_GDB
+
+/*****************************************************************************
+ *     All code below this point should be identical with that of
+ *     the disassembler in gdmp960.
+ *****************************************************************************/
+
+struct tabent {
+       char    *name;
+       char    numops;
+};
+
+static int
+pinsn( memaddr, word1, word2 )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+{
+       int instr_len;
+
+       instr_len = 4;
+       put_abs( word1, word2 );
+
+       /* Divide instruction set into classes based on high 4 bits of opcode*/
+
+       switch ( (word1 >> 28) & 0xf ){
+       case 0x0:
+       case 0x1:
+               ctrl( memaddr, word1, word2 );
+               break;
+       case 0x2:
+       case 0x3:
+               cobr( memaddr, word1, word2 );
+               break;
+       case 0x5:
+       case 0x6:
+       case 0x7:
+               reg( word1 );
+               break;
+       case 0x8:
+       case 0x9:
+       case 0xa:
+       case 0xb:
+       case 0xc:
+               instr_len = mem( memaddr, word1, word2, 0 );
+               break;
+       default:
+               /* invalid instruction, print as data word */ 
+               invalid( word1 );
+               break;
+       }
+       return instr_len;
+}
+
+/****************************************/
+/* CTRL format                         */
+/****************************************/
+static void
+ctrl( memaddr, word1, word2 )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+{
+       int i;
+       static struct tabent ctrl_tab[] = {
+               NULL,           0,      /* 0x00 */
+               NULL,           0,      /* 0x01 */
+               NULL,           0,      /* 0x02 */
+               NULL,           0,      /* 0x03 */
+               NULL,           0,      /* 0x04 */
+               NULL,           0,      /* 0x05 */
+               NULL,           0,      /* 0x06 */
+               NULL,           0,      /* 0x07 */
+               "b",            1,      /* 0x08 */
+               "call",         1,      /* 0x09 */
+               "ret",          0,      /* 0x0a */
+               "bal",          1,      /* 0x0b */
+               NULL,           0,      /* 0x0c */
+               NULL,           0,      /* 0x0d */
+               NULL,           0,      /* 0x0e */
+               NULL,           0,      /* 0x0f */
+               "bno",          1,      /* 0x10 */
+               "bg",           1,      /* 0x11 */
+               "be",           1,      /* 0x12 */
+               "bge",          1,      /* 0x13 */
+               "bl",           1,      /* 0x14 */
+               "bne",          1,      /* 0x15 */
+               "ble",          1,      /* 0x16 */
+               "bo",           1,      /* 0x17 */
+               "faultno",      0,      /* 0x18 */
+               "faultg",       0,      /* 0x19 */
+               "faulte",       0,      /* 0x1a */
+               "faultge",      0,      /* 0x1b */
+               "faultl",       0,      /* 0x1c */
+               "faultne",      0,      /* 0x1d */
+               "faultle",      0,      /* 0x1e */
+               "faulto",       0,      /* 0x1f */
+       };
+
+       i = (word1 >> 24) & 0xff;
+       if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){
+               invalid( word1 );
+               return;
+       }
+
+       fputs( ctrl_tab[i].name, stream );
+       if ( word1 & 2 ){               /* Predicts branch not taken */
+               fputs( ".f", stream );
+       }
+
+       if ( ctrl_tab[i].numops == 1 ){
+               /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */
+               word1 &= 0x00ffffff;
+               if ( word1 & 0x00800000 ){              /* Sign bit is set */
+                       word1 |= (-1 & ~0xffffff);      /* Sign extend */
+               }
+               putc( '\t', stream );
+               print_addr( word1 + memaddr );
+       }
+}
+
+/****************************************/
+/* COBR format                         */
+/****************************************/
+static void
+cobr( memaddr, word1, word2 )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+{
+       int src1;
+       int src2;
+       int i;
+
+       static struct tabent cobr_tab[] = {
+               "testno",       1,      /* 0x20 */
+               "testg",        1,      /* 0x21 */
+               "teste",        1,      /* 0x22 */
+               "testge",       1,      /* 0x23 */
+               "testl",        1,      /* 0x24 */
+               "testne",       1,      /* 0x25 */
+               "testle",       1,      /* 0x26 */
+               "testo",        1,      /* 0x27 */
+               NULL,           0,      /* 0x28 */
+               NULL,           0,      /* 0x29 */
+               NULL,           0,      /* 0x2a */
+               NULL,           0,      /* 0x2b */
+               NULL,           0,      /* 0x2c */
+               NULL,           0,      /* 0x2d */
+               NULL,           0,      /* 0x2e */
+               NULL,           0,      /* 0x2f */
+               "bbc",          3,      /* 0x30 */
+               "cmpobg",       3,      /* 0x31 */
+               "cmpobe",       3,      /* 0x32 */
+               "cmpobge",      3,      /* 0x33 */
+               "cmpobl",       3,      /* 0x34 */
+               "cmpobne",      3,      /* 0x35 */
+               "cmpoble",      3,      /* 0x36 */
+               "bbs",          3,      /* 0x37 */
+               "cmpibno",      3,      /* 0x38 */
+               "cmpibg",       3,      /* 0x39 */
+               "cmpibe",       3,      /* 0x3a */
+               "cmpibge",      3,      /* 0x3b */
+               "cmpibl",       3,      /* 0x3c */
+               "cmpibne",      3,      /* 0x3d */
+               "cmpible",      3,      /* 0x3e */
+               "cmpibo",       3,      /* 0x3f */
+       };
+
+       i = ((word1 >> 24) & 0xff) - 0x20;
+       if ( cobr_tab[i].name == NULL ){
+               invalid( word1 );
+               return;
+       }
+
+       fputs( cobr_tab[i].name, stream );
+       if ( word1 & 2 ){               /* Predicts branch not taken */
+               fputs( ".f", stream );
+       }
+       putc( '\t', stream );
+
+       src1 = (word1 >> 19) & 0x1f;
+       src2 = (word1 >> 14) & 0x1f;
+
+       if ( word1 & 0x02000 ){         /* M1 is 1 */
+               fprintf( stream, "%d", src1 );
+       } else {                        /* M1 is 0 */
+               fputs( reg_names[src1], stream );
+       }
+
+       if ( cobr_tab[i].numops > 1 ){
+               if ( word1 & 1 ){               /* S2 is 1 */
+                       fprintf( stream, ",sf%d,", src2 );
+               } else {                        /* S1 is 0 */
+                       fprintf( stream, ",%s,", reg_names[src2] );
+               }
+
+               /* Extract displacement and convert to address
+                */
+               word1 &= 0x00001ffc;
+               if ( word1 & 0x00001000 ){      /* Negative displacement */
+                       word1 |= (-1 & ~0x1fff);        /* Sign extend */
+               }
+               print_addr( memaddr + word1 );
+       }
+}
+
+/****************************************/
+/* MEM format                          */
+/****************************************/
+static int                             /* returns instruction length: 4 or 8 */
+mem( memaddr, word1, word2, noprint )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+    int noprint;               /* If TRUE, return instruction length, but
+                                  don't output any text.  */
+{
+       int i, j;
+       int len;
+       int mode;
+       int offset;
+       char *reg1, *reg2, *reg3;
+
+       /* This lookup table is too sparse to make it worth typing in, but not
+        * so large as to make a sparse array necessary.  We allocate the
+        * table at runtime, initialize all entries to empty, and copy the
+        * real ones in from an initialization table.
+        *
+        * NOTE: In this table, the meaning of 'numops' is:
+        *       1: single operand
+        *       2: 2 operands, load instruction
+        *      -2: 2 operands, store instruction
+        */
+       static struct tabent *mem_tab = NULL;
+       static struct { int opcode; char *name; char numops; } mem_init[] = {
+#define MEM_MIN        0x80
+               0x80,   "ldob",  2,
+               0x82,   "stob", -2,
+               0x84,   "bx",    1,
+               0x85,   "balx",  2,
+               0x86,   "callx", 1,
+               0x88,   "ldos",  2,
+               0x8a,   "stos", -2,
+               0x8c,   "lda",   2,
+               0x90,   "ld",    2,
+               0x92,   "st",   -2,
+               0x98,   "ldl",   2,
+               0x9a,   "stl",  -2,
+               0xa0,   "ldt",   2,
+               0xa2,   "stt",  -2,
+               0xb0,   "ldq",   2,
+               0xb2,   "stq",  -2,
+               0xc0,   "ldib",  2,
+               0xc2,   "stib", -2,
+               0xc8,   "ldis",  2,
+               0xca,   "stis", -2,
+#define MEM_MAX        0xca
+#define MEM_SIZ        ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
+               0,      NULL,   0
+       };
+
+       if ( mem_tab == NULL ){
+               mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
+               bzero( mem_tab, MEM_SIZ );
+               for ( i = 0; mem_init[i].opcode != 0; i++ ){
+                       j = mem_init[i].opcode - MEM_MIN;
+                       mem_tab[j].name = mem_init[i].name;
+                       mem_tab[j].numops = mem_init[i].numops;
+               }
+       }
+
+       i = ((word1 >> 24) & 0xff) - MEM_MIN;
+       mode = (word1 >> 10) & 0xf;
+
+       if ( (mem_tab[i].name != NULL)          /* Valid instruction */
+       &&   ((mode == 5) || (mode >=12)) ){    /* With 32-bit displacement */
+               len = 8;
+       } else {
+               len = 4;
+       }
+
+       if ( noprint ){
+               return len;
+       }
+
+       if ( (mem_tab[i].name == NULL) || (mode == 6) ){
+               invalid( word1 );
+               return len;
+       }
+
+       fprintf( stream, "%s\t", mem_tab[i].name );
+
+       reg1 = reg_names[ (word1 >> 19) & 0x1f ];       /* MEMB only */
+       reg2 = reg_names[ (word1 >> 14) & 0x1f ];
+       reg3 = reg_names[ word1 & 0x1f ];               /* MEMB only */
+       offset = word1 & 0xfff;                         /* MEMA only  */
+
+       switch ( mem_tab[i].numops ){
+
+       case 2: /* LOAD INSTRUCTION */
+               if ( mode & 4 ){                        /* MEMB FORMAT */
+                       ea( memaddr, mode, reg2, reg3, word1, word2 );
+                       fprintf( stream, ",%s", reg1 );
+               } else {                                /* MEMA FORMAT */
+                       fprintf( stream, "0x%x", offset );
+                       if (mode & 8) {
+                               fprintf( stream, "(%s)", reg2 );
+                       }
+                       fprintf( stream, ",%s", reg1 );
+               }
+               break;
+
+       case -2: /* STORE INSTRUCTION */
+               if ( mode & 4 ){                        /* MEMB FORMAT */
+                       fprintf( stream, "%s,", reg1 );
+                       ea( memaddr, mode, reg2, reg3, word1, word2 );
+               } else {                                /* MEMA FORMAT */
+                       fprintf( stream, "%s,0x%x", reg1, offset );
+                       if (mode & 8) {
+                               fprintf( stream, "(%s)", reg2 );
+                       }
+               }
+               break;
+
+       case 1: /* BX/CALLX INSTRUCTION */
+               if ( mode & 4 ){                        /* MEMB FORMAT */
+                       ea( memaddr, mode, reg2, reg3, word1, word2 );
+               } else {                                /* MEMA FORMAT */
+                       fprintf( stream, "0x%x", offset );
+                       if (mode & 8) {
+                               fprintf( stream, "(%s)", reg2 );
+                       }
+               }
+               break;
+       }
+
+       return len;
+}
+
+/****************************************/
+/* REG format                          */
+/****************************************/
+static void
+reg( word1 )
+    unsigned long word1;
+{
+       int i, j;
+       int opcode;
+       int fp;
+       int m1, m2, m3;
+       int s1, s2;
+       int src, src2, dst;
+       char *mnemp;
+
+       /* This lookup table is too sparse to make it worth typing in, but not
+        * so large as to make a sparse array necessary.  We allocate the
+        * table at runtime, initialize all entries to empty, and copy the
+        * real ones in from an initialization table.
+        *
+        * NOTE: In this table, the meaning of 'numops' is:
+        *       1: single operand, which is NOT a destination.
+        *      -1: single operand, which IS a destination.
+        *       2: 2 operands, the 2nd of which is NOT a destination.
+        *      -2: 2 operands, the 2nd of which IS a destination.
+        *       3: 3 operands
+        *
+        *      If an opcode mnemonic begins with "F", it is a floating-point
+        *      opcode (the "F" is not printed).
+        */
+
+       static struct tabent *reg_tab = NULL;
+       static struct { int opcode; char *name; char numops; } reg_init[] = {
+#define REG_MIN        0x580
+               0x580,  "notbit",       3,
+               0x581,  "and",          3,
+               0x582,  "andnot",       3,
+               0x583,  "setbit",       3,
+               0x584,  "notand",       3,
+               0x586,  "xor",          3,
+               0x587,  "or",           3,
+               0x588,  "nor",          3,
+               0x589,  "xnor",         3,
+               0x58a,  "not",          -2,
+               0x58b,  "ornot",        3,
+               0x58c,  "clrbit",       3,
+               0x58d,  "notor",        3,
+               0x58e,  "nand",         3,
+               0x58f,  "alterbit",     3,
+               0x590,  "addo",         3,
+               0x591,  "addi",         3,
+               0x592,  "subo",         3,
+               0x593,  "subi",         3,
+               0x598,  "shro",         3,
+               0x59a,  "shrdi",        3,
+               0x59b,  "shri",         3,
+               0x59c,  "shlo",         3,
+               0x59d,  "rotate",       3,
+               0x59e,  "shli",         3,
+               0x5a0,  "cmpo",         2,
+               0x5a1,  "cmpi",         2,
+               0x5a2,  "concmpo",      2,
+               0x5a3,  "concmpi",      2,
+               0x5a4,  "cmpinco",      3,
+               0x5a5,  "cmpinci",      3,
+               0x5a6,  "cmpdeco",      3,
+               0x5a7,  "cmpdeci",      3,
+               0x5ac,  "scanbyte",     2,
+               0x5ae,  "chkbit",       2,
+               0x5b0,  "addc",         3,
+               0x5b2,  "subc",         3,
+               0x5cc,  "mov",          -2,
+               0x5d8,  "eshro",        3,
+               0x5dc,  "movl",         -2,
+               0x5ec,  "movt",         -2,
+               0x5fc,  "movq",         -2,
+               0x600,  "synmov",       2,
+               0x601,  "synmovl",      2,
+               0x602,  "synmovq",      2,
+               0x603,  "cmpstr",       3,
+               0x604,  "movqstr",      3,
+               0x605,  "movstr",       3,
+               0x610,  "atmod",        3,
+               0x612,  "atadd",        3,
+               0x613,  "inspacc",      -2,
+               0x614,  "ldphy",        -2,
+               0x615,  "synld",        -2,
+               0x617,  "fill",         3,
+               0x630,  "sdma",         3,
+               0x631,  "udma",         0,
+               0x640,  "spanbit",      -2,
+               0x641,  "scanbit",      -2,
+               0x642,  "daddc",        3,
+               0x643,  "dsubc",        3,
+               0x644,  "dmovt",        -2,
+               0x645,  "modac",        3,
+               0x646,  "condrec",      -2,
+               0x650,  "modify",       3,
+               0x651,  "extract",      3,
+               0x654,  "modtc",        3,
+               0x655,  "modpc",        3,
+               0x656,  "receive",      -2,
+               0x659,  "sysctl",       3,
+               0x660,  "calls",        1,
+               0x662,  "send",         3,
+               0x663,  "sendserv",     1,
+               0x664,  "resumprcs",    1,
+               0x665,  "schedprcs",    1,
+               0x666,  "saveprcs",     0,
+               0x668,  "condwait",     1,
+               0x669,  "wait",         1,
+               0x66a,  "signal",       1,
+               0x66b,  "mark",         0,
+               0x66c,  "fmark",        0,
+               0x66d,  "flushreg",     0,
+               0x66f,  "syncf",        0,
+               0x670,  "emul",         3,
+               0x671,  "ediv",         3,
+               0x673,  "ldtime",       -1,
+               0x674,  "Fcvtir",       -2,
+               0x675,  "Fcvtilr",      -2,
+               0x676,  "Fscalerl",     3,
+               0x677,  "Fscaler",      3,
+               0x680,  "Fatanr",       3,
+               0x681,  "Flogepr",      3,
+               0x682,  "Flogr",        3,
+               0x683,  "Fremr",        3,
+               0x684,  "Fcmpor",       2,
+               0x685,  "Fcmpr",        2,
+               0x688,  "Fsqrtr",       -2,
+               0x689,  "Fexpr",        -2,
+               0x68a,  "Flogbnr",      -2,
+               0x68b,  "Froundr",      -2,
+               0x68c,  "Fsinr",        -2,
+               0x68d,  "Fcosr",        -2,
+               0x68e,  "Ftanr",        -2,
+               0x68f,  "Fclassr",      1,
+               0x690,  "Fatanrl",      3,
+               0x691,  "Flogeprl",     3,
+               0x692,  "Flogrl",       3,
+               0x693,  "Fremrl",       3,
+               0x694,  "Fcmporl",      2,
+               0x695,  "Fcmprl",       2,
+               0x698,  "Fsqrtrl",      -2,
+               0x699,  "Fexprl",       -2,
+               0x69a,  "Flogbnrl",     -2,
+               0x69b,  "Froundrl",     -2,
+               0x69c,  "Fsinrl",       -2,
+               0x69d,  "Fcosrl",       -2,
+               0x69e,  "Ftanrl",       -2,
+               0x69f,  "Fclassrl",     1,
+               0x6c0,  "Fcvtri",       -2,
+               0x6c1,  "Fcvtril",      -2,
+               0x6c2,  "Fcvtzri",      -2,
+               0x6c3,  "Fcvtzril",     -2,
+               0x6c9,  "Fmovr",        -2,
+               0x6d9,  "Fmovrl",       -2,
+               0x6e1,  "Fmovre",       -2,
+               0x6e2,  "Fcpysre",      3,
+               0x6e3,  "Fcpyrsre",     3,
+               0x701,  "mulo",         3,
+               0x708,  "remo",         3,
+               0x70b,  "divo",         3,
+               0x741,  "muli",         3,
+               0x748,  "remi",         3,
+               0x749,  "modi",         3,
+               0x74b,  "divi",         3,
+               0x78b,  "Fdivr",        3,
+               0x78c,  "Fmulr",        3,
+               0x78d,  "Fsubr",        3,
+               0x78f,  "Faddr",        3,
+               0x79b,  "Fdivrl",       3,
+               0x79c,  "Fmulrl",       3,
+               0x79d,  "Fsubrl",       3,
+               0x79f,  "Faddrl",       3,
+#define REG_MAX        0x79f
+#define REG_SIZ        ((REG_MAX-REG_MIN+1) * sizeof(struct tabent))
+               0,      NULL,   0
+       };
+
+       if ( reg_tab == NULL ){
+               reg_tab = (struct tabent *) xmalloc( REG_SIZ );
+               bzero( reg_tab, REG_SIZ );
+               for ( i = 0; reg_init[i].opcode != 0; i++ ){
+                       j = reg_init[i].opcode - REG_MIN;
+                       reg_tab[j].name = reg_init[i].name;
+                       reg_tab[j].numops = reg_init[i].numops;
+               }
+       }
+
+       opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf);
+       i = opcode - REG_MIN;
+
+       if ( (opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL) ){
+               invalid( word1 );
+               return;
+       }
+
+       mnemp = reg_tab[i].name;
+       if ( *mnemp == 'F' ){
+               fp = 1;
+               mnemp++;
+       } else {
+               fp = 0;
+       }
+
+       fputs( mnemp, stream );
+
+       s1   = (word1 >> 5)  & 1;
+       s2   = (word1 >> 6)  & 1;
+       m1   = (word1 >> 11) & 1;
+       m2   = (word1 >> 12) & 1;
+       m3   = (word1 >> 13) & 1;
+       src  =  word1        & 0x1f;
+       src2 = (word1 >> 14) & 0x1f;
+       dst  = (word1 >> 19) & 0x1f;
+
+       if  ( reg_tab[i].numops != 0 ){
+               putc( '\t', stream );
+
+               switch ( reg_tab[i].numops ){
+               case 1:
+                       regop( m1, s1, src, fp );
+                       break;
+               case -1:
+                       dstop( m3, dst, fp );
+                       break;
+               case 2:
+                       regop( m1, s1, src, fp );
+                       putc( ',', stream );
+                       regop( m2, s2, src2, fp );
+                       break;
+               case -2:
+                       regop( m1, s1, src, fp );
+                       putc( ',', stream );
+                       dstop( m3, dst, fp );
+                       break;
+               case 3:
+                       regop( m1, s1, src, fp );
+                       putc( ',', stream );
+                       regop( m2, s2, src2, fp );
+                       putc( ',', stream );
+                       dstop( m3, dst, fp );
+                       break;
+               }
+       }
+}
+
+
+/*
+ * Print out effective address for memb instructions.
+ */
+static void
+ea( memaddr, mode, reg2, reg3, word1, word2 )
+    unsigned long memaddr;
+    int mode;
+    char *reg2, *reg3;
+    unsigned int word2;
+{
+       int scale;
+       static int scale_tab[] = { 1, 2, 4, 8, 16 };
+
+       scale = (word1 >> 7) & 0x07;
+       if ( (scale > 4) || ((word1 >> 5) & 0x03 != 0) ){
+               invalid( word1 );
+               return;
+       }
+       scale = scale_tab[scale];
+
+       switch (mode) {
+       case 4:                                         /* (reg) */
+               fprintf( stream, "(%s)", reg2 );
+               break;
+       case 5:                                         /* displ+8(ip) */
+               print_addr( word2+8+memaddr );
+               break;
+       case 7:                                         /* (reg)[index*scale] */
+               if (scale == 1) {
+                       fprintf( stream, "(%s)[%s]", reg2, reg3 );
+               } else {
+                       fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale);
+               }
+               break;
+       case 12:                                        /* displacement */
+               print_addr( word2 );
+               break;
+       case 13:                                        /* displ(reg) */
+               print_addr( word2 );
+               fprintf( stream, "(%s)", reg2 );
+               break;
+       case 14:                                        /* displ[index*scale] */
+               print_addr( word2 );
+               if (scale == 1) {
+                       fprintf( stream, "[%s]", reg3 );
+               } else {
+                       fprintf( stream, "[%s*%d]", reg3, scale );
+               }
+               break;
+       case 15:                                /* displ(reg)[index*scale] */
+               print_addr( word2 );
+               if (scale == 1) {
+                       fprintf( stream, "(%s)[%s]", reg2, reg3 );
+               } else {
+                       fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale );
+               }
+               break;
+       default:
+               invalid( word1 );
+               return;
+       }
+}
+
+
+/************************************************/
+/* Register Instruction Operand                */
+/************************************************/
+static void
+regop( mode, spec, reg, fp )
+    int mode, spec, reg, fp;
+{
+       if ( fp ){                              /* FLOATING POINT INSTRUCTION */
+               if ( mode == 1 ){                       /* FP operand */
+                       switch ( reg ){
+                       case 0:  fputs( "fp0", stream );        break;
+                       case 1:  fputs( "fp1", stream );        break;
+                       case 2:  fputs( "fp2", stream );        break;
+                       case 3:  fputs( "fp3", stream );        break;
+                       case 16: fputs( "0f0.0", stream );      break;
+                       case 22: fputs( "0f1.0", stream );      break;
+                       default: putc( '?', stream );           break;
+                       }
+               } else {                                /* Non-FP register */
+                       fputs( reg_names[reg], stream );
+               }
+       } else {                                /* NOT FLOATING POINT */
+               if ( mode == 1 ){                       /* Literal */
+                       fprintf( stream, "%d", reg );
+               } else {                                /* Register */
+                       if ( spec == 0 ){
+                               fputs( reg_names[reg], stream );
+                       } else {
+                               fprintf( stream, "sf%d", reg );
+                       }
+               }
+       }
+}
+
+/************************************************/
+/* Register Instruction Destination Operand    */
+/************************************************/
+static void
+dstop( mode, reg, fp )
+    int mode, reg, fp;
+{
+       /* 'dst' operand can't be a literal. On non-FP instructions,  register
+        * mode is assumed and "m3" acts as if were "s3";  on FP-instructions,
+        * sf registers are not allowed so m3 acts normally.
+        */
+        if ( fp ){
+               regop( mode, 0, reg, fp );
+        } else {
+               regop( 0, mode, reg, fp );
+        }
+}
+
+
+static void
+invalid( word1 )
+    int word1;
+{
+       fprintf( stream, ".word\t0x%08x", word1 );
+}      
+
+static void
+print_addr(a)
+{
+       fprintf( stream, "0x%x", a );
+}
+
+static void
+put_abs( word1, word2 )
+    unsigned long word1, word2;
+{
+#ifdef IN_GDB
+       return;
+#else
+       int len;
+
+       switch ( (word1 >> 28) & 0xf ){
+       case 0x8:
+       case 0x9:
+       case 0xa:
+       case 0xb:
+       case 0xc:
+               /* MEM format instruction */
+               len = mem( 0, word1, word2, 1 );
+               break;
+       default:
+               len = 4;
+               break;
+       }
+
+       if ( len == 8 ){
+               fprintf( stream, "%08x %08x\t", word1, word2 );
+       } else {
+               fprintf( stream, "%08x         \t", word1 );
+       }
+;
+
+#endif
+}
diff --git a/gdb/i960-tdep.c b/gdb/i960-tdep.c
new file mode 100644 (file)
index 0000000..a82328a
--- /dev/null
@@ -0,0 +1,646 @@
+/* Target-machine dependent code for the Intel 960
+   Copyright (C) 1991 Free Software Foundation, Inc.
+   Contributed by Intel Corporation.
+   examine_prologue and other parts contributed by Wind River Systems.
+
+This file is part of GDB.
+
+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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Miscellaneous i80960-dependent routines.
+   Most are called from macros defined in "tm-i960.h".  */
+
+#include <stdio.h>
+#include <signal.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "signame.h"
+#include "ieee-float.h"
+
+/* Structure of i960 extended floating point format.  */
+
+const struct ext_format ext_format_i960 [] = {
+/* tot sbyte smask expbyte manbyte */
+ { 12, 9,    0x80, 9,8,           4,0  },              /* i960 */
+};
+
+/* gdb960 is always running on a non-960 host.  Check its characteristics.
+   This routine must be called as part of gdb initialization.  */
+
+static void
+check_host()
+{
+       int i;
+
+       static struct typestruct {
+               int hostsize;           /* Size of type on host         */
+               int i960size;           /* Size of type on i960         */
+               char *typename;         /* Name of type, for error msg  */
+       } types[] = {
+               { sizeof(short),  2, "short" },
+               { sizeof(int),    4, "int" },
+               { sizeof(long),   4, "long" },
+               { sizeof(float),  4, "float" },
+               { sizeof(double), 8, "double" },
+               { sizeof(char *), 4, "pointer" },
+       };
+#define TYPELEN        (sizeof(types) / sizeof(struct typestruct))
+
+       /* Make sure that host type sizes are same as i960
+        */
+       for ( i = 0; i < TYPELEN; i++ ){
+               if ( types[i].hostsize != types[i].i960size ){
+                       printf("sizeof(%s) != %d:  PROCEED AT YOUR OWN RISK!\n",
+                                       types[i].typename, types[i].i960size );
+               }
+
+       }
+}
+\f
+/* Examine an i960 function prologue, recording the addresses at which
+   registers are saved explicitly by the prologue code, and returning
+   the address of the first instruction after the prologue (but not
+   after the instruction at address LIMIT, as explained below).
+
+   LIMIT places an upper bound on addresses of the instructions to be
+   examined.  If the prologue code scan reaches LIMIT, the scan is
+   aborted and LIMIT is returned.  This is used, when examining the
+   prologue for the current frame, to keep examine_prologue () from
+   claiming that a given register has been saved when in fact the
+   instruction that saves it has not yet been executed.  LIMIT is used
+   at other times to stop the scan when we hit code after the true
+   function prologue (e.g. for the first source line) which might
+   otherwise be mistaken for function prologue.
+
+   The format of the function prologue matched by this routine is
+   derived from examination of the source to gcc960 1.21, particularly
+   the routine i960_function_prologue ().  A "regular expression" for
+   the function prologue is given below:
+
+   (lda LRn, g14
+    mov g14, g[0-7]
+    (mov 0, g14) | (lda 0, g14))?
+
+   (mov[qtl]? g[0-15], r[4-15])*
+   ((addo [1-31], sp, sp) | (lda n(sp), sp))?
+   (st[qtl]? g[0-15], n(fp))*
+
+   (cmpobne 0, g14, LFn
+    mov sp, g14
+    lda 0x30(sp), sp
+    LFn: stq g0, (g14)
+    stq g4, 0x10(g14)
+    stq g8, 0x20(g14))?
+
+   (st g14, n(fp))?
+   (mov g13,r[4-15])?
+*/
+
+/* Macros for extracting fields from i960 instructions.  */
+
+#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
+#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
+
+#define REG_SRC1(insn)    EXTRACT_FIELD (insn, 0, 5)
+#define REG_SRC2(insn)    EXTRACT_FIELD (insn, 14, 5)
+#define REG_SRCDST(insn)  EXTRACT_FIELD (insn, 19, 5)
+#define MEM_SRCDST(insn)  EXTRACT_FIELD (insn, 19, 5)
+#define MEMA_OFFSET(insn) EXTRACT_FIELD (insn, 0, 12)
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+   is not the address of a valid instruction, the address of the next
+   instruction beyond ADDR otherwise.  *PWORD1 receives the first word
+   of the instruction, and (for two-word instructions), *PWORD2 receives
+   the second.  */
+
+#define NEXT_PROLOGUE_INSN(addr, lim, pword1, pword2) \
+  (((addr) < (lim)) ? next_insn (addr, pword1, pword2) : 0)
+
+static CORE_ADDR
+examine_prologue (ip, limit, frame_addr, fsr)
+     register CORE_ADDR ip;
+     register CORE_ADDR limit;
+     FRAME_ADDR frame_addr;
+     struct frame_saved_regs *fsr;
+{
+  register CORE_ADDR next_ip;
+  register int src, dst;
+  register unsigned int *pcode;
+  unsigned int insn1, insn2;
+  int size;
+  int within_leaf_prologue;
+  CORE_ADDR save_addr;
+  static unsigned int varargs_prologue_code [] =
+    {
+       0x3507a00c,     /* cmpobne 0x0, g14, LFn */
+       0x5cf01601,     /* mov sp, g14           */
+       0x8c086030,     /* lda 0x30(sp), sp      */
+       0xb2879000,     /* LFn: stq  g0, (g14)   */
+       0xb2a7a010,     /* stq g4, 0x10(g14)     */
+       0xb2c7a020      /* stq g8, 0x20(g14)     */
+    };
+
+  /* Accept a leaf procedure prologue code fragment if present.
+     Note that ip might point to either the leaf or non-leaf
+     entry point; we look for the non-leaf entry point first:  */
+
+  within_leaf_prologue = 0;
+  if ((next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2))
+      && ((insn1 & 0xfffff000) == 0x8cf00000         /* lda LRx, g14 (MEMA) */
+         || (insn1 & 0xfffffc60) == 0x8cf03000))    /* lda LRx, g14 (MEMB) */
+    {
+      within_leaf_prologue = 1;
+      next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2);
+    }
+
+  /* Now look for the prologue code at a leaf entry point:  */
+
+  if (next_ip
+      && (insn1 & 0xff87ffff) == 0x5c80161e         /* mov g14, gx */
+      && REG_SRCDST (insn1) <= G0_REGNUM + 7)
+    {
+      within_leaf_prologue = 1;
+      if ((next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2))
+         && (insn1 == 0x8cf00000                   /* lda 0, g14 */
+             || insn1 == 0x5cf01e00))              /* mov 0, g14 */
+       {
+         ip = next_ip;
+         next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+         within_leaf_prologue = 0;
+       }
+    }
+
+  /* If something that looks like the beginning of a leaf prologue
+     has been seen, but the remainder of the prologue is missing, bail.
+     We don't know what we've got.  */
+
+  if (within_leaf_prologue)
+    return (ip);
+         
+  /* Accept zero or more instances of "mov[qtl]? gx, ry", where y >= 4.
+     This may cause us to mistake the moving of a register
+     parameter to a local register for the saving of a callee-saved
+     register, but that can't be helped, since with the
+     "-fcall-saved" flag, any register can be made callee-saved.  */
+
+  while (next_ip
+        && (insn1 & 0xfc802fb0) == 0x5c000610
+        && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))
+    {
+      src = REG_SRC1 (insn1);
+      size = EXTRACT_FIELD (insn1, 24, 2) + 1;
+      save_addr = frame_addr + ((dst - R0_REGNUM) * 4);
+      while (size--)
+       {
+         fsr->regs[src++] = save_addr;
+         save_addr += 4;
+       }
+      ip = next_ip;
+      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+    }
+
+  /* Accept an optional "addo n, sp, sp" or "lda n(sp), sp".  */
+
+  if (next_ip &&
+      ((insn1 & 0xffffffe0) == 0x59084800      /* addo n, sp, sp */
+       || (insn1 & 0xfffff000) == 0x8c086000   /* lda n(sp), sp (MEMA) */
+       || (insn1 & 0xfffffc60) == 0x8c087400)) /* lda n(sp), sp (MEMB) */
+    {
+      ip = next_ip;
+      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+    }
+
+  /* Accept zero or more instances of "st[qtl]? gx, n(fp)".  
+     This may cause us to mistake the copying of a register
+     parameter to the frame for the saving of a callee-saved
+     register, but that can't be helped, since with the
+     "-fcall-saved" flag, any register can be made callee-saved.
+     We can, however, refuse to accept a save of register g14,
+     since that is matched explicitly below.  */
+
+  while (next_ip &&
+        ((insn1 & 0xf787f000) == 0x9287e000      /* stl? gx, n(fp) (MEMA) */
+         || (insn1 & 0xf787fc60) == 0x9287f400   /* stl? gx, n(fp) (MEMB) */
+         || (insn1 & 0xef87f000) == 0xa287e000   /* st[tq] gx, n(fp) (MEMA) */
+         || (insn1 & 0xef87fc60) == 0xa287f400)  /* st[tq] gx, n(fp) (MEMB) */
+        && ((src = MEM_SRCDST (insn1)) != G14_REGNUM))
+    {
+      save_addr = frame_addr + ((insn1 & BITMASK (12, 1))
+                               ? insn2 : MEMA_OFFSET (insn1));
+      size = (insn1 & BITMASK (29, 1)) ? ((insn1 & BITMASK (28, 1)) ? 4 : 3)
+                                      : ((insn1 & BITMASK (27, 1)) ? 2 : 1);
+      while (size--)
+       {
+         fsr->regs[src++] = save_addr;
+         save_addr += 4;
+       }
+      ip = next_ip;
+      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+    }
+
+  /* Accept the varargs prologue code if present.  */
+
+  size = sizeof (varargs_prologue_code) / sizeof (int);
+  pcode = varargs_prologue_code;
+  while (size-- && next_ip && *pcode++ == insn1)
+    {
+      ip = next_ip;
+      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+    }
+
+  /* Accept an optional "st g14, n(fp)".  */
+
+  if (next_ip &&
+      ((insn1 & 0xfffff000) == 0x92f7e000       /* st g14, n(fp) (MEMA) */
+       || (insn1 & 0xfffffc60) == 0x92f7f400))   /* st g14, n(fp) (MEMB) */
+    {
+      fsr->regs[G14_REGNUM] = frame_addr + ((insn1 & BITMASK (12, 1))
+                                           ? insn2 : MEMA_OFFSET (insn1));
+      ip = next_ip;
+      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+    }
+
+  /* Accept zero or one instance of "mov g13, ry", where y >= 4.
+     This is saving the address where a struct should be returned.  */
+
+  if (next_ip
+      && (insn1 & 0xff802fbf) == 0x5c00061d
+      && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))
+    {
+      save_addr = frame_addr + ((dst - R0_REGNUM) * 4);
+      fsr->regs[G0_REGNUM+13] = save_addr;
+      ip = next_ip;
+#if 0  /* We'll need this once there is a subsequent instruction examined. */
+      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+#endif
+    }
+
+  return (ip);
+}
+
+/* Given an ip value corresponding to the start of a function,
+   return the ip of the first instruction after the function 
+   prologue.  */
+
+CORE_ADDR
+skip_prologue (ip)
+     CORE_ADDR (ip);
+{
+  struct frame_saved_regs saved_regs_dummy;
+  struct symtab_and_line sal;
+  CORE_ADDR limit;
+
+  sal = find_pc_line (ip, 0);
+  limit = (sal.end) ? sal.end : 0xffffffff;
+
+  return (examine_prologue (ip, limit, (FRAME_ADDR) 0, &saved_regs_dummy));
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.
+
+   We cache the result of doing this in the frame_cache_obstack, since
+   it is fairly expensive.  */
+
+void
+frame_find_saved_regs (fi, fsr)
+     struct frame_info *fi;
+     struct frame_saved_regs *fsr;
+{
+  register CORE_ADDR next_addr;
+  register CORE_ADDR *saved_regs;
+  register int regnum;
+  register struct frame_saved_regs *cache_fsr;
+  extern struct obstack frame_cache_obstack;
+  CORE_ADDR ip;
+  struct symtab_and_line sal;
+  CORE_ADDR limit;
+
+  if (!fi->fsr)
+    {
+      cache_fsr = (struct frame_saved_regs *)
+                 obstack_alloc (&frame_cache_obstack,
+                                sizeof (struct frame_saved_regs));
+      bzero (cache_fsr, sizeof (struct frame_saved_regs));
+      fi->fsr = cache_fsr;
+
+      /* Find the start and end of the function prologue.  If the PC
+        is in the function prologue, we only consider the part that
+        has executed already.  */
+         
+      ip = get_pc_function_start (fi->pc);
+      sal = find_pc_line (ip, 0);
+      limit = (sal.end && sal.end < fi->pc) ? sal.end: fi->pc;
+
+      examine_prologue (ip, limit, fi->frame, cache_fsr);
+
+      /* Record the addresses at which the local registers are saved.
+        Strictly speaking, we should only do this for non-leaf procedures,
+        but no one will ever look at these values if it is a leaf procedure,
+        since local registers are always caller-saved.  */
+
+      next_addr = (CORE_ADDR) fi->frame;
+      saved_regs = cache_fsr->regs;
+      for (regnum = R0_REGNUM; regnum <= R15_REGNUM; regnum++)
+       {
+         *saved_regs++ = next_addr;
+         next_addr += 4;
+       }
+
+      cache_fsr->regs[FP_REGNUM] = cache_fsr->regs[PFP_REGNUM];
+    }
+
+  *fsr = *fi->fsr;
+
+  /* Fetch the value of the sp from memory every time, since it
+     is conceivable that it has changed since the cache was flushed.  
+     This unfortunately undoes much of the savings from caching the 
+     saved register values.  I suggest adding an argument to 
+     get_frame_saved_regs () specifying the register number we're
+     interested in (or -1 for all registers).  This would be passed
+     through to FRAME_FIND_SAVED_REGS (), permitting more efficient
+     computation of saved register addresses (e.g., on the i960,
+     we don't have to examine the prologue to find local registers). 
+       -- markf@wrs.com 
+     FIXME, we don't need to refetch this, since the cache is cleared
+     every time the child process is restarted.  If GDB itself
+     modifies SP, it has to clear the cache by hand (does it?).  -gnu */
+
+  fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[SP_REGNUM], 4);
+}
+
+/* Return the address of the argument block for the frame
+   described by FI.  Returns 0 if the address is unknown.  */
+
+CORE_ADDR
+frame_args_address (fi, must_be_correct)
+     struct frame_info *fi;
+{
+  register FRAME frame;
+  struct frame_saved_regs fsr;
+  CORE_ADDR ap;
+
+  /* If g14 was saved in the frame by the function prologue code, return
+     the saved value.  If the frame is current and we are being sloppy,
+     return the value of g14.  Otherwise, return zero.  */
+
+  frame = FRAME_INFO_ID (fi);
+  get_frame_saved_regs (fi, &fsr);
+  if (fsr.regs[G14_REGNUM])
+    ap = read_memory_integer (fsr.regs[G14_REGNUM],4);
+  else {
+    if (must_be_correct)
+      return 0;                        /* Don't cache this result */
+    if (get_next_frame (frame))
+      ap = 0;
+    else
+      ap = read_register (G14_REGNUM);
+  }
+  fi->arg_pointer = ap;                /* Cache it for next time */
+  return ap;
+}
+
+/* Return the address of the return struct for the frame
+   described by FI.  Returns 0 if the address is unknown.  */
+
+CORE_ADDR
+frame_struct_result_address (fi)
+     struct frame_info *fi;
+{
+  register FRAME frame;
+  struct frame_saved_regs fsr;
+  CORE_ADDR ap;
+
+  /* If the frame is non-current, check to see if g14 was saved in the
+     frame by the function prologue code; return the saved value if so,
+     zero otherwise.  If the frame is current, return the value of g14.
+
+     FIXME, shouldn't this use the saved value as long as we are past
+     the function prologue, and only use the current value if we have
+     no saved value and are at TOS?   -- gnu@cygnus.com */
+
+  frame = FRAME_INFO_ID (fi);
+  if (get_next_frame (frame)) {
+    get_frame_saved_regs (fi, &fsr);
+    if (fsr.regs[G13_REGNUM])
+      ap = read_memory_integer (fsr.regs[G13_REGNUM],4);
+    else
+      ap = 0;
+  } else {
+    ap = read_register (G13_REGNUM);
+  }
+  return ap;
+}
+
+/* Return address to which the currently executing leafproc will return,
+   or 0 if ip is not in a leafproc (or if we can't tell if it is).
+  
+   Do this by finding the starting address of the routine in which ip lies.
+   If the instruction there is "mov g14, gx" (where x is in [0,7]), this
+   is a leafproc and the return address is in register gx.  Well, this is
+   true unless the return address points at a RET instruction in the current
+   procedure, which indicates that we have a 'dual entry' routine that
+   has been entered through the CALL entry point.  */
+
+CORE_ADDR
+leafproc_return (ip)
+     CORE_ADDR ip;     /* ip from currently executing function */
+{
+  int i;
+  register struct misc_function *mf;
+  char *p;
+  int dst;
+  unsigned int insn1, insn2;
+  CORE_ADDR return_addr;
+  char *index ();
+
+  if ((i = find_pc_misc_function (ip)) >= 0)
+    {
+      mf = &misc_function_vector[i];
+      if ((p = index (mf->name, '.')) && !strcmp (p, ".lf"))
+       {
+         if (next_insn (mf->address, &insn1, &insn2)
+             && (insn1 & 0xff87ffff) == 0x5c80161e       /* mov g14, gx */
+             && (dst = REG_SRCDST (insn1)) <= G0_REGNUM + 7)
+           {
+             /* Get the return address.  If the "mov g14, gx" 
+                instruction hasn't been executed yet, read
+                the return address from g14; otherwise, read it
+                from the register into which g14 was moved.  */
+
+             return_addr = read_register ((ip == mf->address)
+                                          ? G14_REGNUM : dst);
+
+             /* We know we are in a leaf procedure, but we don't know
+                whether the caller actually did a "bal" to the ".lf"
+                entry point, or a normal "call" to the non-leaf entry
+                point one instruction before.  In the latter case, the
+                return address will be the address of a "ret"
+                instruction within the procedure itself.  We test for
+                this below.  */
+
+             if (!next_insn (return_addr, &insn1, &insn2)
+                 || (insn1 & 0xff000000) != 0xa000000   /* ret */
+                 || find_pc_misc_function (return_addr) != i)
+               return (return_addr);
+           }
+       }
+    }
+  
+  return (0);
+}
+
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions. 
+   On the i960, the frame *is* set up immediately after the call,
+   unless the function is a leaf procedure.  */
+
+CORE_ADDR
+saved_pc_after_call (frame)
+     FRAME frame;
+{
+  CORE_ADDR saved_pc;
+  CORE_ADDR get_frame_pc ();
+
+  saved_pc = leafproc_return (get_frame_pc (frame));
+  if (!saved_pc)
+    saved_pc = FRAME_SAVED_PC (frame);
+
+  return (saved_pc);
+}
+
+/* Discard from the stack the innermost frame,
+   restoring all saved registers.  */
+
+pop_frame ()
+{
+  register struct frame_info *current_fi, *prev_fi;
+  register int i;
+  CORE_ADDR save_addr;
+  CORE_ADDR leaf_return_addr;
+  struct frame_saved_regs fsr;
+  char local_regs_buf[16 * 4];
+
+  current_fi = get_frame_info (get_current_frame ());
+
+  /* First, undo what the hardware does when we return.
+     If this is a non-leaf procedure, restore local registers from
+     the save area in the calling frame.  Otherwise, load the return
+     address obtained from leafproc_return () into the rip.  */
+
+  leaf_return_addr = leafproc_return (current_fi->pc);
+  if (!leaf_return_addr)
+    {
+      /* Non-leaf procedure.  Restore local registers, incl IP.  */
+      prev_fi = get_frame_info (get_prev_frame (FRAME_INFO_ID (current_fi)));
+      read_memory (prev_fi->frame, local_regs_buf, sizeof (local_regs_buf));
+      write_register_bytes (REGISTER_BYTE (R0_REGNUM), local_regs_buf, 
+                           sizeof (local_regs_buf));
+
+      /* Restore frame pointer.  */
+      write_register (FP_REGNUM, prev_fi->frame);
+    }
+  else
+    {
+      /* Leaf procedure.  Just restore the return address into the IP.  */
+      write_register (RIP_REGNUM, leaf_return_addr);
+    }
+
+  /* Now restore any global regs that the current function had saved. */
+  get_frame_saved_regs (current_fi, &fsr);
+  for (i = G0_REGNUM; i < G14_REGNUM; i++)
+    {
+      if (save_addr = fsr.regs[i])
+       write_register (i, read_memory_integer (save_addr, 4));
+    }
+
+  /* Flush the frame cache, create a frame for the new innermost frame,
+     and make it the current frame.  */
+
+  flush_cached_frames ();
+  set_current_frame (create_new_frame (read_register (FP_REGNUM), read_pc ()));
+}
+
+/* Print out text describing a "signal number" with which the i80960 halted.
+  
+   See the file "fault.c" in the nindy monitor source code for a list
+   of stop codes.  */
+
+void
+print_fault( siggnal )
+    int siggnal;       /* Signal number, as returned by target_wait() */
+{
+       static char unknown[] = "Unknown fault or trace";
+       static char *sigmsgs[] = {
+               /* FAULTS */
+               "parallel fault",       /* 0x00 */
+               unknown,                /* 0x01 */
+               "operation fault",      /* 0x02 */
+               "arithmetic fault",     /* 0x03 */
+               "floating point fault", /* 0x04 */
+               "constraint fault",     /* 0x05 */
+               "virtual memory fault", /* 0x06 */
+               "protection fault",     /* 0x07 */
+               "machine fault",        /* 0x08 */
+               "structural fault",     /* 0x09 */
+               "type fault",           /* 0x0a */
+               "reserved (0xb) fault", /* 0x0b */
+               "process fault",        /* 0x0c */
+               "descriptor fault",     /* 0x0d */
+               "event fault",          /* 0x0e */
+               "reserved (0xf) fault", /* 0x0f */
+
+               /* TRACES */
+               "single-step trace",    /* 0x10 */
+               "branch trace",         /* 0x11 */
+               "call trace",           /* 0x12 */
+               "return trace",         /* 0x13 */
+               "pre-return trace",     /* 0x14 */
+               "supervisor call trace",/* 0x15 */
+               "breakpoint trace",     /* 0x16 */
+       };
+#      define NUMMSGS ((int)( sizeof(sigmsgs) / sizeof(sigmsgs[0]) ))
+
+       if (siggnal < NSIG) {
+             printf ("\nProgram received signal %d, %s\n",
+                     siggnal,
+                     sys_siglist[siggnal]);
+       } else {
+               /* The various target_wait()s bias the 80960 "signal number"
+                  by adding NSIG to it, so it won't get confused with any
+                  of the Unix signals elsewhere in GDB.  We need to
+                  "unbias" it before using it.  */
+               siggnal -= NSIG;
+
+               printf("Program stopped for reason #%d: %s.\n", siggnal,
+                               (siggnal < NUMMSGS && siggnal >= 0)?
+                               sigmsgs[siggnal] : unknown );
+       }
+}
+
+/* Initialization stub */
+
+_initialize_i960_tdep ()
+{
+  check_host ();
+}
diff --git a/gdb/ieee-float.c b/gdb/ieee-float.c
new file mode 100644 (file)
index 0000000..7b7f9f1
--- /dev/null
@@ -0,0 +1,141 @@
+/* IEEE floating point support routines, for GDB, the GNU Debugger.
+   Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+#include "ieee-float.h"
+#include <math.h>              /* ldexp */
+
+/* Convert an IEEE extended float to a double.
+   FROM is the address of the extended float.
+   Store the double in *TO.  */
+
+void
+ieee_extended_to_double (ext_format, from, to)
+     struct ext_format *ext_format;
+     char *from;
+     double *to;
+{
+  unsigned char *ufrom = (unsigned char *)from;
+  double dto;
+  unsigned long mant0, mant1, exp;
+  
+  bcopy (&from[MANBYTE_H], &mant0, 4);
+  bcopy (&from[MANBYTE_L], &mant1, 4);
+  exp = ((ufrom[EXPBYTE_H] & (unsigned char)~SIGNMASK) << 8) | ufrom[EXPBYTE_L];
+
+  if (exp == EXT_EXP_NAN) {
+    /* We have a NaN source.  */
+    dto = 0.123456789; /* Not much else useful to do */
+  } else if (exp == 0 && mant0 == 0 && mant1 == 0) {
+    dto = 0;
+  } else {
+    /* Build the result algebraically.  Might go infinite, underflow, etc;
+       who cares. */
+    mant0 |= 0x80000000;
+    dto = ldexp  ((double)mant0, exp - EXT_EXP_BIAS - 31);
+    dto += ldexp ((double)mant1, exp - EXT_EXP_BIAS - 31 - 32);
+  }
+  *to = dto;
+}
+
+/* The converse: convert the double *FROM to an extended float
+   and store where TO points.  */
+
+void
+double_to_ieee_extended (ext_format, from, to)
+     struct ext_format *ext_format;
+     double *from;
+     char *to;
+{
+  double dfrom = *from;
+  unsigned long twolongs[2];
+  unsigned long mant0, mant1, exp;
+  unsigned char twobytes[2];
+
+  bzero (to, TOTALSIZE);
+  if (dfrom == 0)
+    return;                    /* Result is zero */
+  if (dfrom != dfrom) {
+    /* From is NaN */
+    to[EXPBYTE_H] = (unsigned char)(EXT_EXP_NAN >> 8);
+    to[EXPBYTE_L] = (unsigned char)EXT_EXP_NAN;
+    to[MANBYTE_H] = 1; /* Be sure it's not infinity, but NaN value is irrel */
+    return;                    /* Result is NaN */
+  }
+  if (dfrom < 0)
+    to[SIGNBYTE] |= SIGNMASK;  /* Set negative sign */
+  /* How to tell an infinity from an ordinary number?  FIXME-someday */
+
+  /* The following code assumes that the host has IEEE doubles.  FIXME-someday.
+     It also assumes longs are 32 bits!  FIXME-someday.  */
+  bcopy (from, twolongs, 8);
+  bcopy (from, twobytes, 2);
+#if HOST_BYTE_ORDER == BIG_ENDIAN
+  exp = ((twobytes[1] & 0xF0) >> 4) | (twobytes[0] & 0x7F) << 4;
+  mant0 = (twolongs[0] << 11) | twolongs[1] >> 21;
+  mant1 = (twolongs[1] << 11);
+#else
+  exp = ((twobytes[0] & 0xF0) >> 4) | (twobytes[1] & 0x7F) << 4;
+  mant0 = (twolongs[1] << 11) | twolongs[0] >> 21;
+  mant1 = (twolongs[0] << 11);
+#endif
+
+  /* Fiddle with leading 1-bit, implied in double, explicit in extended. */
+  if (exp == 0)
+    mant0 &= 0x7FFFFFFF;
+  else
+    mant0 |= 0x80000000;
+
+  exp -= DBL_EXP_BIAS;                         /* Get integer exp */
+  exp += EXT_EXP_BIAS;                         /* Offset for extended *&/
+
+  /* OK, now store it in extended format. */
+  to[EXPBYTE_H] |= (unsigned char)(exp >> 8);  /* Retain sign */
+  to[EXPBYTE_L] =  (unsigned char) exp;
+  
+  bcopy (&mant0, &to[MANBYTE_H], 4);
+  bcopy (&mant1, &to[MANBYTE_L], 4);
+}
+
+
+#ifdef DEBUG
+
+/* Test some numbers to see that extended/double conversion works for them.  */
+
+ieee_test (n)
+     int n;
+{
+  union { double d; int i[2]; } di;
+  double result;
+  int i;
+  char exten[16];
+  extern struct ext_format ext_format_68881;
+
+  for (i = 0; i < n; i++) {
+    di.i[0] = random();
+    di.i[1] = random();
+    double_to_ieee_extended (ext_format_68881, &di.d, exten);
+    ieee_extended_to_double (ext_format_68881, exten, &result);
+    if (di.d != result)
+      printf ("Differ: %x %x %g => %x %x %g\n", di.d, di.d, result, result);
+  }
+}
+
+#endif
diff --git a/gdb/ieee-float.h b/gdb/ieee-float.h
new file mode 100644 (file)
index 0000000..9325518
--- /dev/null
@@ -0,0 +1,66 @@
+/* IEEE floating point support declarations, for GDB, the GNU Debugger.
+   Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Parameters for extended float format:  */
+
+struct ext_format {
+  unsigned totalsize;          /* Total size of extended number */
+  unsigned signbyte;           /* Byte number of sign bit */
+  unsigned char signmask;      /* Mask for sign bit */
+  unsigned expbyte_h;          /* High byte of exponent */
+  unsigned expbyte_l;          /* Low  byte of exponent */
+  unsigned manbyte_h;          /* High byte of mantissa */
+  unsigned manbyte_l;          /* Low  byte of mantissa */
+};
+
+#define        TOTALSIZE       ext_format->totalsize
+#define        SIGNBYTE        ext_format->signbyte
+#define        SIGNMASK        ext_format->signmask
+#define EXPBYTE_H      ext_format->expbyte_h
+#define EXPBYTE_L      ext_format->expbyte_l
+#define        MANBYTE_H       ext_format->manbyte_h
+#define        MANBYTE_L       ext_format->manbyte_l
+
+/* Actual ext_format structs for various machines are in the *-tdep.c file
+   for each machine.  */
+
+#define        EXT_EXP_NAN     0x7FFF  /* Exponent value that indicates NaN */
+#define        EXT_EXP_BIAS    0x3FFF  /* Amount added to "true" exponent for ext */
+#define        DBL_EXP_BIAS     0x3FF  /* Ditto, for doubles */
+
+/* Convert an IEEE extended float to a double.
+   FROM is the address of the extended float.
+   Store the double in *TO.  */
+
+extern void
+ieee_extended_to_double (
+#ifdef __STDC__
+       struct ext_format *ext_format, char *from, double *to
+#endif
+);
+
+/* The converse: convert the double *FROM to an extended float
+   and store where TO points.  */
+
+void
+double_to_ieee_extended (
+#ifdef __STDC__
+       struct ext_format *ext_format, double *from, char *to
+#endif
+);
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
new file mode 100644 (file)
index 0000000..e3f86d4
--- /dev/null
@@ -0,0 +1,1088 @@
+/* Memory-access and commands for inferior process, for GDB.
+   Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "target.h"
+
+extern char *sys_siglist[];
+
+extern void until_break_command ();    /* breakpoint.c */
+
+#define ERROR_NO_INFERIOR \
+   if (!target_has_execution) error ("The program is not being run.");
+
+/* String containing arguments to give to the program, separated by spaces.
+   Empty string (pointer to '\0') means no args.  */
+
+static char *inferior_args;
+
+/* File name for default use for standard in/out in the inferior.  */
+
+char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now.
+   Since various parts of infrun.c test this to see whether there is a program
+   being debugged it should be nonzero (currently 3 is used) for remote
+   debugging.  */
+
+int inferior_pid;
+
+/* Last signal that the inferior received (why it stopped).  */
+
+int stop_signal;
+
+/* Address at which inferior stopped.  */
+
+CORE_ADDR stop_pc;
+
+/* Stack frame when program stopped.  */
+
+FRAME_ADDR stop_frame_address;
+
+/* Chain containing status of breakpoint(s) that we have stopped at.  */
+
+bpstat stop_bpstat;
+
+/* Flag indicating that a command has proceeded the inferior past the
+   current breakpoint.  */
+
+int breakpoint_proceeded;
+
+/* Nonzero if stopped due to a step command.  */
+
+int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine.  */
+
+int stop_stack_dummy;
+
+/* Nonzero if stopped due to a random (unexpected) signal in inferior
+   process.  */
+
+int stopped_by_random_signal;
+
+/* Range to single step within.
+   If this is nonzero, respond to a single-step signal
+   by continuing to step if the pc is in this range.  */
+
+CORE_ADDR step_range_start; /* Inclusive */
+CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+   This is how we know when we step into a subroutine call,
+   and how to set the frame for the breakpoint used to step out.  */
+
+FRAME_ADDR step_frame_address;
+
+/* 1 means step over all subroutine calls.
+   -1 means step over calls to undebuggable functions.  */
+
+int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+   so don't print frame next time inferior stops
+   if it stops due to stepping.  */
+
+int step_multi;
+
+/* Environment to use for running inferior,
+   in format described in environ.h.  */
+
+struct environ *inferior_environ;
+
+CORE_ADDR read_pc ();
+void breakpoint_clear_ignore_counts ();
+
+\f
+void
+tty_command (file, from_tty)
+     char *file;
+     int from_tty;
+{
+  if (file == 0)
+    error_no_arg ("terminal name for running target process");
+
+  inferior_io_terminal = savestring (file, strlen (file));
+}
+
+static void
+run_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file;
+
+  dont_repeat ();
+
+  if (inferior_pid)
+    {
+      if (
+         !query ("The program being debugged has been started already.\n\
+Start it from the beginning? "))
+       error ("Program not restarted.");
+      target_kill ((char *)0, 0);
+    }
+
+  exec_file = (char *) get_exec_file (0);
+
+  /* The exec file is re-read every time we do an inferior_died, so
+     we just have to worry about the symbol file.  */
+  reread_symbols ();
+
+  if (args)
+    {
+      char *cmd;
+      cmd = concat ("set args ", args, "");
+      make_cleanup (free, cmd);
+      execute_command (cmd, from_tty);
+    }
+
+  if (from_tty)
+    {
+      printf ("Starting program: %s %s\n",
+             exec_file? exec_file: "", inferior_args);
+      fflush (stdout);
+    }
+
+  target_create_inferior (exec_file, inferior_args,
+                         environ_vector (inferior_environ));
+}
+\f
+void
+continue_command (proc_count_exp, from_tty)
+     char *proc_count_exp;
+     int from_tty;
+{
+  ERROR_NO_INFERIOR;
+
+  /* If have argument, set proceed count of breakpoint we stopped at.  */
+
+  if (proc_count_exp != NULL)
+    {
+      bpstat bs = stop_bpstat;
+      int num = bpstat_num (&bs);
+      if (num == 0 && from_tty)
+       {
+         printf_filtered
+           ("Not stopped at any breakpoint; argument ignored.\n");
+       }
+      while (num != 0)
+       {
+         set_ignore_count (num,
+                           parse_and_eval_address (proc_count_exp) - 1,
+                           from_tty);
+         /* set_ignore_count prints a message ending with a period.
+            So print two spaces before "Continuing.".  */
+         if (from_tty)
+           printf ("  ");
+         num = bpstat_num (&bs);
+       }
+    }
+
+  if (from_tty)
+    printf ("Continuing.\n");
+
+  clear_proceed_status ();
+
+  proceed ((CORE_ADDR) -1, -1, 0);
+}
+\f
+/* Step until outside of current statement.  */
+static void step_1 ();
+
+static void
+step_command (count_string, from_tty)
+     char * count_string;
+     int from_tty;
+{
+  step_1 (0, 0, count_string);
+}
+
+/* Likewise, but skip over subroutine calls as if single instructions.  */
+
+static void
+next_command (count_string, from_tty)
+     char * count_string;
+     int from_tty;
+{
+  step_1 (1, 0, count_string);
+}
+
+/* Likewise, but step only one instruction.  */
+
+static void
+stepi_command (count_string, from_tty)
+     char * count_string;
+     int from_tty;
+{
+  step_1 (0, 1, count_string);
+}
+
+static void
+nexti_command (count_string, from_tty)
+     char * count_string;
+     int from_tty;
+{
+  step_1 (1, 1, count_string);
+}
+
+static void
+step_1 (skip_subroutines, single_inst, count_string)
+     int skip_subroutines;
+     int single_inst;
+     char *count_string;
+{
+  register int count = 1;
+  FRAME fr;
+
+  ERROR_NO_INFERIOR;
+  count = count_string ? parse_and_eval_address (count_string) : 1;
+
+  for (; count > 0; count--)
+    {
+      clear_proceed_status ();
+
+
+      fr = get_current_frame ();
+      if (!fr)                         /* Avoid coredump here.  Why tho? */
+       error ("No current frame");
+      step_frame_address = FRAME_FP (fr);
+
+      if (! single_inst)
+       {
+         find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
+         if (step_range_end == 0)
+           {
+             int misc;
+
+             misc = find_pc_misc_function (stop_pc);
+             target_terminal_ours ();
+             printf ("Current function has no line number information.\n");
+             fflush (stdout);
+
+             /* No info or after _etext ("Can't happen") */
+             if (misc == -1 || misc == misc_function_count - 1)
+               error ("No data available on pc function.");
+
+             printf ("Single stepping until function exit.\n");
+             fflush (stdout);
+
+             step_range_start = misc_function_vector[misc].address;
+             step_range_end = misc_function_vector[misc + 1].address;
+           }
+       }
+      else
+       {
+         /* Say we are stepping, but stop after one insn whatever it does.
+            Don't step through subroutine calls even to undebuggable
+            functions.  */
+         step_range_start = step_range_end = 1;
+         if (!skip_subroutines)
+           step_over_calls = 0;
+       }
+
+      if (skip_subroutines)
+       step_over_calls = 1;
+
+      step_multi = (count > 1);
+      proceed ((CORE_ADDR) -1, -1, 1);
+      if (! stop_step)
+       break;
+#if defined (SHIFT_INST_REGS)
+      write_register (NNPC_REGNUM, read_register (NPC_REGNUM));
+      write_register (NPC_REGNUM, read_register (PC_REGNUM));
+#endif
+    }
+}
+\f
+/* Continue program at specified address.  */
+
+static void
+jump_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register CORE_ADDR addr;
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+
+  ERROR_NO_INFERIOR;
+
+  if (!arg)
+    error_no_arg ("starting address");
+
+  sals = decode_line_spec_1 (arg, 1);
+  if (sals.nelts != 1)
+    {
+      error ("Unreasonable jump request");
+    }
+
+  sal = sals.sals[0];
+  free (sals.sals);
+
+  if (sal.symtab == 0 && sal.pc == 0)
+    error ("No source file has been specified.");
+
+  if (sal.pc == 0)
+    sal.pc = find_line_pc (sal.symtab, sal.line);
+
+  {
+    struct symbol *fn = get_frame_function (get_current_frame ());
+    struct symbol *sfn = find_pc_function (sal.pc);
+    if (fn != 0 && sfn != fn
+       && ! query ("Line %d is not in `%s'.  Jump anyway? ",
+                   sal.line, SYMBOL_NAME (fn)))
+      error ("Not confirmed.");
+  }
+
+  if (sal.pc == 0)
+    error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
+
+  addr = ADDR_BITS_SET (sal.pc);
+
+  if (from_tty)
+    printf ("Continuing at 0x%x.\n", addr);
+
+  clear_proceed_status ();
+  proceed (addr, 0, 0);
+}
+
+/* Continue program giving it specified signal.  */
+
+static void
+signal_command (signum_exp, from_tty)
+     char *signum_exp;
+     int from_tty;
+{
+  register int signum;
+
+  dont_repeat ();              /* Too dangerous.  */
+  ERROR_NO_INFERIOR;
+
+  if (!signum_exp)
+    error_no_arg ("signal number");
+
+  signum = parse_and_eval_address (signum_exp);
+
+  if (from_tty)
+    printf ("Continuing with signal %d.\n", signum);
+
+  clear_proceed_status ();
+  proceed (stop_pc, signum, 0);
+}
+
+/* Execute a "stack dummy", a piece of code stored in the stack
+   by the debugger to be executed in the inferior.
+
+   To call: first, do PUSH_DUMMY_FRAME.
+   Then push the contents of the dummy.  It should end with a breakpoint insn.
+   Then call here, passing address at which to start the dummy.
+
+   The contents of all registers are saved before the dummy frame is popped
+   and copied into the buffer BUFFER.
+
+   The dummy's frame is automatically popped whenever that break is hit.
+   If that is the first time the program stops, run_stack_dummy
+   returns to its caller with that frame already gone.
+   Otherwise, the caller never gets returned to.  */
+
+/* 4 => return instead of letting the stack dummy run.  */
+
+static int stack_dummy_testing = 0;
+
+void
+run_stack_dummy (addr, buffer)
+     CORE_ADDR addr;
+     char buffer[REGISTER_BYTES];
+{
+  /* Now proceed, having reached the desired place.  */
+  clear_proceed_status ();
+  if (stack_dummy_testing & 4)
+    {
+      POP_FRAME;
+      return;
+    }
+  proceed_to_finish = 1;       /* We want stop_registers, please... */
+  proceed (addr, 0, 0);
+
+  if (!stop_stack_dummy)
+    /* This used to say
+       "Cannot continue previously requested operation".  */
+    error ("\
+The program being debugged stopped while in a function called from GDB.\n\
+The expression which contained the function call has been discarded.");
+
+  /* On return, the stack dummy has been popped already.  */
+
+  bcopy (stop_registers, buffer, sizeof stop_registers);
+}
+\f
+/* Proceed until we reach a different source line with pc greater than
+   our current one or exit the function.  We skip calls in both cases.
+
+   Note that eventually this command should probably be changed so
+   that only source lines are printed out when we hit the breakpoint
+   we set.  I'm going to postpone this until after a hopeful rewrite
+   of wait_for_inferior and the proceed status code. -- randy */
+
+void
+until_next_command (from_tty)
+     int from_tty;
+{
+  FRAME frame;
+  CORE_ADDR pc;
+  struct symbol *func;
+  struct symtab_and_line sal;
+  clear_proceed_status ();
+
+  frame = get_current_frame ();
+
+  /* Step until either exited from this function or greater
+     than the current line (if in symbolic section) or pc (if
+     not). */
+
+  pc = read_pc ();
+  func = find_pc_function (pc);
+  
+  if (!func)
+    {
+      int misc_func = find_pc_misc_function (pc);
+      
+      if (misc_func != -1)
+       error ("Execution is not within a known function.");
+      
+      step_range_start = misc_function_vector[misc_func].address;
+      step_range_end = pc;
+    }
+  else
+    {
+      sal = find_pc_line (pc, 0);
+      
+      step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
+      step_range_end = sal.end;
+    }
+  
+  step_over_calls = 1;
+  step_frame_address = FRAME_FP (frame);
+  
+  step_multi = 0;              /* Only one call to proceed */
+  
+  proceed ((CORE_ADDR) -1, -1, 1);
+}
+
+void 
+until_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  if (!target_has_execution)
+    error ("The program is not running.");
+  if (arg)
+    until_break_command (arg, from_tty);
+  else
+    until_next_command (from_tty);
+}
+\f
+/* "finish": Set a temporary breakpoint at the place
+   the selected frame will return to, then continue.  */
+
+static void
+finish_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtab_and_line sal;
+  register FRAME frame;
+  struct frame_info *fi;
+  register struct symbol *function;
+
+  if (arg)
+    error ("The \"finish\" command does not take any arguments.");
+  if (!target_has_execution)
+    error ("The program is not running.");
+
+  frame = get_prev_frame (selected_frame);
+  if (frame == 0)
+    error ("\"finish\" not meaningful in the outermost frame.");
+
+  clear_proceed_status ();
+
+  fi = get_frame_info (frame);
+  sal = find_pc_line (fi->pc, 0);
+  sal.pc = fi->pc;
+  set_momentary_breakpoint (sal, frame);
+
+  /* Find the function we will return from.  */
+
+  fi = get_frame_info (selected_frame);
+  function = find_pc_function (fi->pc);
+
+  if (from_tty)
+    {
+      printf ("Run till exit from ");
+      print_selected_frame ();
+    }
+
+  proceed_to_finish = 1;               /* We want stop_registers, please... */
+  proceed ((CORE_ADDR) -1, -1, 0);
+
+  if (bpstat_momentary_breakpoint (stop_bpstat) && function != 0)
+    {
+      struct type *value_type;
+      register value val;
+      CORE_ADDR funcaddr;
+
+      value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
+      if (!value_type)
+       fatal ("internal: finish_command: function has no target type");
+      
+      if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
+       return;
+
+      funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));
+
+      val = value_being_returned (value_type, stop_registers,
+             using_struct_return (value_of_variable (function),
+                                  funcaddr,
+                                  value_type,
+               BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))));
+
+      printf ("Value returned is $%d = ", record_latest_value (val));
+      value_print (val, stdout, 0, Val_no_prettyprint);
+      putchar ('\n');
+    }
+}
+\f
+static void
+program_info (args, from_tty)
+    char *args;
+    int from_tty;
+{
+  bpstat bs = stop_bpstat;
+  int num = bpstat_num (&bs);
+  
+  if (!target_has_execution)
+    {
+      printf ("The program being debugged is not being run.\n");
+      return;
+    }
+
+  target_files_info ();
+  printf ("Program stopped at 0x%x.\n", stop_pc);
+  if (stop_step)
+    printf ("It stopped after being stepped.\n");
+  else if (num != 0)
+    {
+      /* There may be several breakpoints in the same place, so this
+        isn't as strange as it seems.  */
+      while (num != 0)
+       {
+         if (num < 0)
+           printf ("It stopped at a breakpoint that has since been deleted.\n");
+         else
+           printf ("It stopped at breakpoint %d.\n", num);
+         num = bpstat_num (&bs);
+       }
+    }
+  else if (stop_signal) {
+#ifdef PRINT_RANDOM_SIGNAL
+    PRINT_RANDOM_SIGNAL (stop_signal);
+#else
+    printf ("It stopped with signal %d (%s).\n",
+           stop_signal, 
+           (stop_signal > NSIG)? "unknown": sys_siglist[stop_signal]);
+#endif
+  }
+
+  if (!from_tty)
+    printf ("Type \"info stack\" or \"info registers\" for more information.\n");
+}
+\f
+static void
+environment_info (var)
+     char *var;
+{
+  if (var)
+    {
+      register char *val = get_in_environ (inferior_environ, var);
+      if (val)
+       printf ("%s = %s\n", var, val);
+      else
+       printf ("Environment variable \"%s\" not defined.\n", var);
+    }
+  else
+    {
+      register char **vector = environ_vector (inferior_environ);
+      while (*vector)
+       printf ("%s\n", *vector++);
+    }
+}
+
+static void
+set_environment_command (arg)
+     char *arg;
+{
+  register char *p, *val, *var;
+  int nullset = 0;
+
+  if (arg == 0)
+    error_no_arg ("environment variable and value");
+
+  /* Find seperation between variable name and value */
+  p = (char *) strchr (arg, '=');
+  val = (char *) strchr (arg, ' ');
+
+  if (p != 0 && val != 0)
+    {
+      /* We have both a space and an equals.  If the space is before the
+        equals and the only thing between the two is more space, use
+        the equals */
+      if (p > val)
+       while (*val == ' ')
+         val++;
+
+      /* Take the smaller of the two.  If there was space before the
+        "=", they will be the same right now. */
+      p = arg + min (p - arg, val - arg);
+    }
+  else if (val != 0 && p == 0)
+    p = val;
+
+  if (p == arg)
+    error_no_arg ("environment variable to set");
+
+  if (p == 0 || p[1] == 0)
+    {
+      nullset = 1;
+      if (p == 0)
+       p = arg + strlen (arg); /* So that savestring below will work */
+    }
+  else
+    {
+      /* Not setting variable value to null */
+      val = p + 1;
+      while (*val == ' ' || *val == '\t')
+       val++;
+    }
+
+  while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--;
+
+  var = savestring (arg, p - arg);
+  if (nullset)
+    {
+      printf ("Setting environment variable \"%s\" to null value.\n", var);
+      set_in_environ (inferior_environ, var, "");
+    }
+  else
+    set_in_environ (inferior_environ, var, val);
+  free (var);
+}
+
+static void
+unset_environment_command (var, from_tty)
+     char *var;
+     int from_tty;
+{
+  if (var == 0)
+    {
+      /* If there is no argument, delete all environment variables.
+        Ask for confirmation if reading from the terminal.  */
+      if (!from_tty || query ("Delete all environment variables? "))
+       {
+         free_environ (inferior_environ);
+         inferior_environ = make_environ ();
+       }
+    }
+  else
+    unset_in_environ (inferior_environ, var);
+}
+
+/* Handle the execution path (PATH variable) */
+
+const static char path_var_name[] = "PATH";
+
+void
+path_info (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  printf ("Executable and object file path: %s\n", 
+      get_in_environ (inferior_environ, path_var_name));
+}
+
+/* Add zero or more directories to the front of the execution path.  */
+
+void
+path_command (dirname, from_tty)
+     char *dirname;
+     int from_tty;
+{
+  char *exec_path;
+
+  dont_repeat ();
+  exec_path = strsave (get_in_environ (inferior_environ, path_var_name));
+  mod_path (dirname, from_tty, &exec_path);
+  set_in_environ (inferior_environ, path_var_name, exec_path);
+  free (exec_path);
+  if (from_tty)
+    path_info ();
+}
+\f
+CORE_ADDR
+read_pc ()
+{
+  return ADDR_BITS_REMOVE ((CORE_ADDR) read_register (PC_REGNUM));
+}
+
+void
+write_pc (val)
+     CORE_ADDR val;
+{
+  write_register (PC_REGNUM, (long) val);
+#ifdef NPC_REGNUM
+  write_register (NPC_REGNUM, (long) val+4);
+#endif
+  pc_changed = 0;
+}
+
+char *reg_names[] = REGISTER_NAMES;
+
+/* Print out the machine register regnum. If regnum is -1,
+   print all registers.
+   For most machines, having all_registers_info() print the
+   register(s) one per line is good enough. If a different format
+   is required, (eg, for SPARC or Pyramid 90x, which both have
+   lots of regs), or there is an existing convention for showing
+   all the registers, define the macro DO_REGISTERS_INFO(regnum)
+   to provide that format.  */  
+#if !defined (DO_REGISTERS_INFO)
+#define DO_REGISTERS_INFO(regnum) do_registers_info(regnum)
+static void do_registers_info (regnum)
+     int regnum;
+{
+  register int i;
+
+  if (regnum == -1)
+    printf_filtered (
+      "Register       Contents (relative to selected stack frame)\n\n");
+
+  for (i = 0; i < NUM_REGS; i++)
+    {
+      char raw_buffer[MAX_REGISTER_RAW_SIZE];
+      char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+      if (regnum != -1 && i != regnum)
+       continue;
+
+      fputs_filtered (reg_names[i], stdout);
+      print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
+
+      /* Get the data in raw format, then convert also to virtual format.  */
+      if (read_relative_register_raw_bytes (i, raw_buffer))
+       {
+         printf_filtered ("Invalid register contents\n");
+         continue;
+       }
+      
+      target_convert_to_virtual (i, raw_buffer, virtual_buffer);
+
+      /* If virtual format is floating, print it that way, and in raw hex.  */
+      if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT
+         && ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
+       {
+         register int j;
+
+         val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0,
+                    stdout, 0, 1, 0, Val_pretty_default);
+
+         printf_filtered ("\t(raw 0x");
+         for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+           printf_filtered ("%02x", (unsigned char)raw_buffer[j]);
+         printf_filtered (")");
+       }
+
+/* FIXME!  val_print probably can handle all of these cases now...  */
+
+      /* Else if virtual format is too long for printf,
+        print in hex a byte at a time.  */
+      else if (REGISTER_VIRTUAL_SIZE (i) > sizeof (long))
+       {
+         register int j;
+         printf_filtered ("0x");
+         for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
+           printf_filtered ("%02x", (unsigned char)virtual_buffer[j]);
+       }
+      /* Else print as integer in hex and in decimal.  */
+      else
+       {
+         val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0,
+                    stdout, 'x', 1, 0, Val_pretty_default);
+         printf_filtered ("\t");
+         val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0,
+                    stdout,   0, 1, 0, Val_pretty_default);
+       }
+
+      /* The SPARC wants to print even-numbered float regs as doubles
+        in addition to printing them as floats.  */
+#ifdef PRINT_REGISTER_HOOK
+      PRINT_REGISTER_HOOK (i);
+#endif
+
+      printf_filtered ("\n");
+    }
+}
+#endif /* no DO_REGISTERS_INFO.  */
+
+static void
+registers_info (addr_exp)
+     char *addr_exp;
+{
+  int regnum;
+
+  if (!target_has_registers)
+    error ("The program has no registers now.");
+
+  if (addr_exp)
+    {
+      if (*addr_exp >= '0' && *addr_exp <= '9')
+       regnum = atoi (addr_exp);
+      else
+       {
+         register char *p = addr_exp;
+         if (p[0] == '$')
+           p++;
+         for (regnum = 0; regnum < NUM_REGS; regnum++)
+           if (!strcmp (p, reg_names[regnum]))
+             break;
+         if (regnum == NUM_REGS)
+           error ("%s: invalid register name.", addr_exp);
+       }
+    }
+  else
+    regnum = -1;
+
+  DO_REGISTERS_INFO(regnum);
+}
+\f
+/*
+ * TODO:
+ * Should save/restore the tty state since it might be that the
+ * program to be debugged was started on this tty and it wants
+ * the tty in some state other than what we want.  If it's running
+ * on another terminal or without a terminal, then saving and
+ * restoring the tty state is a harmless no-op.
+ * This only needs to be done if we are attaching to a process.
+ */
+
+/*
+ * attach_command --
+ * takes a program started up outside of gdb and ``attaches'' to it.
+ * This stops it cold in its tracks and allows us to start tracing it.
+ * For this to work, we must be able to send the process a
+ * signal and we must have the same effective uid as the program.
+ */
+void
+attach_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  target_attach (args, from_tty);
+}
+
+/*
+ * detach_command --
+ * takes a program previously attached to and detaches it.
+ * The program resumes execution and will no longer stop
+ * on signals, etc.  We better not have left any breakpoints
+ * in the program or it'll die when it hits one.  For this
+ * to work, it may be necessary for the process to have been
+ * previously attached.  It *might* work if the program was
+ * started via the normal ptrace (PTRACE_TRACEME).
+ */
+
+static void
+detach_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  target_detach (args, from_tty);
+}
+
+/* ARGSUSED */
+static void
+float_info (addr_exp)
+     char *addr_exp;
+{
+#ifdef FLOAT_INFO
+       FLOAT_INFO;
+#else
+       printf ("No floating point info available for this processor.\n");
+#endif
+}
+\f
+void
+_initialize_infcmd ()
+{
+  struct cmd_list_element *c;
+  
+  add_com ("tty", class_run, tty_command,
+          "Set terminal for future runs of program being debugged.");
+
+  add_show_from_set
+    (add_set_cmd ("args", class_run, var_string_noescape, (char *)&inferior_args,
+                 
+"Set arguments to give program being debugged when it is started.\n\
+Follow this command with any number of args, to be passed to the program.",
+                 &setlist),
+     &showlist);
+
+  c = add_cmd
+    ("environment", no_class, environment_info,
+     "The environment to give the program, or one variable's value.\n\
+With an argument VAR, prints the value of environment variable VAR to\n\
+give the program being debugged.  With no arguments, prints the entire\n\
+environment to be given to the program.", &showlist);
+  c->completer = noop_completer;
+
+  c = add_cmd ("environment", class_run, unset_environment_command,
+             "Cancel environment variable VAR for the program.\n\
+This does not affect the program until the next \"run\" command.",
+          &deletelist);
+  c->completer = noop_completer;
+
+  c = add_cmd ("environment", class_run, set_environment_command,
+              "Set environment variable value to give the program.\n\
+Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
+VALUES of environment variables are uninterpreted strings.\n\
+This does not affect the program until the next \"run\" command.",
+          &setlist);
+  c->completer = noop_completer;
+  add_com ("path", class_files, path_command,
+       "Add directory DIR(s) to beginning of search path for object files.\n\
+$cwd in the path means the current working directory.\n\
+This path is equivalent to the $PATH shell variable.  It is a list of\n\
+directories, separated by colons.  These directories are searched to find\n\
+fully linked executable files and separately compiled object files as needed.");
+
+  add_info ("path", path_info,
+           "Current search path for finding object files.\n\
+$cwd in the path means the current working directory.\n\
+This path is equivalent to the $PATH shell variable.  It is a list of\n\
+directories, separated by colons.  These directories are searched to find\n\
+fully linked executable files and separately compiled object files as needed.");
+
+ add_com ("attach", class_run, attach_command,
+          "Attach to a process or file outside of GDB.\n\
+This command attaches to another target, of the same type as your last\n\
+`target' command (`info files' will show your target stack).\n\
+The command may take as argument a process id or a device file.\n\
+For a process id, you must have permission to send the process a signal,\n\
+and it must have the same effective uid as the debugger.\n\
+When using \"attach\", you should use the \"file\" command to specify\n\
+the program running in the process, and to load its symbol table.");
+
+  add_com ("detach", class_run, detach_command,
+          "Detach a process or file previously attached.\n\
+If a process, it is no longer traced, and it continues its execution.  If you\n\
+were debugging a file, the file is closed and gdb no longer accesses it.");
+
+  add_com ("signal", class_run, signal_command,
+          "Continue program giving it signal number SIGNUMBER.");
+
+  add_com ("stepi", class_run, stepi_command,
+          "Step one instruction exactly.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("si", "stepi", class_alias, 0);
+
+  add_com ("nexti", class_run, nexti_command,
+          "Step one instruction, but proceed through subroutine calls.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("ni", "nexti", class_alias, 0);
+
+  add_com ("finish", class_run, finish_command,
+          "Execute until selected stack frame returns.\n\
+Upon return, the value returned is printed and put in the value history.");
+
+  add_com ("next", class_run, next_command,
+          "Step program, proceeding through subroutine calls.\n\
+Like the \"step\" command as long as subroutine calls do not happen;\n\
+when they do, the call is treated as one instruction.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("n", "next", class_run, 1);
+
+  add_com ("step", class_run, step_command,
+          "Step program until it reaches a different source line.\n\
+Argument N means do this N times (or till program stops for another reason).");
+  add_com_alias ("s", "step", class_run, 1);
+
+  add_com ("until", class_run, until_command,
+          "Execute until the program reaches a source line greater than the current\n\
+or a specified line or address or function (same args as break command).\n\
+Execution will also stop upon exit from the current stack frame.");
+  add_com_alias ("u", "until", class_run, 1);
+  
+  add_com ("jump", class_run, jump_command,
+          "Continue program being debugged at specified line or address.\n\
+Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
+for an address to start at.");
+
+  add_com ("continue", class_run, continue_command,
+          "Continue program being debugged, after signal or breakpoint.\n\
+If proceeding from breakpoint, a number N may be used as an argument:\n\
+then the same breakpoint won't break until the Nth time it is reached.");
+  add_com_alias ("c", "cont", class_run, 1);
+  add_com_alias ("fg", "cont", class_run, 1);
+
+  add_com ("run", class_run, run_command,
+          "Start debugged program.  You may specify arguments to give it.\n\
+Args may include \"*\", or \"[...]\"; they are expanded using \"sh\".\n\
+Input and output redirection with \">\", \"<\", or \">>\" are also allowed.\n\n\
+With no arguments, uses arguments last specified (with \"run\" or \"set args\".\n\
+To cancel previous arguments and run with no arguments,\n\
+use \"set args\" without arguments.");
+  add_com_alias ("r", "run", class_run, 1);
+
+  add_info ("registers", registers_info,
+           "List of registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.");
+
+  add_info ("program", program_info,
+           "Execution status of the program.");
+
+  add_info ("float", float_info,
+           "Print the status of the floating point unit\n");
+
+  inferior_args = savestring ("", 1);  /* Initially no args */
+  inferior_environ = make_environ ();
+  init_environ (inferior_environ);
+}
diff --git a/gdb/inferior.h b/gdb/inferior.h
new file mode 100644 (file)
index 0000000..d99c4a6
--- /dev/null
@@ -0,0 +1,201 @@
+/* Variables that describe the inferior process running under GDB:
+   Where it is, why it stopped, and how to step it.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* For bpstat.  */
+#include "breakpoint.h"
+
+/* For FRAME_ADDR.  */
+#include "frame.h"
+
+/*
+ * Structure in which to save the status of the inferior.  Save
+ * through "save_inferior_status", restore through
+ * "restore_inferior_status".
+ * This pair of routines should be called around any transfer of
+ * control to the inferior which you don't want showing up in your
+ * control variables.
+ */
+struct inferior_status {
+  int pc_changed;
+  int stop_signal;
+  int stop_pc;
+  FRAME_ADDR stop_frame_address;
+  bpstat stop_bpstat;
+  int stop_step;
+  int stop_stack_dummy;
+  int stopped_by_random_signal;
+  int trap_expected;
+  CORE_ADDR step_range_start;
+  CORE_ADDR step_range_end;
+  FRAME_ADDR step_frame_address;
+  int step_over_calls;
+  CORE_ADDR step_resume_break_address;
+  int stop_after_trap;
+  int stop_soon_quietly;
+  FRAME_ADDR selected_frame_address;
+  int selected_level;
+  char stop_registers[REGISTER_BYTES];
+  int breakpoint_proceeded;
+  int restore_stack_info;
+  int proceed_to_finish;
+};
+
+void save_inferior_status (), restore_inferior_status ();
+
+/* File name for default use for standard in/out in the inferior.  */
+
+extern char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now.  */
+
+extern int inferior_pid;
+
+/* Character array containing an image of the inferior programs' registers.  */
+
+extern char registers[];
+
+extern void clear_proceed_status ();
+extern void start_inferior ();
+extern void proceed ();
+extern void kill_inferior ();
+extern void kill_inferior_fast ();
+extern void generic_mourn_inferior ();
+extern void terminal_ours ();
+extern void detach ();
+extern void run_stack_dummy ();
+extern CORE_ADDR read_pc ();
+extern void write_pc ();
+extern void wait_for_inferior ();
+extern void init_wait_for_inferior ();
+extern void close_exec_file ();
+extern void reopen_exec_file ();
+
+/* Last signal that the inferior received (why it stopped).  */
+
+extern int stop_signal;
+
+/* Address at which inferior stopped.  */
+
+extern CORE_ADDR stop_pc;
+
+/* Stack frame when program stopped.  */
+
+extern FRAME_ADDR stop_frame_address;
+
+/* Chain containing status of breakpoint(s) that we have stopped at.  */
+
+extern bpstat stop_bpstat;
+
+/* Flag indicating that a command has proceeded the inferior past the
+   current breakpoint.  */
+
+extern int breakpoint_proceeded;
+
+/* Nonzero if stopped due to a step command.  */
+
+extern int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine.  */
+
+extern int stop_stack_dummy;
+
+/* Nonzero if program stopped due to a random (unexpected) signal in
+   inferior process.  */
+
+extern int stopped_by_random_signal;
+
+/* Range to single step within.
+   If this is nonzero, respond to a single-step signal
+   by continuing to step if the pc is in this range.  */
+
+extern CORE_ADDR step_range_start; /* Inclusive */
+extern CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+   This is how we know when we step into a subroutine call,
+   and how to set the frame for the breakpoint used to step out.  */
+
+extern FRAME_ADDR step_frame_address;
+
+/* 1 means step over all subroutine calls.
+   -1 means step over calls to undebuggable functions.  */
+
+extern int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+   so don't print frame next time inferior stops
+   if it stops due to stepping.  */
+
+extern int step_multi;
+
+/* Nonzero if proceed is being used for a "finish" command or a similar
+   situation when stop_registers should be saved.  */
+
+extern int proceed_to_finish;
+
+/* Save register contents here when about to pop a stack dummy frame,
+   if-and-only-if proceed_to_finish is set.
+   Thus this contains the return value from the called function (assuming
+   values are returned in a register).  */
+
+extern char stop_registers[REGISTER_BYTES];
+
+/* Nonzero if pc has been changed by the debugger
+   since the inferior stopped.  */
+
+extern int pc_changed;
+
+/* Nonzero if the child process in inferior_pid was attached rather
+   than forked.  */
+
+int attach_flag;
+\f
+/* Possible values for CALL_DUMMY_LOCATION.  */
+#define ON_STACK 1
+#define BEFORE_TEXT_END 2
+#define AFTER_TEXT_END 3
+
+#if !defined (CALL_DUMMY_LOCATION)
+#if defined (CANNOT_EXECUTE_STACK)
+#define CALL_DUMMY_LOCATION BEFORE_TEXT_END
+#else /* Can execute stack.  */
+#define CALL_DUMMY_LOCATION ON_STACK
+#endif /* Can execute stack.  */
+#endif /* No CALL_DUMMY_LOCATION.  */
+
+/* Are we in a call dummy?  The code below which allows DECR_PC_AFTER_BREAK
+   below is for infrun.c, which may give the macro a pc without that
+   subtracted out.  */
+#if !defined (PC_IN_CALL_DUMMY)
+#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+  ((pc) >= text_end - CALL_DUMMY_LENGTH         \
+   && (pc) < text_end + DECR_PC_AFTER_BREAK)
+#else /* Not before text_end.  */
+#if CALL_DUMMY_LOCATION == AFTER_TEXT_END
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+  ((pc) >= text_end   \
+   && (pc) < text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK)
+#else /* On stack.  */
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+  ((sp) INNER_THAN (pc) && (pc) INNER_THAN (frame_address))
+#endif /* On stack.  */
+#endif /* Not before text_end.  */
+#endif /* No PC_IN_CALL_DUMMY.  */
diff --git a/gdb/inflow.c b/gdb/inflow.c
new file mode 100644 (file)
index 0000000..6e6905f
--- /dev/null
@@ -0,0 +1,478 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "command.h"
+#include "signals.h"
+#include "terminal.h"
+#include "target.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+/* Some USG-esque systems (some of which are BSD-esque enough so that USG
+   is not defined) want this header, and it won't do any harm.  */
+#include <fcntl.h>
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+
+extern struct target_ops child_ops;
+
+/* Nonzero if we are debugging an attached outside process
+   rather than an inferior.  */
+
+int attach_flag;
+
+\f
+/* Record terminal status separately for debugger and inferior.  */
+
+static TERMINAL sg_inferior;
+static TERMINAL sg_ours;
+
+static int tflags_inferior;
+static int tflags_ours;
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+static struct tchars tc_inferior;
+static struct tchars tc_ours;
+#endif
+
+#ifdef TIOCGLTC
+static struct ltchars ltc_inferior;
+static struct ltchars ltc_ours;
+#endif
+
+#ifdef TIOCLGET
+static int lmode_inferior;
+static int lmode_ours;
+#endif
+
+#ifdef TIOCGPGRP
+static int pgrp_inferior;
+static int pgrp_ours;
+#else
+static void (*sigint_ours) ();
+static void (*sigquit_ours) ();
+#endif /* TIOCGPGRP */
+
+/* Copy of inferior_io_terminal when inferior was last started.  */
+static char *inferior_thisrun_terminal;
+
+static void terminal_ours_1 ();
+
+/* Nonzero if our terminal settings are in effect.
+   Zero if the inferior's settings are in effect.  */
+static int terminal_is_ours;
+
+/* Initialize the terminal settings we record for the inferior,
+   before we actually run the inferior.  */
+
+void
+terminal_init_inferior ()
+{
+  sg_inferior = sg_ours;
+  tflags_inferior = tflags_ours;
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+  tc_inferior = tc_ours;
+#endif
+
+#ifdef TIOCGLTC
+  ltc_inferior = ltc_ours;
+#endif
+
+#ifdef TIOCLGET
+  lmode_inferior = lmode_ours;
+#endif
+
+#ifdef TIOCGPGRP
+  pgrp_inferior = inferior_pid;
+#endif /* TIOCGPGRP */
+
+  terminal_is_ours = 1;
+}
+
+/* Put the inferior's terminal settings into effect.
+   This is preparation for starting or resuming the inferior.  */
+
+void
+terminal_inferior ()
+{
+  if (terminal_is_ours && inferior_thisrun_terminal == 0)
+    {
+      fcntl (0, F_SETFL, tflags_inferior);
+      fcntl (0, F_SETFL, tflags_inferior);
+      ioctl (0, TIOCSETN, &sg_inferior);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+      ioctl (0, TIOCSETC, &tc_inferior);
+#endif
+#ifdef TIOCGLTC
+      ioctl (0, TIOCSLTC, &ltc_inferior);
+#endif
+#ifdef TIOCLGET
+      ioctl (0, TIOCLSET, &lmode_inferior);
+#endif
+
+#ifdef TIOCGPGRP
+      ioctl (0, TIOCSPGRP, &pgrp_inferior);
+#else
+      sigint_ours = (void (*) ()) signal (SIGINT, SIG_IGN);
+      sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN);
+#endif /* TIOCGPGRP */
+    }
+  terminal_is_ours = 0;
+}
+
+/* Put some of our terminal settings into effect,
+   enough to get proper results from our output,
+   but do not change into or out of RAW mode
+   so that no input is discarded.
+
+   After doing this, either terminal_ours or terminal_inferior
+   should be called to get back to a normal state of affairs.  */
+
+void
+terminal_ours_for_output ()
+{
+  terminal_ours_1 (1);
+}
+
+/* Put our terminal settings into effect.
+   First record the inferior's terminal settings
+   so they can be restored properly later.  */
+
+void
+terminal_ours ()
+{
+  terminal_ours_1 (0);
+}
+
+static void
+terminal_ours_1 (output_only)
+     int output_only;
+{
+#ifdef TIOCGPGRP
+  /* Ignore this signal since it will happen when we try to set the pgrp.  */
+  void (*osigttou) ();
+#endif /* TIOCGPGRP */
+
+  /* The check for inferior_thisrun_terminal had been commented out
+     when the call to ioctl (TIOCNOTTY) was commented out.
+     Checking inferior_thisrun_terminal is necessary so that
+     if GDB is running in the background, it won't block trying
+     to do the ioctl()'s below.  */
+  if (inferior_thisrun_terminal != 0)
+    return;
+
+  if (!terminal_is_ours)
+    {
+      terminal_is_ours = 1;
+
+#ifdef TIOCGPGRP
+      osigttou = (void (*) ()) signal (SIGTTOU, SIG_IGN);
+
+      ioctl (0, TIOCGPGRP, &pgrp_inferior);
+      ioctl (0, TIOCSPGRP, &pgrp_ours);
+
+      signal (SIGTTOU, osigttou);
+#else
+      signal (SIGINT, sigint_ours);
+      signal (SIGQUIT, sigquit_ours);
+#endif /* TIOCGPGRP */
+
+      tflags_inferior = fcntl (0, F_GETFL, 0);
+      ioctl (0, TIOCGETP, &sg_inferior);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+      ioctl (0, TIOCGETC, &tc_inferior);
+#endif
+#ifdef TIOCGLTC
+      ioctl (0, TIOCGLTC, &ltc_inferior);
+#endif
+#ifdef TIOCLGET
+      ioctl (0, TIOCLGET, &lmode_inferior);
+#endif
+    }
+
+#ifdef HAVE_TERMIO
+  sg_ours.c_lflag |= ICANON;
+  if (output_only && !(sg_inferior.c_lflag & ICANON))
+    sg_ours.c_lflag &= ~ICANON;
+#else /* not HAVE_TERMIO */
+  sg_ours.sg_flags &= ~RAW & ~CBREAK;
+  if (output_only)
+    sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
+#endif /* not HAVE_TERMIO */
+
+  fcntl (0, F_SETFL, tflags_ours);
+  fcntl (0, F_SETFL, tflags_ours);
+  ioctl (0, TIOCSETN, &sg_ours);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+  ioctl (0, TIOCSETC, &tc_ours);
+#endif
+#ifdef TIOCGLTC
+  ioctl (0, TIOCSLTC, &ltc_ours);
+#endif
+#ifdef TIOCLGET
+  ioctl (0, TIOCLSET, &lmode_ours);
+#endif
+
+#ifdef HAVE_TERMIO
+  sg_ours.c_lflag |= ICANON;
+#else /* not HAVE_TERMIO */
+  sg_ours.sg_flags &= ~RAW & ~CBREAK;
+#endif /* not HAVE_TERMIO */
+}
+
+/* ARGSUSED */
+void
+term_info (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  target_terminal_info (arg, from_tty);
+}
+
+void
+child_terminal_info (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  register int i;
+
+  printf_filtered ("Inferior's terminal status (currently saved by GDB):\n");
+
+#ifdef HAVE_TERMIO
+
+  printf_filtered ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
+         tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
+  printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
+         sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
+  printf_filtered ("c_cc: ");
+  for (i = 0; (i < NCC); i += 1)
+    printf_filtered ("0x%x ", sg_inferior.c_cc[i]);
+  printf_filtered ("\n");
+
+#else /* not HAVE_TERMIO */
+
+  printf_filtered ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
+         tflags_inferior, sg_inferior.sg_flags, pgrp_inferior);
+
+#endif /* not HAVE_TERMIO */
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+  printf_filtered ("tchars: ");
+  for (i = 0; i < (int)sizeof (struct tchars); i++)
+    printf_filtered ("0x%x ", ((char *)&tc_inferior)[i]);
+  printf_filtered ("\n");
+#endif
+
+#ifdef TIOCGLTC
+  printf_filtered ("ltchars: ");
+  for (i = 0; i < (int)sizeof (struct ltchars); i++)
+    printf_filtered ("0x%x ", ((char *)&ltc_inferior)[i]);
+  printf_filtered ("\n");
+#endif
+  
+#ifdef TIOCLGET
+  printf_filtered ("lmode:  0x%x\n", lmode_inferior);
+#endif
+}
+\f
+/* NEW_TTY is called in new child processes under Unix, which will
+   become debugger target processes.
+   If the TTYNAME argument is non-null, we switch to that tty for further
+   input and output.  In either case, we remember the setup.  */
+
+void
+new_tty (ttyname)
+     char *ttyname;
+{
+  register int tty;
+
+  /* Save the name for later, for determining whether we and the child
+     are sharing a tty.  */
+  inferior_thisrun_terminal = ttyname;
+  if (ttyname == 0)
+    return;
+
+#ifdef TIOCNOTTY
+  /* Disconnect the child process from our controlling terminal.  */
+  tty = open("/dev/tty", O_RDWR);
+  if (tty > 0)
+    {
+      ioctl(tty, TIOCNOTTY, 0);
+      close(tty);
+    }
+#endif
+
+  /* Now open the specified new terminal.  */
+
+  tty = open(ttyname, O_RDWR);
+  if (tty == -1)
+    {
+      print_sys_errmsg (ttyname, errno);
+      _exit(1);
+    }
+
+  /* Avoid use of dup2; doesn't exist on all systems.  */
+  if (tty != 0)
+    { close (0); dup (tty); }
+  if (tty != 1)
+    { close (1); dup (tty); }
+  if (tty != 2)
+    { close (2); dup (tty); }
+  if (tty > 2)
+    close(tty);
+}
+\f
+/* Kill the inferior process.  Make us have no inferior.  */
+
+/* ARGSUSED */
+static void
+kill_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  if (inferior_pid == 0)
+    error ("The program is not being run.");
+  if (!query ("Kill the inferior process? "))
+    error ("Not confirmed.");
+  target_kill (arg, from_tty);
+}
+
+/* The inferior process has died.  Long live the inferior!  */
+
+void
+generic_mourn_inferior ()
+{
+  inferior_pid = 0;
+  attach_flag = 0;
+  mark_breakpoints_out ();
+  registers_changed ();
+
+#ifdef CLEAR_DEFERRED_STORES
+  /* Delete any pending stores to the inferior... */
+  CLEAR_DEFERRED_STORES;
+#endif
+
+  select_frame ((FRAME) 0, -1);
+  reopen_exec_file ();
+  if (target_has_stack)
+    set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                         read_pc ()));
+  else
+    set_current_frame (0);
+  /* It is confusing to the user for ignore counts to stick around
+     from previous runs of the inferior.  So clear them.  */
+  breakpoint_clear_ignore_counts ();
+}
+
+void
+child_mourn_inferior ()
+{
+  unpush_target (&child_ops);
+  generic_mourn_inferior ();
+}
+\f
+#if 0 
+/* This function is just for testing, and on some systems (Sony NewsOS
+   3.2) <sys/user.h> also includes <sys/time.h> which leads to errors
+   (since on this system at least sys/time.h is not protected against
+   multiple inclusion).  */
+/* ARGSUSED */
+static void
+try_writing_regs_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register int i;
+  register int value;
+
+  if (inferior_pid == 0)
+    error ("There is no inferior process now.");
+
+  /* A Sun 3/50 or 3/60 (at least) running SunOS 4.0.3 will have a
+     kernel panic if we try to write past the end of the user area.
+     Presumably Sun will fix this bug (it has been reported), but it
+     is tacky to crash the system, so at least on SunOS4 we need to
+     stop writing when we hit the end of the user area.  */
+  for (i = 0; i < sizeof (struct user); i += 2)
+    {
+      QUIT;
+      errno = 0;
+      value = call_ptrace (3, inferior_pid, i, 0);
+      call_ptrace (6, inferior_pid, i, value);
+      if (errno == 0)
+       {
+         printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
+                 i, value, value);
+       }
+      else if ((i & 0377) == 0)
+       printf (" Failed at 0x%x.\n", i);
+    }
+}
+#endif
+\f
+void
+_initialize_inflow ()
+{
+  add_info ("terminal", term_info,
+          "Print inferior's saved terminal status.");
+
+#if 0
+  add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
+          "Try writing all locations in inferior's system block.\n\
+Report which ones can be written.");
+#endif
+
+  add_com ("kill", class_run, kill_command,
+          "Kill execution of program being debugged.");
+
+  inferior_pid = 0;
+
+  ioctl (0, TIOCGETP, &sg_ours);
+  fcntl (0, F_GETFL, tflags_ours);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+  ioctl (0, TIOCGETC, &tc_ours);
+#endif
+#ifdef TIOCGLTC
+  ioctl (0, TIOCGLTC, &ltc_ours);
+#endif
+#ifdef TIOCLGET
+  ioctl (0, TIOCLGET, &lmode_ours);
+#endif
+
+#ifdef TIOCGPGRP
+  ioctl (0, TIOCGPGRP, &pgrp_ours);
+#endif /* TIOCGPGRP */
+
+  terminal_is_ours = 1;
+}
+
diff --git a/gdb/infptrace.c b/gdb/infptrace.c
new file mode 100644 (file)
index 0000000..03bb271
--- /dev/null
@@ -0,0 +1,397 @@
+/* Low level Unix child interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#if !defined (PT_KILL)
+#define PT_KILL 8
+#define PT_STEP 9
+#define PT_CONTINUE 7
+#define PT_READ_U 3
+#define PT_WRITE_U 6
+#define PT_READ_I 1
+#define PT_WRITE_I 4
+/* The Following Change is for a Sun */
+#define PT_WRITE_D 4
+#endif /* No PT_KILL.  */
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#include "gdbcore.h"
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+/* This function simply calls ptrace with the given arguments.  
+   It exists so that all calls to ptrace are isolated in this 
+   machine-dependent file. */
+int
+call_ptrace (request, pid, addr, data)
+     int request, pid, *addr, data;
+{
+  return ptrace (request, pid, addr, data);
+}
+
+#ifdef DEBUG_PTRACE
+/* For the rest of the file, use an extra level of indirection */
+/* This lets us breakpoint usefully on call_ptrace. */
+#define ptrace call_ptrace
+#endif
+
+/* This is used when GDB is exiting.  It gives less chance of error.*/
+
+void
+kill_inferior_fast ()
+{
+  if (inferior_pid == 0)
+    return;
+  ptrace (PT_KILL, inferior_pid, 0, 0);
+  wait ((int *)0);
+}
+
+void
+kill_inferior (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  kill_inferior_fast ();
+  target_mourn_inferior ();
+}
+
+/* Resume execution of the inferior process.
+   If STEP is nonzero, single-step it.
+   If SIGNAL is nonzero, give it that signal.  */
+
+void
+child_resume (step, signal)
+     int step;
+     int signal;
+{
+  errno = 0;
+  /* An address of (int *)1 tells it to continue from where it was. 
+     (If GDB wanted it to start some other way, we have already written
+     a new PC value to the child.)  */
+  if (step)
+    {
+#if defined (NO_SINGLE_STEP)
+      single_step (signal);
+#else /* Have single step.  */
+      ptrace (PT_STEP, inferior_pid, (int *)1, signal);
+#endif /* Have single step.  */
+    }
+  else
+    ptrace (PT_CONTINUE, inferior_pid, (int *)1, signal);
+  if (errno)
+    perror_with_name ("ptrace");
+}
+\f
+#ifdef ATTACH_DETACH
+/* Nonzero if we are debugging an attached process rather than
+   an inferior.  */
+extern int attach_flag;
+
+/* Start debugging the process whose number is PID.  */
+int
+attach (pid)
+     int pid;
+{
+  errno = 0;
+  ptrace (PT_ATTACH, pid, 0, 0);
+  if (errno)
+    perror_with_name ("ptrace");
+  attach_flag = 1;
+  return pid;
+}
+
+/* Stop debugging the process whose number is PID
+   and continue it with signal number SIGNAL.
+   SIGNAL = 0 means just continue it.  */
+
+void
+detach (signal)
+     int signal;
+{
+  errno = 0;
+  ptrace (PT_DETACH, inferior_pid, 1, signal);
+  if (errno)
+    perror_with_name ("ptrace");
+  attach_flag = 0;
+}
+#endif /* ATTACH_DETACH */
+\f
+#if !defined (FETCH_INFERIOR_REGISTERS)
+
+/* KERNEL_U_ADDR is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+#if defined (KERNEL_U_ADDR_BSD)
+/* Get kernel_u_addr using BSD-style nlist().  */
+CORE_ADDR kernel_u_addr;
+
+void
+_initialize_kernel_u_addr ()
+{
+  struct nlist names[2];
+
+  names[0].n_un.n_name = "_u";
+  names[1].n_un.n_name = NULL;
+  if (nlist ("/vmunix", names) == 0)
+    kernel_u_addr = names[0].n_value;
+  else
+    fatal ("Unable to get kernel u area address.");
+}
+#endif /* KERNEL_U_ADDR_BSD.  */
+
+#if defined (KERNEL_U_ADDR_HPUX)
+/* Get kernel_u_addr using HPUX-style nlist().  */
+CORE_ADDR kernel_u_addr;
+
+struct hpnlist {      
+        char *          n_name;
+        long            n_value;  
+        unsigned char   n_type;   
+        unsigned char   n_length;  
+        short           n_almod;   
+        short           n_unused;
+};
+static struct hpnlist nl[] = {{ "_u", -1, }, { (char *) 0, }};
+
+/* read the value of the u area from the hp-ux kernel */
+void _initialize_kernel_u_addr ()
+{
+    struct user u;
+    nlist ("/hp-ux", &nl);
+    kernel_u_addr = nl[0].n_value;
+}
+#endif /* KERNEL_U_ADDR_HPUX.  */
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area.  */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+  ptrace (PT_READ_U, inferior_pid, \
+         (int *)(offsetof (struct user, u_ar0)), 0) - KERNEL_U_ADDR
+#endif
+
+/* Fetch one register.  */
+static void
+fetch_register (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[MAX_REGISTER_RAW_SIZE];
+  register int i;
+
+  /* Offset of registers within the u area.  */
+  unsigned int offset = U_REGS_OFFSET;
+
+  regaddr = register_addr (regno, offset);
+  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+    {
+      *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid, (int *)regaddr, 0);
+      regaddr += sizeof (int);
+    }
+  supply_register (regno, buf);
+}
+
+/* Fetch all registers, or just one, from the child process.
+   We should check for errors, but we don't.  FIXME.  */
+
+int
+fetch_inferior_registers (regno)
+     int regno;
+{
+  if (regno == -1)
+    for (regno = 0; regno < NUM_REGS; regno++)
+      fetch_register (regno);
+  else
+    fetch_register (regno);
+  return 0;
+}
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+int
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+  extern char registers[];
+  register int i;
+  int result = 0;
+
+  unsigned int offset = U_REGS_OFFSET;
+
+  if (regno >= 0)
+    {
+      regaddr = register_addr (regno, offset);
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+       {
+         errno = 0;
+         ptrace (PT_WRITE_U, inferior_pid, (int *)regaddr,
+                 *(int *) &registers[REGISTER_BYTE (regno) + i]);
+         if (errno != 0)
+           {
+             sprintf (buf, "writing register number %d(%d)", regno, i);
+             perror_with_name (buf);
+             result = -1;
+           }
+         regaddr += sizeof(int);
+       }
+    }
+  else
+    {
+      for (regno = 0; regno < NUM_REGS; regno++)
+       {
+         if (CANNOT_STORE_REGISTER (regno))
+           continue;
+         regaddr = register_addr (regno, offset);
+         for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+           {
+             errno = 0;
+             ptrace (PT_WRITE_U, inferior_pid, (int *)regaddr,
+                     *(int *) &registers[REGISTER_BYTE (regno) + i]);
+             if (errno != 0)
+               {
+                 sprintf (buf, "writing register number %d(%d)", regno, i);
+                 perror_with_name (buf);
+                 result = -1;
+               }
+             regaddr += sizeof(int);
+           }
+       }
+    }
+  return result;
+}
+#endif /* !defined (FETCH_INFERIOR_REGISTERS).  */
+\f
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+   in the NEW_SUN_PTRACE case.
+   It ought to be straightforward.  But it appears that writing did
+   not write the data that I specified.  I cannot understand where
+   it got the data that it actually did write.  */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.   Copy to inferior if
+   WRITE is nonzero.
+  
+   Returns the length copied, which is either the LEN argument or zero.
+   This xfer function does not do partial moves, since child_ops
+   doesn't allow memory operations to cross below us in the target stack
+   anyway.  */
+
+int
+child_xfer_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+
+  if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory data.  */
+
+      if (addr != memaddr || len < (int)sizeof (int)) {
+       /* Need part of initial word -- fetch it.  */
+        buffer[0] = ptrace (PT_READ_I, inferior_pid, (int *)addr, 0);
+      }
+
+      if (count > 1)           /* FIXME, avoid if even boundary */
+       {
+         buffer[count - 1]
+           = ptrace (PT_READ_I, inferior_pid,
+                     (int *)(addr + (count - 1) * sizeof (int)), 0);
+       }
+
+      /* Copy data to be written over corresponding part of buffer */
+
+      bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+      /* Write the entire buffer.  */
+
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         ptrace (PT_WRITE_D, inferior_pid, (int *)addr, buffer[i]);
+         if (errno)
+           {
+             /* Using the appropriate one (I or D) is necessary for
+                Gould NP1, at least.  */
+             errno = 0;
+             ptrace (PT_WRITE_I, inferior_pid, (int *)addr, buffer[i]);
+           }
+         if (errno)
+           return 0;
+       }
+    }
+  else
+    {
+      /* Read all the longwords */
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         buffer[i] = ptrace (PT_READ_I, inferior_pid, (int *)addr, 0);
+         if (errno)
+           return 0;
+         QUIT;
+       }
+
+      /* Copy appropriate bytes out of the buffer.  */
+      bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+    }
+  return len;
+}
diff --git a/gdb/infrun.c b/gdb/infrun.c
new file mode 100644 (file)
index 0000000..1cca592
--- /dev/null
@@ -0,0 +1,1690 @@
+/* Start (run) and stop the inferior process, for GDB.
+   Copyright (C) 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Notes on the algorithm used in wait_for_inferior to determine if we
+   just did a subroutine call when stepping.  We have the following
+   information at that point:
+
+                  Current and previous (just before this step) pc.
+                 Current and previous sp.
+                 Current and previous start of current function.
+
+   If the start's of the functions don't match, then
+
+       a) We did a subroutine call.
+
+   In this case, the pc will be at the beginning of a function.
+
+       b) We did a subroutine return.
+
+   Otherwise.
+
+       c) We did a longjmp.
+
+   If we did a longjump, we were doing "nexti", since a next would
+   have attempted to skip over the assembly language routine in which
+   the longjmp is coded and would have simply been the equivalent of a
+   continue.  I consider this ok behaivior.  We'd like one of two
+   things to happen if we are doing a nexti through the longjmp()
+   routine: 1) It behaves as a stepi, or 2) It acts like a continue as
+   above.  Given that this is a special case, and that anybody who
+   thinks that the concept of sub calls is meaningful in the context
+   of a longjmp, I'll take either one.  Let's see what happens.  
+
+   Acts like a subroutine return.  I can handle that with no problem
+   at all.
+
+   -->So: If the current and previous beginnings of the current
+   function don't match, *and* the pc is at the start of a function,
+   we've done a subroutine call.  If the pc is not at the start of a
+   function, we *didn't* do a subroutine call.  
+
+   -->If the beginnings of the current and previous function do match,
+   either: 
+
+       a) We just did a recursive call.
+
+          In this case, we would be at the very beginning of a
+          function and 1) it will have a prologue (don't jump to
+          before prologue, or 2) (we assume here that it doesn't have
+          a prologue) there will have been a change in the stack
+          pointer over the last instruction.  (Ie. it's got to put
+          the saved pc somewhere.  The stack is the usual place.  In
+          a recursive call a register is only an option if there's a
+          prologue to do something with it.  This is even true on
+          register window machines; the prologue sets up the new
+          window.  It might not be true on a register window machine
+          where the call instruction moved the register window
+          itself.  Hmmm.  One would hope that the stack pointer would
+          also change.  If it doesn't, somebody send me a note, and
+          I'll work out a more general theory.
+          bug-gdb@prep.ai.mit.edu).  This is true (albeit slipperly
+          so) on all machines I'm aware of:
+
+             m68k:     Call changes stack pointer.  Regular jumps don't.
+
+             sparc:    Recursive calls must have frames and therefor,
+                       prologues.
+
+             vax:      All calls have frames and hence change the
+                       stack pointer.
+
+       b) We did a return from a recursive call.  I don't see that we
+          have either the ability or the need to distinguish this
+          from an ordinary jump.  The stack frame will be printed
+          when and if the frame pointer changes; if we are in a
+          function without a frame pointer, it's the users own
+          lookout.
+
+       c) We did a jump within a function.  We assume that this is
+          true if we didn't do a recursive call.
+
+       d) We are in no-man's land ("I see no symbols here").  We
+          don't worry about this; it will make calls look like simple
+          jumps (and the stack frames will be printed when the frame
+          pointer moves), which is a reasonably non-violent response.
+
+#if 0
+    We skip this; it causes more problems than it's worth.
+#ifdef SUN4_COMPILER_FEATURE
+    We do a special ifdef for the sun 4, forcing it to single step
+  into calls which don't have prologues.  This means that we can't
+  nexti over leaf nodes, we can probably next over them (since they
+  won't have debugging symbols, usually), and we can next out of
+  functions returning structures (with a "call .stret4" at the end).
+#endif
+#endif
+*/
+   
+
+   
+   
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "breakpoint.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "signame.h"
+#include "command.h"
+#include "terminal.h"          /* For #ifdef TIOCGPGRP and new_tty */
+#include "target.h"
+
+#include <signal.h>
+
+/* unistd.h is needed to #define X_OK */
+#ifdef USG
+#include <unistd.h>
+#else
+#include <sys/file.h>
+#endif
+
+#ifdef SET_STACK_LIMIT_HUGE
+extern int original_stack_limit;
+#endif /* SET_STACK_LIMIT_HUGE */
+
+/* Required by <sys/user.h>.  */
+#include <sys/types.h>
+/* Required by <sys/user.h>, at least on system V.  */
+#include <sys/dir.h>
+/* Needed by IN_SIGTRAMP on some machines (e.g. vax).  */
+#include <sys/param.h>
+/* Needed by IN_SIGTRAMP on some machines (e.g. vax).  */
+#include <sys/user.h>
+
+extern char *getenv ();
+
+extern struct target_ops child_ops;    /* In inftarg.c */
+
+/* Copy of inferior_io_terminal when inferior was last started.  */
+
+extern char *inferior_thisrun_terminal;
+
+
+/* Sigtramp is a routine that the kernel calls (which then calls the
+   signal handler).  On most machines it is a library routine that
+   is linked into the executable.
+
+   This macro, given a program counter value and the name of the
+   function in which that PC resides (which can be null if the
+   name is not known), returns nonzero if the PC and name show
+   that we are in sigtramp.
+
+   On most machines just see if the name is sigtramp (and if we have
+   no name, assume we are not in sigtramp).  */
+#if !defined (IN_SIGTRAMP)
+#define IN_SIGTRAMP(pc, name) \
+  name && !strcmp ("_sigtramp", name)
+#endif
+
+/* Tables of how to react to signals; the user sets them.  */
+
+static char signal_stop[NSIG];
+static char signal_print[NSIG];
+static char signal_program[NSIG];
+
+/* Nonzero if breakpoints are now inserted in the inferior.  */
+/* Nonstatic for initialization during xxx_create_inferior. FIXME. */
+
+/*static*/ int breakpoints_inserted;
+
+/* Function inferior was in as of last step command.  */
+
+static struct symbol *step_start_function;
+
+/* Nonzero => address for special breakpoint for resuming stepping.  */
+
+static CORE_ADDR step_resume_break_address;
+
+/* Pointer to orig contents of the byte where the special breakpoint is.  */
+
+static char step_resume_break_shadow[BREAKPOINT_MAX];
+
+/* Nonzero means the special breakpoint is a duplicate
+   so it has not itself been inserted.  */
+
+static int step_resume_break_duplicate;
+
+/* Nonzero if we are expecting a trace trap and should proceed from it.  */
+
+static int trap_expected;
+
+/* Nonzero if the next time we try to continue the inferior, it will
+   step one instruction and generate a spurious trace trap.
+   This is used to compensate for a bug in HP-UX.  */
+
+static int trap_expected_after_continue;
+
+/* Nonzero means expecting a trace trap
+   and should stop the inferior and return silently when it happens.  */
+
+int stop_after_trap;
+
+/* Nonzero means expecting a trap and caller will handle it themselves.
+   It is used after attach, due to attaching to a process;
+   when running in the shell before the child program has been exec'd;
+   and when running some kinds of remote stuff (FIXME?).  */
+
+int stop_soon_quietly;
+
+/* Nonzero if pc has been changed by the debugger
+   since the inferior stopped.  */
+
+int pc_changed;
+
+/* Nonzero if proceed is being used for a "finish" command or a similar
+   situation when stop_registers should be saved.  */
+
+int proceed_to_finish;
+
+/* Save register contents here when about to pop a stack dummy frame,
+   if-and-only-if proceed_to_finish is set.
+   Thus this contains the return value from the called function (assuming
+   values are returned in a register).  */
+
+char stop_registers[REGISTER_BYTES];
+
+/* Nonzero if program stopped due to error trying to insert breakpoints.  */
+
+static int breakpoints_failed;
+
+/* Nonzero after stop if current stack frame should be printed.  */
+
+static int stop_print_frame;
+
+#ifdef NO_SINGLE_STEP
+extern int one_stepped;                /* From machine dependent code */
+extern void single_step ();    /* Same. */
+#endif /* NO_SINGLE_STEP */
+
+static void insert_step_breakpoint ();
+static void remove_step_breakpoint ();
+/*static*/ void wait_for_inferior ();
+void init_wait_for_inferior ();
+void normal_stop ();
+
+\f
+/* Clear out all variables saying what to do when inferior is continued.
+   First do this, then set the ones you want, then call `proceed'.  */
+
+void
+clear_proceed_status ()
+{
+  trap_expected = 0;
+  step_range_start = 0;
+  step_range_end = 0;
+  step_frame_address = 0;
+  step_over_calls = -1;
+  step_resume_break_address = 0;
+  stop_after_trap = 0;
+  stop_soon_quietly = 0;
+  proceed_to_finish = 0;
+  breakpoint_proceeded = 1;    /* We're about to proceed... */
+
+  /* Discard any remaining commands or status from previous stop.  */
+  bpstat_clear (&stop_bpstat);
+}
+
+/* Basic routine for continuing the program in various fashions.
+
+   ADDR is the address to resume at, or -1 for resume where stopped.
+   SIGGNAL is the signal to give it, or 0 for none,
+     or -1 for act according to how it stopped.
+   STEP is nonzero if should trap after one instruction.
+     -1 means return after that and print nothing.
+     You should probably set various step_... variables
+     before calling here, if you are stepping.
+
+   You should call clear_proceed_status before calling proceed.  */
+
+void
+proceed (addr, siggnal, step)
+     CORE_ADDR addr;
+     int siggnal;
+     int step;
+{
+  int oneproc = 0;
+
+  if (step > 0)
+    step_start_function = find_pc_function (read_pc ());
+  if (step < 0)
+    stop_after_trap = 1;
+
+  if (addr == -1)
+    {
+      /* If there is a breakpoint at the address we will resume at,
+        step one instruction before inserting breakpoints
+        so that we do not stop right away.  */
+
+      if (!pc_changed && breakpoint_here_p (read_pc ()))
+       oneproc = 1;
+    }
+  else
+    {
+      write_register (PC_REGNUM, addr);
+#ifdef NPC_REGNUM
+      write_register (NPC_REGNUM, addr + 4);
+#ifdef NNPC_REGNUM
+      write_register (NNPC_REGNUM, addr + 8);
+#endif
+#endif
+    }
+
+  if (trap_expected_after_continue)
+    {
+      /* If (step == 0), a trap will be automatically generated after
+        the first instruction is executed.  Force step one
+        instruction to clear this condition.  This should not occur
+        if step is nonzero, but it is harmless in that case.  */
+      oneproc = 1;
+      trap_expected_after_continue = 0;
+    }
+
+  if (oneproc)
+    /* We will get a trace trap after one instruction.
+       Continue it automatically and insert breakpoints then.  */
+    trap_expected = 1;
+  else
+    {
+      int temp = insert_breakpoints ();
+      if (temp)
+       {
+         print_sys_errmsg ("ptrace", temp);
+         error ("Cannot insert breakpoints.\n\
+The same program may be running in another process.");
+       }
+      breakpoints_inserted = 1;
+    }
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  if (siggnal >= 0)
+    stop_signal = siggnal;
+  /* If this signal should not be seen by program,
+     give it zero.  Used for debugging signals.  */
+  else if (stop_signal < NSIG && !signal_program[stop_signal])
+    stop_signal= 0;
+
+  /* Handle any optimized stores to the inferior NOW...  */
+#ifdef DO_DEFERRED_STORES
+  DO_DEFERRED_STORES;
+#endif
+
+  /* Resume inferior.  */
+  target_resume (oneproc || step || bpstat_should_step (), stop_signal);
+
+  /* Wait for it to stop (if not standalone)
+     and in any case decode why it stopped, and act accordingly.  */
+
+  wait_for_inferior ();
+  normal_stop ();
+}
+
+#if 0
+/* This might be useful (not sure), but isn't currently used.  See also
+   write_pc().  */
+/* Writing the inferior pc as a register calls this function
+   to inform infrun that the pc has been set in the debugger.  */
+
+void
+writing_pc (val)
+     CORE_ADDR val;
+{
+  stop_pc = val;
+  pc_changed = 1;
+}
+#endif
+
+/* Record the pc and sp of the program the last time it stopped.
+   These are just used internally by wait_for_inferior, but need
+   to be preserved over calls to it and cleared when the inferior
+   is started.  */
+static CORE_ADDR prev_pc;
+static CORE_ADDR prev_sp;
+static CORE_ADDR prev_func_start;
+static char *prev_func_name;
+
+/* Start an inferior Unix child process and sets inferior_pid to its pid.
+   EXEC_FILE is the file to run.
+   ALLARGS is a string containing the arguments to the program.
+   ENV is the environment vector to pass.  Errors reported with error().  */
+
+#ifndef SHELL_FILE
+#define SHELL_FILE "/bin/sh"
+#endif
+
+void
+child_create_inferior (exec_file, allargs, env)
+     char *exec_file;
+     char *allargs;
+     char **env;
+{
+  int pid;
+  char *shell_command;
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  char *shell_file;
+  static char default_shell_file[] = SHELL_FILE;
+  int len;
+  int pending_execs;
+  /* Set debug_fork then attach to the child while it sleeps, to debug. */
+  static int debug_fork = 0;
+  /* This is set to the result of setpgrp, which if vforked, will be visible
+     to you in the parent process.  It's only used by humans for debugging.  */
+  static int debug_setpgrp = 657473;
+
+  /* The user might want tilde-expansion, and in general probably wants
+     the program to behave the same way as if run from
+     his/her favorite shell.  So we let the shell run it for us.
+     FIXME, this should probably search the local environment (as
+     modified by the setenv command), not the env gdb inherited.  */
+  shell_file = getenv ("SHELL");
+  if (shell_file == NULL)
+    shell_file = default_shell_file;
+  
+  len = 5 + strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 10;
+  /* If desired, concat something onto the front of ALLARGS.
+     SHELL_COMMAND is the result.  */
+#ifdef SHELL_COMMAND_CONCAT
+  shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + len);
+  strcpy (shell_command, SHELL_COMMAND_CONCAT);
+#else
+  shell_command = (char *) alloca (len);
+  shell_command[0] = '\0';
+#endif
+  strcat (shell_command, "exec ");
+  strcat (shell_command, exec_file);
+  strcat (shell_command, " ");
+  strcat (shell_command, allargs);
+
+  /* exec is said to fail if the executable is open.  */
+  close_exec_file ();
+
+#if defined(USG) && !defined(HAVE_VFORK)
+  pid = fork ();
+#else
+  if (debug_fork)
+    pid = fork ();
+  else
+    pid = vfork ();
+#endif
+
+  if (pid < 0)
+    perror_with_name ("vfork");
+
+  if (pid == 0)
+    {
+      if (debug_fork) 
+       sleep (debug_fork);
+
+#ifdef TIOCGPGRP
+      /* Run inferior in a separate process group.  */
+      debug_setpgrp = setpgrp (getpid (), getpid ());
+      if (0 != debug_setpgrp)
+        perror("setpgrp failed in child");
+#endif /* TIOCGPGRP */
+
+#ifdef SET_STACK_LIMIT_HUGE
+      /* Reset the stack limit back to what it was.  */
+      {
+       struct rlimit rlim;
+
+       getrlimit (RLIMIT_STACK, &rlim);
+       rlim.rlim_cur = original_stack_limit;
+       setrlimit (RLIMIT_STACK, &rlim);
+      }
+#endif /* SET_STACK_LIMIT_HUGE */
+
+      /* Tell the terminal handling subsystem what tty we plan to run on;
+        it will now switch to that one if non-null.  */
+
+      new_tty (inferior_io_terminal);
+
+      /* Changing the signal handlers for the inferior after
+        a vfork can also change them for the superior, so we don't mess
+        with signals here.  See comments in
+        initialize_signals for how we get the right signal handlers
+        for the inferior.  */
+
+      call_ptrace (0, 0, 0, 0);                /* "Trace me, Dr. Memory!" */
+      execle (shell_file, shell_file, "-c", shell_command, (char *)0, env);
+
+      fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
+              errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+      fflush (stderr);
+      _exit (0177);
+    }
+
+  /* Now that we have a child process, make it our target.  */
+  push_target (&child_ops);
+
+#ifdef CREATE_INFERIOR_HOOK
+  CREATE_INFERIOR_HOOK (pid);
+#endif  
+
+/* The process was started by the fork that created it,
+   but it will have stopped one instruction after execing the shell.
+   Here we must get it up to actual execution of the real program.  */
+
+  inferior_pid = pid;          /* Needed for wait_for_inferior stuff below */
+
+  clear_proceed_status ();
+
+#if defined (START_INFERIOR_HOOK)
+  START_INFERIOR_HOOK ();
+#endif
+
+  /* We will get a trace trap after one instruction.
+     Continue it automatically.  Eventually (after shell does an exec)
+     it will get another trace trap.  Then insert breakpoints and continue.  */
+
+#ifdef START_INFERIOR_TRAPS_EXPECTED
+  pending_execs = START_INFERIOR_TRAPS_EXPECTED;
+#else
+  pending_execs = 2;
+#endif
+
+  init_wait_for_inferior ();
+
+  /* Set up the "saved terminal modes" of the inferior
+     based on what modes we are starting it with.  */
+  target_terminal_init ();
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  while (1)
+    {
+      stop_soon_quietly = 1;   /* Make wait_for_inferior be quiet */
+      wait_for_inferior ();
+      if (stop_signal != SIGTRAP)
+       {
+         /* Let shell child handle its own signals in its own way */
+         /* FIXME, what if child has exit()ed?  Must exit loop somehow */
+         target_resume (0, stop_signal);
+       }
+      else
+       {
+         /* We handle SIGTRAP, however; it means child did an exec.  */
+         if (0 == --pending_execs)
+           break;
+         target_resume (0, 0);         /* Just make it go on */
+       }
+    }
+  stop_soon_quietly = 0;
+
+  /* Should this perhaps just be a "proceed" call?  FIXME */
+  insert_step_breakpoint ();
+  breakpoints_failed = insert_breakpoints ();
+  if (!breakpoints_failed)
+    {
+      breakpoints_inserted = 1;
+      target_terminal_inferior();
+      /* Start the child program going on its first instruction, single-
+        stepping if we need to.  */
+      target_resume (bpstat_should_step (), 0);
+      wait_for_inferior ();
+      normal_stop ();
+    }
+}
+
+/* Start remote-debugging of a machine over a serial link.  */
+
+void
+start_remote ()
+{
+  init_wait_for_inferior ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  trap_expected = 0;
+}
+
+/* Initialize static vars when a new inferior begins.  */
+
+void
+init_wait_for_inferior ()
+{
+  /* These are meaningless until the first time through wait_for_inferior.  */
+  prev_pc = 0;
+  prev_sp = 0;
+  prev_func_start = 0;
+  prev_func_name = NULL;
+
+  trap_expected_after_continue = 0;
+  breakpoints_inserted = 0;
+  mark_breakpoints_out ();
+  stop_signal = 0;             /* Don't confuse first call to proceed(). */
+}
+
+
+/* Attach to process PID, then initialize for debugging it
+   and wait for the trace-trap that results from attaching.  */
+
+void
+child_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file;
+  int pid;
+
+  dont_repeat();
+
+  if (!args)
+    error_no_arg ("process-id to attach");
+
+#ifndef ATTACH_DETACH
+  error ("Can't attach to a process on this machine.");
+#else
+  pid = atoi (args);
+
+  if (target_has_execution)
+    {
+      if (query ("A program is being debugged already.  Kill it? "))
+       target_kill ((char *)0, from_tty);
+      else
+       error ("Inferior not killed.");
+    }
+
+  exec_file = (char *) get_exec_file (1);
+
+  if (from_tty)
+    {
+      printf ("Attaching program: %s pid %d\n",
+             exec_file, pid);
+      fflush (stdout);
+    }
+
+  attach (pid);
+  inferior_pid = pid;
+  push_target (&child_ops);
+
+  mark_breakpoints_out ();
+  target_terminal_init ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  /*proceed (-1, 0, -2);*/
+  target_terminal_inferior ();
+  wait_for_inferior ();
+  normal_stop ();
+#endif  /* ATTACH_DETACH */
+}
+\f
+/* Wait for control to return from inferior to debugger.
+   If inferior gets a signal, we may decide to start it up again
+   instead of returning.  That is why there is a loop in this function.
+   When this function actually returns it means the inferior
+   should be left stopped and GDB should read more commands.  */
+
+void
+wait_for_inferior ()
+{
+  WAITTYPE w;
+  int another_trap;
+  int random_signal;
+  CORE_ADDR stop_sp;
+  CORE_ADDR stop_func_start;
+  char *stop_func_name;
+  CORE_ADDR prologue_pc;
+  int stop_step_resume_break;
+  struct symtab_and_line sal;
+  int remove_breakpoints_on_following_step = 0;
+
+#if 0
+  /* This no longer works now that read_register is lazy;
+     it might try to ptrace when the process is not stopped.  */
+  prev_pc = read_pc ();
+  (void) find_pc_partial_function (prev_pc, &prev_func_name,
+                                  &prev_func_start);
+  prev_func_start += FUNCTION_START_OFFSET;
+  prev_sp = read_register (SP_REGNUM);
+#endif /* 0 */
+
+  while (1)
+    {
+      /* Clean up saved state that will become invalid.  */
+      pc_changed = 0;
+      flush_cached_frames ();
+      registers_changed ();
+
+      target_wait (&w);
+
+      /* See if the process still exists; clean up if it doesn't.  */
+      if (WIFEXITED (w))
+       {
+         target_terminal_ours ();      /* Must do this before mourn anyway */
+         if (WEXITSTATUS (w))
+           printf ("\nProgram exited with code 0%o.\n", 
+                    (unsigned int)WEXITSTATUS (w));
+         else
+           if (!batch_mode())
+             printf ("\nProgram exited normally.\n");
+         fflush (stdout);
+         target_mourn_inferior ();
+#ifdef NO_SINGLE_STEP
+         one_stepped = 0;
+#endif
+         stop_print_frame = 0;
+         break;
+       }
+      else if (!WIFSTOPPED (w))
+       {
+         stop_print_frame = 0;
+         stop_signal = WTERMSIG (w);
+         target_terminal_ours ();      /* Must do this before mourn anyway */
+         target_kill ((char *)0, 0);   /* kill mourns as well */
+#ifdef PRINT_RANDOM_SIGNAL
+         printf ("\nProgram terminated: ");
+         PRINT_RANDOM_SIGNAL (stop_signal);
+#else
+         printf ("\nProgram terminated with signal %d, %s\n",
+                 stop_signal,
+                 stop_signal < NSIG
+                 ? sys_siglist[stop_signal]
+                 : "(undocumented)");
+#endif
+         printf ("The inferior process no longer exists.\n");
+         fflush (stdout);
+#ifdef NO_SINGLE_STEP
+         one_stepped = 0;
+#endif
+         break;
+       }
+      
+#ifdef NO_SINGLE_STEP
+      if (one_stepped)
+       single_step (0);        /* This actually cleans up the ss */
+#endif /* NO_SINGLE_STEP */
+      
+      stop_pc = read_pc ();
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      
+      stop_frame_address = FRAME_FP (get_current_frame ());
+      stop_sp = read_register (SP_REGNUM);
+      stop_func_start = 0;
+      stop_func_name = 0;
+      /* Don't care about return value; stop_func_start and stop_func_name
+        will both be 0 if it doesn't work.  */
+      (void) find_pc_partial_function (stop_pc, &stop_func_name,
+                                      &stop_func_start);
+      stop_func_start += FUNCTION_START_OFFSET;
+      another_trap = 0;
+      bpstat_clear (&stop_bpstat);
+      stop_step = 0;
+      stop_stack_dummy = 0;
+      stop_print_frame = 1;
+      stop_step_resume_break = 0;
+      random_signal = 0;
+      stopped_by_random_signal = 0;
+      breakpoints_failed = 0;
+      
+      /* Look at the cause of the stop, and decide what to do.
+        The alternatives are:
+        1) break; to really stop and return to the debugger,
+        2) drop through to start up again
+        (set another_trap to 1 to single step once)
+        3) set random_signal to 1, and the decision between 1 and 2
+        will be made according to the signal handling tables.  */
+      
+      stop_signal = WSTOPSIG (w);
+      
+      /* First, distinguish signals caused by the debugger from signals
+        that have to do with the program's own actions.
+        Note that breakpoint insns may cause SIGTRAP or SIGILL
+        or SIGEMT, depending on the operating system version.
+        Here we detect when a SIGILL or SIGEMT is really a breakpoint
+        and change it to SIGTRAP.  */
+      
+      if (stop_signal == SIGTRAP
+         || (breakpoints_inserted &&
+             (stop_signal == SIGILL
+              || stop_signal == SIGEMT))
+         || stop_soon_quietly)
+       {
+         if (stop_signal == SIGTRAP && stop_after_trap)
+           {
+             stop_print_frame = 0;
+             break;
+           }
+         if (stop_soon_quietly)
+           break;
+
+         /* Don't even think about breakpoints
+            if just proceeded over a breakpoint.
+
+            However, if we are trying to proceed over a breakpoint
+            and end up in sigtramp, then step_resume_break_address
+            will be set and we should check whether we've hit the
+            step breakpoint.  */
+         if (stop_signal == SIGTRAP && trap_expected
+             && step_resume_break_address == NULL)
+           bpstat_clear (&stop_bpstat);
+         else
+           {
+             /* See if there is a breakpoint at the current PC.  */
+#if DECR_PC_AFTER_BREAK
+             /* Notice the case of stepping through a jump
+                that leads just after a breakpoint.
+                Don't confuse that with hitting the breakpoint.
+                What we check for is that 1) stepping is going on
+                and 2) the pc before the last insn does not match
+                the address of the breakpoint before the current pc.  */
+             if (!(prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+                   && step_range_end && !step_resume_break_address))
+#endif /* DECR_PC_AFTER_BREAK not zero */
+               {
+                 /* See if we stopped at the special breakpoint for
+                    stepping over a subroutine call.  If both are zero,
+                    this wasn't the reason for the stop.  */
+                 if (stop_pc - DECR_PC_AFTER_BREAK
+                                 == step_resume_break_address
+                     && step_resume_break_address)
+                   {
+                     stop_step_resume_break = 1;
+                     if (DECR_PC_AFTER_BREAK)
+                       {
+                         stop_pc -= DECR_PC_AFTER_BREAK;
+                         write_register (PC_REGNUM, stop_pc);
+                         pc_changed = 0;
+                       }
+                   }
+                 else
+                   {
+                     stop_bpstat =
+                       bpstat_stop_status (&stop_pc, stop_frame_address);
+                     /* Following in case break condition called a
+                        function.  */
+                     stop_print_frame = 1;
+                   }
+               }
+           }
+         
+         if (stop_signal == SIGTRAP)
+           random_signal
+             = !(bpstat_explains_signal (stop_bpstat)
+                 || trap_expected
+                 || stop_step_resume_break
+                 || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+                 || (step_range_end && !step_resume_break_address));
+         else
+           {
+             random_signal
+               = !(bpstat_explains_signal (stop_bpstat)
+                   || stop_step_resume_break
+                   /* End of a stack dummy.  Some systems (e.g. Sony
+                      news) give another signal besides SIGTRAP,
+                      so check here as well as above.  */
+                   || (stop_sp INNER_THAN stop_pc
+                       && stop_pc INNER_THAN stop_frame_address)
+                   );
+             if (!random_signal)
+               stop_signal = SIGTRAP;
+           }
+       }
+      else
+       random_signal = 1;
+      
+      /* For the program's own signals, act according to
+        the signal handling tables.  */
+      
+      if (random_signal)
+       {
+         /* Signal not for debugging purposes.  */
+         int printed = 0;
+         
+         stopped_by_random_signal = 1;
+         
+         if (stop_signal >= NSIG
+             || signal_print[stop_signal])
+           {
+             printed = 1;
+             target_terminal_ours_for_output ();
+#ifdef PRINT_RANDOM_SIGNAL
+             PRINT_RANDOM_SIGNAL (stop_signal);
+#else
+             printf ("\nProgram received signal %d, %s\n",
+                     stop_signal,
+                     stop_signal < NSIG
+                     ? sys_siglist[stop_signal]
+                     : "(undocumented)");
+#endif /* PRINT_RANDOM_SIGNAL */
+             fflush (stdout);
+           }
+         if (stop_signal >= NSIG
+             || signal_stop[stop_signal])
+           break;
+         /* If not going to stop, give terminal back
+            if we took it away.  */
+         else if (printed)
+           target_terminal_inferior ();
+       }
+      
+      /* Handle cases caused by hitting a breakpoint.  */
+      
+      if (!random_signal
+         && (bpstat_explains_signal (stop_bpstat) || stop_step_resume_break))
+       {
+         /* Does a breakpoint want us to stop?  */
+         if (bpstat_stop (stop_bpstat))
+           {
+             stop_print_frame = bpstat_should_print (stop_bpstat);
+             break;
+           }
+         /* But if we have hit the step-resumption breakpoint,
+            remove it.  It has done its job getting us here.
+            The sp test is to make sure that we don't get hung
+            up in recursive calls in functions without frame
+            pointers.  If the stack pointer isn't outside of
+            where the breakpoint was set (within a routine to be
+            stepped over), we're in the middle of a recursive
+            call. Not true for reg window machines (sparc)
+            because the must change frames to call things and
+            the stack pointer doesn't have to change if it
+            the bp was set in a routine without a frame (pc can
+            be stored in some other window).
+            
+            The removal of the sp test is to allow calls to
+            alloca.  Nasty things were happening.  Oh, well,
+            gdb can only handle one level deep of lack of
+            frame pointer. */
+         if (stop_step_resume_break
+             && (step_frame_address == 0
+                 || (stop_frame_address == step_frame_address)))
+           {
+             remove_step_breakpoint ();
+             step_resume_break_address = 0;
+
+             /* If were waiting for a trap, hitting the step_resume_break
+                doesn't count as getting it.  */
+             if (trap_expected)
+               another_trap = 1;
+           }
+         /* Otherwise, must remove breakpoints and single-step
+            to get us past the one we hit.  */
+         else
+           {
+             remove_breakpoints ();
+             remove_step_breakpoint ();
+             breakpoints_inserted = 0;
+             another_trap = 1;
+           }
+         
+         /* We come here if we hit a breakpoint but should not
+            stop for it.  Possibly we also were stepping
+            and should stop for that.  So fall through and
+            test for stepping.  But, if not stepping,
+            do not stop.  */
+       }
+      
+      /* If this is the breakpoint at the end of a stack dummy,
+        just stop silently.  */
+      if (PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address))
+         {
+           stop_print_frame = 0;
+           stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+           trap_expected_after_continue = 1;
+#endif
+           break;
+         }
+      
+      if (step_resume_break_address)
+       /* Having a step-resume breakpoint overrides anything
+          else having to do with stepping commands until
+          that breakpoint is reached.  */
+       ;
+      /* If stepping through a line, keep going if still within it.  */
+      else if (!random_signal
+              && step_range_end
+              && stop_pc >= step_range_start
+              && stop_pc < step_range_end
+              /* The step range might include the start of the
+                 function, so if we are at the start of the
+                 step range and either the stack or frame pointers
+                 just changed, we've stepped outside */
+              && !(stop_pc == step_range_start
+                   && stop_frame_address
+                   && (stop_sp INNER_THAN prev_sp
+                       || stop_frame_address != step_frame_address)))
+       {
+#if 0
+         /* When "next"ing through a function,
+            This causes an extra stop at the end.
+            Is there any reason for this?
+            It's confusing to the user.  */
+         /* Don't step through the return from a function
+            unless that is the first instruction stepped through.  */
+         if (ABOUT_TO_RETURN (stop_pc))
+           {
+             stop_step = 1;
+             break;
+           }
+#endif
+       }
+      
+      /* We stepped out of the stepping range.  See if that was due
+        to a subroutine call that we should proceed to the end of.  */
+      else if (!random_signal && step_range_end)
+       {
+         if (stop_func_start)
+           {
+             prologue_pc = stop_func_start;
+             SKIP_PROLOGUE (prologue_pc);
+           }
+
+         /* Did we just take a signal?  */
+         if (IN_SIGTRAMP (stop_pc, stop_func_name)
+             && !IN_SIGTRAMP (prev_pc, prev_func_name))
+           {
+             /* This code is needed at least in the following case:
+                The user types "next" and then a signal arrives (before
+                the "next" is done).  */
+             /* We've just taken a signal; go until we are back to
+                the point where we took it and one more.  */
+             step_resume_break_address = prev_pc;
+             step_resume_break_duplicate =
+               breakpoint_here_p (step_resume_break_address);
+             if (breakpoints_inserted)
+               insert_step_breakpoint ();
+             /* Make sure that the stepping range gets us past
+                that instruction.  */
+             if (step_range_end == 1)
+               step_range_end = (step_range_start = prev_pc) + 1;
+             remove_breakpoints_on_following_step = 1;
+           }
+
+         /* ==> See comments at top of file on this algorithm.  <==*/
+         
+         else if (stop_pc == stop_func_start
+             && (stop_func_start != prev_func_start
+                 || prologue_pc != stop_func_start
+                 || stop_sp != prev_sp))
+           {
+             /* It's a subroutine call */
+             if (step_over_calls > 0 
+                 || (step_over_calls &&  find_pc_function (stop_pc) == 0))
+               {
+                 /* A subroutine call has happened.  */
+                 /* Set a special breakpoint after the return */
+                 step_resume_break_address =
+                   ADDR_BITS_REMOVE
+                     (SAVED_PC_AFTER_CALL (get_current_frame ()));
+                 step_resume_break_duplicate
+                   = breakpoint_here_p (step_resume_break_address);
+                 if (breakpoints_inserted)
+                   insert_step_breakpoint ();
+               }
+             /* Subroutine call with source code we should not step over.
+                Do step to the first line of code in it.  */
+             else if (step_over_calls)
+               {
+                 SKIP_PROLOGUE (stop_func_start);
+                 sal = find_pc_line (stop_func_start, 0);
+                 /* Use the step_resume_break to step until
+                    the end of the prologue, even if that involves jumps
+                    (as it seems to on the vax under 4.2).  */
+                 /* If the prologue ends in the middle of a source line,
+                    continue to the end of that source line.
+                    Otherwise, just go to end of prologue.  */
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+                 /* no, don't either.  It skips any code that's
+                    legitimately on the first line.  */
+#else
+                 if (sal.end && sal.pc != stop_func_start)
+                   stop_func_start = sal.end;
+#endif
+                 
+                 if (stop_func_start == stop_pc)
+                   {
+                     /* We are already there: stop now.  */
+                     stop_step = 1;
+                     break;
+                   }
+                 else
+                   /* Put the step-breakpoint there and go until there. */
+                   {
+                     step_resume_break_address = stop_func_start;
+                     
+                     step_resume_break_duplicate
+                       = breakpoint_here_p (step_resume_break_address);
+                     if (breakpoints_inserted)
+                       insert_step_breakpoint ();
+                     /* Do not specify what the fp should be when we stop
+                        since on some machines the prologue
+                        is where the new fp value is established.  */
+                     step_frame_address = 0;
+                     /* And make sure stepping stops right away then.  */
+                     step_range_end = step_range_start;
+                   }
+               }
+             else
+               {
+                 /* We get here only if step_over_calls is 0 and we
+                    just stepped into a subroutine.  I presume
+                    that step_over_calls is only 0 when we're
+                    supposed to be stepping at the assembly
+                    language level.*/
+                 stop_step = 1;
+                 break;
+               }
+           }
+         /* No subroutince call; stop now.  */
+         else
+           {
+             stop_step = 1;
+             break;
+           }
+       }
+
+      else if (trap_expected
+              && IN_SIGTRAMP (stop_pc, stop_func_name)
+              && !IN_SIGTRAMP (prev_pc, prev_func_name))
+       {
+         /* What has happened here is that we have just stepped the inferior
+            with a signal (because it is a signal which shouldn't make
+            us stop), thus stepping into sigtramp.
+
+            So we need to set a step_resume_break_address breakpoint
+            and continue until we hit it, and then step.  */
+         step_resume_break_address = prev_pc;
+         /* Always 1, I think, but it's probably easier to have
+            the step_resume_break as usual rather than trying to
+            re-use the breakpoint which is already there.  */
+         step_resume_break_duplicate =
+           breakpoint_here_p (step_resume_break_address);
+         if (breakpoints_inserted)
+           insert_step_breakpoint ();
+         remove_breakpoints_on_following_step = 1;
+         another_trap = 1;
+       }
+
+      /* Save the pc before execution, to compare with pc after stop.  */
+      prev_pc = read_pc ();    /* Might have been DECR_AFTER_BREAK */
+      prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER
+                                         BREAK is defined, the
+                                         original pc would not have
+                                         been at the start of a
+                                         function. */
+      prev_func_name = stop_func_name;
+      prev_sp = stop_sp;
+
+      /* If we did not do break;, it means we should keep
+        running the inferior and not return to debugger.  */
+
+      if (trap_expected && stop_signal != SIGTRAP)
+       {
+         /* We took a signal (which we are supposed to pass through to
+            the inferior, else we'd have done a break above) and we
+            haven't yet gotten our trap.  Simply continue.  */
+         target_resume ((step_range_end && !step_resume_break_address)
+                 || (trap_expected && !step_resume_break_address)
+                 || bpstat_should_step (),
+                 stop_signal);
+       }
+      else
+       {
+         /* Either the trap was not expected, but we are continuing
+            anyway (the user asked that this signal be passed to the
+            child)
+              -- or --
+            The signal was SIGTRAP, e.g. it was our signal, but we
+            decided we should resume from it.
+
+            We're going to run this baby now!
+
+            Insert breakpoints now, unless we are trying
+            to one-proceed past a breakpoint.  */
+         /* If we've just finished a special step resume and we don't
+            want to hit a breakpoint, pull em out.  */
+         if (!step_resume_break_address &&
+             remove_breakpoints_on_following_step)
+           {
+             remove_breakpoints_on_following_step = 0;
+             remove_breakpoints ();
+             breakpoints_inserted = 0;
+           }
+         else if (!breakpoints_inserted &&
+                  (step_resume_break_address != NULL || !another_trap))
+           {
+             insert_step_breakpoint ();
+             breakpoints_failed = insert_breakpoints ();
+             if (breakpoints_failed)
+               break;
+             breakpoints_inserted = 1;
+           }
+
+         trap_expected = another_trap;
+
+         if (stop_signal == SIGTRAP)
+           stop_signal = 0;
+
+#ifdef SHIFT_INST_REGS
+         /* I'm not sure when this following segment applies.  I do know, now,
+            that we shouldn't rewrite the regs when we were stopped by a
+            random signal from the inferior process.  */
+
+          if (!stop_breakpoint && (stop_signal != SIGCLD) 
+              && !stopped_by_random_signal)
+            {
+            CORE_ADDR pc_contents = read_register (PC_REGNUM);
+            CORE_ADDR npc_contents = read_register (NPC_REGNUM);
+            if (pc_contents != npc_contents)
+              {
+              write_register (NNPC_REGNUM, npc_contents);
+              write_register (NPC_REGNUM, pc_contents);
+             }
+            }
+#endif /* SHIFT_INST_REGS */
+
+         target_resume ((step_range_end && !step_resume_break_address)
+                 || (trap_expected && !step_resume_break_address)
+                 || bpstat_should_step (),
+                 stop_signal);
+       }
+    }
+  if (target_has_execution)
+    {
+      /* Assuming the inferior still exists, set these up for next
+        time, just like we did above if we didn't break out of the
+        loop.  */
+      prev_pc = read_pc ();
+      prev_func_start = stop_func_start;
+      prev_func_name = stop_func_name;
+      prev_sp = stop_sp;
+    }
+}
+\f
+/* Here to return control to GDB when the inferior stops for real.
+   Print appropriate messages, remove breakpoints, give terminal our modes.
+
+   STOP_PRINT_FRAME nonzero means print the executing frame
+   (pc, function, args, file, line number and line text).
+   BREAKPOINTS_FAILED nonzero means stop was due to error
+   attempting to insert breakpoints.  */
+
+void
+normal_stop ()
+{
+  /* Make sure that the current_frame's pc is correct.  This
+     is a correction for setting up the frame info before doing
+     DECR_PC_AFTER_BREAK */
+  if (target_has_execution)
+    (get_current_frame ())->pc = read_pc ();
+  
+  if (breakpoints_failed)
+    {
+      target_terminal_ours_for_output ();
+      print_sys_errmsg ("ptrace", breakpoints_failed);
+      printf ("Stopped; cannot insert breakpoints.\n\
+The same program may be running in another process.\n");
+    }
+
+  if (target_has_execution)
+    remove_step_breakpoint ();
+
+  if (target_has_execution && breakpoints_inserted)
+    if (remove_breakpoints ())
+      {
+       target_terminal_ours_for_output ();
+       printf ("Cannot remove breakpoints because program is no longer writable.\n\
+It might be running in another process.\n\
+Further execution is probably impossible.\n");
+      }
+
+  breakpoints_inserted = 0;
+
+  /* Delete the breakpoint we stopped at, if it wants to be deleted.
+     Delete any breakpoint that is to be deleted at the next stop.  */
+
+  breakpoint_auto_delete (stop_bpstat);
+
+  /* If an auto-display called a function and that got a signal,
+     delete that auto-display to avoid an infinite recursion.  */
+
+  if (stopped_by_random_signal)
+    disable_current_display ();
+
+  if (step_multi && stop_step)
+    return;
+
+  target_terminal_ours ();
+
+  if (!target_has_stack)
+    return;
+
+  /* Select innermost stack frame except on return from a stack dummy routine,
+     or if the program has exited.  */
+  if (!stop_stack_dummy)
+    {
+      select_frame (get_current_frame (), 0);
+
+      if (stop_print_frame)
+       {
+         int source_only = bpstat_print (stop_bpstat);
+         print_sel_frame
+           (source_only
+            || (stop_step
+                && step_frame_address == stop_frame_address
+                && step_start_function == find_pc_function (stop_pc)));
+
+         /* Display the auto-display expressions.  */
+         do_displays ();
+       }
+    }
+
+  /* Save the function value return registers, if we care.
+     We might be about to restore their previous contents.  */
+  if (proceed_to_finish)
+    read_register_bytes (0, stop_registers, REGISTER_BYTES);
+
+  if (stop_stack_dummy)
+    {
+      /* Pop the empty frame that contains the stack dummy.
+         POP_FRAME ends with a setting of the current frame, so we
+        can use that next. */
+      POP_FRAME;
+      select_frame (get_current_frame (), 0);
+    }
+}
+\f
+static void
+insert_step_breakpoint ()
+{
+  if (step_resume_break_address && !step_resume_break_duplicate)
+    target_insert_breakpoint (step_resume_break_address,
+                             step_resume_break_shadow);
+}
+
+static void
+remove_step_breakpoint ()
+{
+  if (step_resume_break_address && !step_resume_break_duplicate)
+    target_remove_breakpoint (step_resume_break_address,
+                             step_resume_break_shadow);
+}
+\f
+static void
+sig_print_header ()
+{
+  printf_filtered ("Signal\t\tStop\tPrint\tPass to program\tDescription\n");
+}
+
+static void
+sig_print_info (number)
+     int number;
+{
+  char *abbrev = sig_abbrev(number);
+  if (abbrev == NULL)
+    printf_filtered ("%d\t\t", number);
+  else
+    printf_filtered ("SIG%s (%d)\t", abbrev, number);
+  printf_filtered ("%s\t", signal_stop[number] ? "Yes" : "No");
+  printf_filtered ("%s\t", signal_print[number] ? "Yes" : "No");
+  printf_filtered ("%s\t\t", signal_program[number] ? "Yes" : "No");
+  printf_filtered ("%s\n", sys_siglist[number]);
+}
+
+/* Specify how various signals in the inferior should be handled.  */
+
+static void
+handle_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  register char *p = args;
+  int signum = 0;
+  register int digits, wordlen;
+  char *nextarg;
+
+  if (!args)
+    error_no_arg ("signal to handle");
+
+  while (*p)
+    {
+      /* Find the end of the next word in the args.  */
+      for (wordlen = 0;
+          p[wordlen] && p[wordlen] != ' ' && p[wordlen] != '\t';
+          wordlen++);
+      /* Set nextarg to the start of the word after the one we just
+        found, and null-terminate this one.  */
+      if (p[wordlen] == '\0')
+       nextarg = p + wordlen;
+      else
+       {
+         p[wordlen] = '\0';
+         nextarg = p + wordlen + 1;
+       }
+      
+
+      for (digits = 0; p[digits] >= '0' && p[digits] <= '9'; digits++);
+
+      if (signum == 0)
+       {
+         /* It is the first argument--must be the signal to operate on.  */
+         if (digits == wordlen)
+           {
+             /* Numeric.  */
+             signum = atoi (p);
+             if (signum <= 0 || signum >= NSIG)
+               {
+                 p[wordlen] = '\0';
+                 error ("Invalid signal %s given as argument to \"handle\".", p);
+               }
+           }
+         else
+           {
+             /* Symbolic.  */
+             signum = sig_number (p);
+             if (signum == -1)
+               error ("No such signal \"%s\"", p);
+           }
+
+         if (signum == SIGTRAP || signum == SIGINT)
+           {
+             if (!query ("SIG%s is used by the debugger.\nAre you sure you want to change it? ", sig_abbrev (signum)))
+               error ("Not confirmed.");
+           }
+       }
+      /* Else, if already got a signal number, look for flag words
+        saying what to do for it.  */
+      else if (!strncmp (p, "stop", wordlen))
+       {
+         signal_stop[signum] = 1;
+         signal_print[signum] = 1;
+       }
+      else if (wordlen >= 2 && !strncmp (p, "print", wordlen))
+       signal_print[signum] = 1;
+      else if (wordlen >= 2 && !strncmp (p, "pass", wordlen))
+       signal_program[signum] = 1;
+      else if (!strncmp (p, "ignore", wordlen))
+       signal_program[signum] = 0;
+      else if (wordlen >= 3 && !strncmp (p, "nostop", wordlen))
+       signal_stop[signum] = 0;
+      else if (wordlen >= 4 && !strncmp (p, "noprint", wordlen))
+       {
+         signal_print[signum] = 0;
+         signal_stop[signum] = 0;
+       }
+      else if (wordlen >= 4 && !strncmp (p, "nopass", wordlen))
+       signal_program[signum] = 0;
+      else if (wordlen >= 3 && !strncmp (p, "noignore", wordlen))
+       signal_program[signum] = 1;
+      /* Not a number and not a recognized flag word => complain.  */
+      else
+       {
+         error ("Unrecognized flag word: \"%s\".", p);
+       }
+
+      /* Find start of next word.  */
+      p = nextarg;
+      while (*p == ' ' || *p == '\t') p++;
+    }
+
+  if (from_tty)
+    {
+      /* Show the results.  */
+      sig_print_header ();
+      sig_print_info (signum);
+    }
+}
+
+/* Print current contents of the tables set by the handle command.  */
+
+static void
+signals_info (signum_exp)
+     char *signum_exp;
+{
+  register int i;
+  sig_print_header ();
+
+  if (signum_exp)
+    {
+      /* First see if this is a symbol name.  */
+      i = sig_number (signum_exp);
+      if (i == -1)
+       {
+         /* Nope, maybe it's an address which evaluates to a signal
+            number.  */
+         i = parse_and_eval_address (signum_exp);
+         if (i >= NSIG || i < 0)
+           error ("Signal number out of bounds.");
+       }
+      sig_print_info (i);
+      return;
+    }
+
+  printf_filtered ("\n");
+  for (i = 0; i < NSIG; i++)
+    {
+      QUIT;
+
+      sig_print_info (i);
+    }
+
+  printf_filtered ("\nUse the \"handle\" command to change these tables.\n");
+}
+\f
+/* Save all of the information associated with the inferior<==>gdb
+   connection.  INF_STATUS is a pointer to a "struct inferior_status"
+   (defined in inferior.h).  */
+
+void
+save_inferior_status (inf_status, restore_stack_info)
+     struct inferior_status *inf_status;
+     int restore_stack_info;
+{
+  inf_status->pc_changed = pc_changed;
+  inf_status->stop_signal = stop_signal;
+  inf_status->stop_pc = stop_pc;
+  inf_status->stop_frame_address = stop_frame_address;
+  inf_status->stop_step = stop_step;
+  inf_status->stop_stack_dummy = stop_stack_dummy;
+  inf_status->stopped_by_random_signal = stopped_by_random_signal;
+  inf_status->trap_expected = trap_expected;
+  inf_status->step_range_start = step_range_start;
+  inf_status->step_range_end = step_range_end;
+  inf_status->step_frame_address = step_frame_address;
+  inf_status->step_over_calls = step_over_calls;
+  inf_status->step_resume_break_address = step_resume_break_address;
+  inf_status->stop_after_trap = stop_after_trap;
+  inf_status->stop_soon_quietly = stop_soon_quietly;
+  /* Save original bpstat chain here; replace it with copy of chain. 
+     If caller's caller is walking the chain, they'll be happier if we
+     hand them back the original chain when restore_i_s is called.  */
+  inf_status->stop_bpstat = stop_bpstat;
+  stop_bpstat = bpstat_copy (stop_bpstat);
+  inf_status->breakpoint_proceeded = breakpoint_proceeded;
+  inf_status->restore_stack_info = restore_stack_info;
+  inf_status->proceed_to_finish = proceed_to_finish;
+  
+  bcopy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
+  
+  record_selected_frame (&(inf_status->selected_frame_address),
+                        &(inf_status->selected_level));
+  return;
+}
+
+void
+restore_inferior_status (inf_status)
+     struct inferior_status *inf_status;
+{
+  FRAME fid;
+  int level = inf_status->selected_level;
+
+  pc_changed = inf_status->pc_changed;
+  stop_signal = inf_status->stop_signal;
+  stop_pc = inf_status->stop_pc;
+  stop_frame_address = inf_status->stop_frame_address;
+  stop_step = inf_status->stop_step;
+  stop_stack_dummy = inf_status->stop_stack_dummy;
+  stopped_by_random_signal = inf_status->stopped_by_random_signal;
+  trap_expected = inf_status->trap_expected;
+  step_range_start = inf_status->step_range_start;
+  step_range_end = inf_status->step_range_end;
+  step_frame_address = inf_status->step_frame_address;
+  step_over_calls = inf_status->step_over_calls;
+  step_resume_break_address = inf_status->step_resume_break_address;
+  stop_after_trap = inf_status->stop_after_trap;
+  stop_soon_quietly = inf_status->stop_soon_quietly;
+  bpstat_clear (&stop_bpstat);
+  stop_bpstat = inf_status->stop_bpstat;
+  breakpoint_proceeded = inf_status->breakpoint_proceeded;
+  proceed_to_finish = inf_status->proceed_to_finish;
+
+  bcopy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
+
+  /* The inferior can be gone if the user types "print exit(0)"
+     (and perhaps other times).  */
+  if (target_has_stack && inf_status->restore_stack_info)
+    {
+      fid = find_relative_frame (get_current_frame (),
+                                &level);
+
+      if (fid == 0 ||
+         FRAME_FP (fid) != inf_status->selected_frame_address ||
+         level != 0)
+       {
+#if 0
+         /* I'm not sure this error message is a good idea.  I have
+            only seen it occur after "Can't continue previously
+            requested operation" (we get called from do_cleanups), in
+            which case it just adds insult to injury (one confusing
+            error message after another.  Besides which, does the
+            user really care if we can't restore the previously
+            selected frame?  */
+         fprintf (stderr, "Unable to restore previously selected frame.\n");
+#endif
+         select_frame (get_current_frame (), 0);
+         return;
+       }
+      
+      select_frame (fid, inf_status->selected_level);
+    }
+}
+
+\f
+void
+_initialize_infrun ()
+{
+  register int i;
+
+  add_info ("signals", signals_info,
+           "What debugger does when program gets various signals.\n\
+Specify a signal number as argument to print info on that signal only.");
+
+  add_com ("handle", class_run, handle_command,
+          "Specify how to handle a signal.\n\
+Args are signal number followed by flags.\n\
+Flags allowed are \"stop\", \"print\", \"pass\",\n\
+ \"nostop\", \"noprint\" or \"nopass\".\n\
+Print means print a message if this signal happens.\n\
+Stop means reenter debugger if this signal happens (implies print).\n\
+Pass means let program see this signal; otherwise program doesn't know.\n\
+Pass and Stop may be combined.");
+
+  for (i = 0; i < NSIG; i++)
+    {
+      signal_stop[i] = 1;
+      signal_print[i] = 1;
+      signal_program[i] = 1;
+    }
+
+  /* Signals caused by debugger's own actions
+     should not be given to the program afterwards.  */
+  signal_program[SIGTRAP] = 0;
+  signal_program[SIGINT] = 0;
+
+  /* Signals that are not errors should not normally enter the debugger.  */
+#ifdef SIGALRM
+  signal_stop[SIGALRM] = 0;
+  signal_print[SIGALRM] = 0;
+#endif /* SIGALRM */
+#ifdef SIGVTALRM
+  signal_stop[SIGVTALRM] = 0;
+  signal_print[SIGVTALRM] = 0;
+#endif /* SIGVTALRM */
+#ifdef SIGPROF
+  signal_stop[SIGPROF] = 0;
+  signal_print[SIGPROF] = 0;
+#endif /* SIGPROF */
+#ifdef SIGCHLD
+  signal_stop[SIGCHLD] = 0;
+  signal_print[SIGCHLD] = 0;
+#endif /* SIGCHLD */
+#ifdef SIGCLD
+  signal_stop[SIGCLD] = 0;
+  signal_print[SIGCLD] = 0;
+#endif /* SIGCLD */
+#ifdef SIGIO
+  signal_stop[SIGIO] = 0;
+  signal_print[SIGIO] = 0;
+#endif /* SIGIO */
+#ifdef SIGURG
+  signal_stop[SIGURG] = 0;
+  signal_print[SIGURG] = 0;
+#endif /* SIGURG */
+}
+
diff --git a/gdb/inftarg.c b/gdb/inftarg.c
new file mode 100644 (file)
index 0000000..ce64437
--- /dev/null
@@ -0,0 +1,182 @@
+/* Subroutines for handling an "inferior" (child) process as a target
+   for debugging, in GDB.
+   Copyright 1990, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"  /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "ieee-float.h"                /* Required by REGISTER_CONVERT_TO_XXX */
+
+extern int fetch_inferior_registers();
+extern int store_inferior_registers();
+extern int child_xfer_memory();
+extern int memory_insert_breakpoint(), memory_remove_breakpoint();
+extern void terminal_init_inferior(), terminal_ours(), terminal_inferior();
+extern void terminal_ours_for_output(), child_terminal_info();
+extern void kill_inferior(), add_syms_addr_command();
+extern struct value *call_function_by_hand();
+extern void child_resume();
+extern void child_create_inferior();
+extern void child_mourn_inferior();
+extern void child_attach ();
+
+/* Forward declaration */
+extern struct target_ops child_ops;
+
+/* Wait for child to do something.  Return pid of child, or -1 in case
+   of error; store status through argument pointer STATUS.  */
+
+int
+child_wait (status)
+     int *status;
+{
+  int pid;
+
+  do {
+    pid = wait (status);
+    if (pid == -1)             /* No more children to wait for */
+      {
+       fprintf (stderr, "Child process unexpectedly missing.\n");
+       *status = 42;   /* Claim it exited with signal 42 */
+        return -1;
+      }
+  } while (pid != inferior_pid); /* Some other child died or stopped */
+  return pid;
+}
+
+
+/*
+ * child_detach()
+ * takes a program previously attached to and detaches it.
+ * The program resumes execution and will no longer stop
+ * on signals, etc.  We better not have left any breakpoints
+ * in the program or it'll die when it hits one.  For this
+ * to work, it may be necessary for the process to have been
+ * previously attached.  It *might* work if the program was
+ * started via the normal ptrace (PTRACE_TRACEME).
+ */
+
+static void
+child_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  int siggnal = 0;
+
+#ifdef ATTACH_DETACH
+  if (from_tty)
+    {
+      char *exec_file = get_exec_file (0);
+      if (exec_file == 0)
+       exec_file = "";
+      printf ("Detaching program: %s pid %d\n",
+             exec_file, inferior_pid);
+      fflush (stdout);
+    }
+  if (args)
+    siggnal = atoi (args);
+  
+  detach (siggnal);
+  inferior_pid = 0;
+  unpush_target (&child_ops);          /* Pop out of handling an inferior */
+#else
+    error ("This version of Unix does not support detaching a process.");
+#endif
+}
+
+/* Get ready to modify the registers array.  On machines which store
+   individual registers, this doesn't need to do anything.  On machines
+   which store all the registers in one fell swoop, this makes sure
+   that registers contains all the registers from the program being
+   debugged.  */
+
+void
+child_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+  CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+void
+host_convert_to_virtual (regnum, from, to)
+     int regnum;
+     char *from;
+     char *to;
+{
+  REGISTER_CONVERT_TO_VIRTUAL (regnum, from, to);
+}
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+void
+host_convert_from_virtual (regnum, from, to)
+     int regnum;
+     char *from;
+     char *to;
+{
+  REGISTER_CONVERT_TO_RAW (regnum, from, to);
+}
+
+/* Print status information about what we're accessing.  */
+
+static void
+child_files_info ()
+{
+  printf ("\tUsing the running image of %s process %d.\n",
+         attach_flag? "attached": "child", inferior_pid);
+}
+
+struct target_ops child_ops = {
+       "child", "Unix child process",
+       0, 0,  /* open, close */
+       child_attach, child_detach, 
+       child_resume,
+       child_wait,
+       fetch_inferior_registers, store_inferior_registers,
+       child_prepare_to_store,
+       host_convert_to_virtual, host_convert_from_virtual,
+       child_xfer_memory, child_files_info,
+       memory_insert_breakpoint, memory_remove_breakpoint,
+       terminal_init_inferior, terminal_inferior, 
+       terminal_ours_for_output, terminal_ours, child_terminal_info,
+       kill_inferior, 0, add_syms_addr_command,  /* load */
+       call_function_by_hand,
+       0, /* lookup_symbol */
+       child_create_inferior, child_mourn_inferior,
+       process_stratum, 0, /* next */
+       1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_inftarg ()
+{
+  add_target (&child_ops);
+}
diff --git a/gdb/kdb-start.c b/gdb/kdb-start.c
new file mode 100644 (file)
index 0000000..cbc69fd
--- /dev/null
@@ -0,0 +1,40 @@
+/* Main loop for the standalone kernel debugger.
+   Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+
+static char *args[] = {"kdb", "kdb-symbols", 0};
+
+static char *environment[] = {0};
+
+char **environ;
+
+start ()
+{
+#ifdef NAMES_HAVE_UNDERSCORE
+  INIT_STACK (_kdb_stack_beg, _kdb_stack_end);
+#else /* not NAMES_HAVE_UNDERSCORE */
+  INIT_STACK (kdb_stack_beg, kdb_stack_end);
+#endif /* not NAMES_HAVE_UNDERSCORE */
+
+  environ = environment;
+
+  main (2, args, environment);
+}
diff --git a/gdb/m68k-opcode.h b/gdb/m68k-opcode.h
new file mode 100755 (executable)
index 0000000..a0961f6
--- /dev/null
@@ -0,0 +1,1680 @@
+/* Opcode table for m68000/m68020 and m68881.
+   Copyright (C) 1989, Free Software Foundation.
+
+This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.
+
+Both GDB and GAS are free software; you can redistribute and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB and GAS are 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 GDB or GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   
+
+struct m68k_opcode
+{
+  char *name;
+  unsigned long opcode;
+  unsigned long  match;
+  char *args;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+   is the most any of them need.  The actual length of an instruction
+   is always at least 2 bytes, and is as much longer as necessary to
+   hold the operands it has.
+
+   The match component is a mask saying which bits must match
+   particular opcode in order for an instruction to be an instance
+   of that opcode.
+
+   The args component is a string containing two characters
+   for each operand of the instruction.  The first specifies
+   the kind of operand; the second, the place it is stored.  */
+
+/* Kinds of operands:
+   D  data register only.  Stored as 3 bits.
+   A  address register only.  Stored as 3 bits.
+   R  either kind of register.  Stored as 4 bits.
+   F  floating point coprocessor register only.   Stored as 3 bits.
+   O  an offset (or width): immediate data 0-31 or data register.
+      Stored as 6 bits in special format for BF... insns.
+   +  autoincrement only.  Stored as 3 bits (number of the address register).
+   -  autodecrement only.  Stored as 3 bits (number of the address register).
+   Q  quick immediate data.  Stored as 3 bits.
+      This matches an immediate operand only when value is in range 1 .. 8.
+   M  moveq immediate data.  Stored as 8 bits.
+      This matches an immediate operand only when value is in range -128..127
+   T  trap vector immediate data.  Stored as 4 bits.
+
+   k  K-factor for fmove.p instruction.   Stored as a 7-bit constant or
+      a three bit register offset, depending on the field type.
+
+   #  immediate data.  Stored in special places (b, w or l)
+      which say how many bits to store.
+   ^  immediate data for floating point instructions.   Special places
+      are offset by 2 bytes from '#'...
+   B  pc-relative address, converted to an offset
+      that is treated as immediate data.
+   d  displacement and register.  Stores the register as 3 bits
+      and stores the displacement in the entire second word.
+
+   C  the CCR.  No need to store it; this is just for filtering validity.
+   S  the SR.  No need to store, just as with CCR.
+   U  the USP.  No need to store, just as with CCR.
+
+   I  Coprocessor ID.   Not printed if 1.   The Coprocessor ID is always
+      extracted from the 'd' field of word one, which means that an extended
+      coprocessor opcode can be skipped using the 'i' place, if needed.
+
+   s  System Control register for the floating point coprocessor.
+   S  List of system control registers for floating point coprocessor.
+
+   J  Misc register for movec instruction, stored in 'j' format.
+       Possible values:
+       000     SFC     Source Function Code reg
+       001     DFC     Data Function Code reg
+       002     CACR    Cache Control Register
+       800     USP     User Stack Pointer
+       801     VBR     Vector Base reg
+       802     CAAR    Cache Address Register
+       803     MSP     Master Stack Pointer
+       804     ISP     Interrupt Stack Pointer
+
+    L  Register list of the type d0-d7/a0-a7 etc.
+       (New!  Improved!  Can also hold fp0-fp7, as well!)
+       The assembler tries to see if the registers match the insn by
+       looking at where the insn wants them stored.
+
+    l  Register list like L, but with all the bits reversed.
+       Used for going the other way. . .
+
+ They are all stored as 6 bits using an address mode and a register number;
+ they differ in which addressing modes they match.
+
+   *  all                                      (modes 0-6,7.*)
+   ~  alterable memory                         (modes 2-6,7.0,7.1)(not 0,1,7.~)
+   %  alterable                                        (modes 0-6,7.0,7.1)(not 7.~)
+   ;  data                                     (modes 0,2-6,7.*)(not 1)
+   @  data, but not immediate                  (modes 0,2-6,7.? ? ?)(not 1,7.?)  This may really be ;, the 68020 book says it is
+   !  control                                  (modes 2,5,6,7.*-)(not 0,1,3,4,7.4)
+   &  alterable control                                (modes 2,5,6,7.0,7.1)(not 0,1,7.? ? ?)
+   $  alterable data                           (modes 0,2-6,7.0,7.1)(not 1,7.~)
+   ?  alterable control, or data register      (modes 0,2,5,6,7.0,7.1)(not 1,3,4,7.~)
+   /  control, or data register                        (modes 0,2,5,6,7.0,7.1,7.2,7.3)(not 1,3,4,7.4)
+*/
+
+/* JF: for the 68851 */
+/*
+   I didn't use much imagination in choosing the 
+   following codes, so many of them aren't very
+   mnemonic. -rab
+
+   P  pmmu register
+       Possible values:
+       000     TC      Translation Control reg
+       100     CAL     Current Access Level
+       101     VAL     Validate Access Level
+       110     SCC     Stack Change Control
+       111     AC      Access Control
+
+   W  wide pmmu registers
+       Possible values:
+       001     DRP     Dma Root Pointer
+       010     SRP     Supervisor Root Pointer
+       011     CRP     Cpu Root Pointer
+
+   f   function code register
+       0       SFC
+       1       DFC
+
+   V   VAL register only
+
+   X   BADx, BACx
+       100     BAD     Breakpoint Acknowledge Data
+       101     BAC     Breakpoint Acknowledge Control
+
+   Y   PSR
+   Z   PCSR
+
+   |   memory          (modes 2-6, 7.*)
+
+*/
+
+/* Places to put an operand, for non-general operands:
+   s  source, low bits of first word.
+   d  dest, shifted 9 in first word
+   1  second word, shifted 12
+   2  second word, shifted 6
+   3  second word, shifted 0
+   4  third word, shifted 12
+   5  third word, shifted 6
+   6  third word, shifted 0
+   7  second word, shifted 7
+   8  second word, shifted 10
+   D  store in both place 1 and place 3; for divul and divsl.
+   b  second word, low byte
+   w  second word (entire)
+   l  second and third word (entire)
+   g  branch offset for bra and similar instructions.
+      The place to store depends on the magnitude of offset.
+   t  store in both place 7 and place 8; for floating point operations
+   c  branch offset for cpBcc operations.
+      The place to store is word two if bit six of word one is zero,
+      and words two and three if bit six of word one is one.
+   i  Increment by two, to skip over coprocessor extended operands.   Only
+      works with the 'I' format.
+   k  Dynamic K-factor field.   Bits 6-4 of word 2, used as a register number.
+      Also used for dynamic fmovem instruction.
+   C  floating point coprocessor constant - 7 bits.  Also used for static
+      K-factors...
+   j  Movec register #, stored in 12 low bits of second word.
+
+ Places to put operand, for general operands:
+   d  destination, shifted 6 bits in first word
+   b  source, at low bit of first word, and immediate uses one byte
+   w  source, at low bit of first word, and immediate uses two bytes
+   l  source, at low bit of first word, and immediate uses four bytes
+   s  source, at low bit of first word.
+      Used sometimes in contexts where immediate is not allowed anyway.
+   f  single precision float, low bit of 1st word, immediate uses 4 bytes
+   F  double precision float, low bit of 1st word, immediate uses 8 bytes
+   x  extended precision float, low bit of 1st word, immediate uses 12 bytes
+   p  packed float, low bit of 1st word, immediate uses 12 bytes
+*/
+
+#define one(x) ((x) << 16)
+#define two(x, y) (((x) << 16) + y)
+
+/*
+       *** DANGER WILL ROBINSON ***
+
+   The assembler requires that all instances of the same mnemonic must be
+   consecutive.  If they aren't, the assembler will bomb at runtime
+ */
+struct m68k_opcode m68k_opcodes[] =
+{
+{"abcd",       one(0140400),           one(0170770),           "DsDd"},
+{"abcd",       one(0140410),           one(0170770),           "-s-d"},
+
+               /* Add instructions */
+{"addal",      one(0150700),           one(0170700),           "*lAd"},
+{"addaw",      one(0150300),           one(0170700),           "*wAd"},
+{"addib",      one(0003000),           one(0177700),           "#b$b"},
+{"addil",      one(0003200),           one(0177700),           "#l$l"},
+{"addiw",      one(0003100),           one(0177700),           "#w$w"},
+{"addqb",      one(0050000),           one(0170700),           "Qd$b"},
+{"addql",      one(0050200),           one(0170700),           "Qd%l"},
+{"addqw",      one(0050100),           one(0170700),           "Qd%w"},
+
+{"addb",       one(0050000),           one(0170700),           "Qd$b"},        /* addq written as add */
+{"addb",       one(0003000),           one(0177700),           "#b$b"},        /* addi written as add */
+{"addb",       one(0150000),           one(0170700),           ";bDd"},        /* addb <ea>,   Dd */
+{"addb",       one(0150400),           one(0170700),           "Dd~b"},        /* addb Dd,     <ea> */
+
+{"addw",       one(0050100),           one(0170700),           "Qd%w"},        /* addq written as add */
+{"addw",       one(0003100),           one(0177700),           "#w$w"},        /* addi written as add */
+{"addw",       one(0150300),           one(0170700),           "*wAd"},        /* adda written as add */
+{"addw",       one(0150100),           one(0170700),           "*wDd"},        /* addw <ea>,   Dd */
+{"addw",       one(0150500),           one(0170700),           "Dd~w"},        /* addw Dd,     <ea> */
+
+{"addl",       one(0050200),           one(0170700),           "Qd%l"},        /* addq written as add */
+{"addl",       one(0003200),           one(0177700),           "#l$l"},        /* addi written as add */
+{"addl",       one(0150700),           one(0170700),           "*lAd"},        /* adda written as add */
+{"addl",       one(0150200),           one(0170700),           "*lDd"},        /* addl <ea>,   Dd */
+{"addl",       one(0150600),           one(0170700),           "Dd~l"},        /* addl Dd,     <ea> */
+
+{"addxb",      one(0150400),           one(0170770),           "DsDd"},
+{"addxb",      one(0150410),           one(0170770),           "-s-d"},
+{"addxl",      one(0150600),           one(0170770),           "DsDd"},
+{"addxl",      one(0150610),           one(0170770),           "-s-d"},
+{"addxw",      one(0150500),           one(0170770),           "DsDd"},
+{"addxw",      one(0150510),           one(0170770),           "-s-d"},
+
+{"andib",      one(0001000),           one(0177700),           "#b$b"},
+{"andib",      one(0001074),           one(0177777),           "#bCb"},        /* andi to ccr */
+{"andiw",      one(0001100),           one(0177700),           "#w$w"},
+{"andiw",      one(0001174),           one(0177777),           "#wSw"},        /* andi to sr */
+{"andil",      one(0001200),           one(0177700),           "#l$l"},
+
+{"andb",       one(0001000),           one(0177700),           "#b$b"},        /* andi written as or */
+{"andb",       one(0001074),           one(0177777),           "#bCb"},        /* andi to ccr */
+{"andb",       one(0140000),           one(0170700),           ";bDd"},        /* memory to register */
+{"andb",       one(0140400),           one(0170700),           "Dd~b"},        /* register to memory */
+{"andw",       one(0001100),           one(0177700),           "#w$w"},        /* andi written as or */
+{"andw",       one(0001174),           one(0177777),           "#wSw"},        /* andi to sr */
+{"andw",       one(0140100),           one(0170700),           ";wDd"},        /* memory to register */
+{"andw",       one(0140500),           one(0170700),           "Dd~w"},        /* register to memory */
+{"andl",       one(0001200),           one(0177700),           "#l$l"},        /* andi written as or */
+{"andl",       one(0140200),           one(0170700),           ";lDd"},        /* memory to register */
+{"andl",       one(0140600),           one(0170700),           "Dd~l"},        /* register to memory */
+
+{"aslb",       one(0160400),           one(0170770),           "QdDs"},
+{"aslb",       one(0160440),           one(0170770),           "DdDs"},
+{"asll",       one(0160600),           one(0170770),           "QdDs"},
+{"asll",       one(0160640),           one(0170770),           "DdDs"},
+{"aslw",       one(0160500),           one(0170770),           "QdDs"},
+{"aslw",       one(0160540),           one(0170770),           "DdDs"},
+{"aslw",       one(0160700),           one(0177700),           "~s"},  /* Shift memory */
+{"asrb",       one(0160000),           one(0170770),           "QdDs"},
+{"asrb",       one(0160040),           one(0170770),           "DdDs"},
+{"asrl",       one(0160200),           one(0170770),           "QdDs"},
+{"asrl",       one(0160240),           one(0170770),           "DdDs"},
+{"asrw",       one(0160100),           one(0170770),           "QdDs"},
+{"asrw",       one(0160140),           one(0170770),           "DdDs"},
+{"asrw",       one(0160300),           one(0177700),           "~s"},  /* Shift memory */
+
+{"bhi",                one(0061000),           one(0177400),           "Bg"},
+{"bls",                one(0061400),           one(0177400),           "Bg"},
+{"bcc",                one(0062000),           one(0177400),           "Bg"},
+{"bcs",                one(0062400),           one(0177400),           "Bg"},
+{"bne",                one(0063000),           one(0177400),           "Bg"},
+{"beq",                one(0063400),           one(0177400),           "Bg"},
+{"bvc",                one(0064000),           one(0177400),           "Bg"},
+{"bvs",                one(0064400),           one(0177400),           "Bg"},
+{"bpl",                one(0065000),           one(0177400),           "Bg"},
+{"bmi",                one(0065400),           one(0177400),           "Bg"},
+{"bge",                one(0066000),           one(0177400),           "Bg"},
+{"blt",                one(0066400),           one(0177400),           "Bg"},
+{"bgt",                one(0067000),           one(0177400),           "Bg"},
+{"ble",                one(0067400),           one(0177400),           "Bg"},
+
+{"bchg",       one(0000500),           one(0170700),           "Dd$s"},
+{"bchg",       one(0004100),           one(0177700),           "#b$s"},
+{"bclr",       one(0000600),           one(0170700),           "Dd$s"},
+{"bclr",       one(0004200),           one(0177700),           "#b$s"},
+{"bfchg",      two(0165300, 0),        two(0177700, 0170000),  "?sO2O3"},
+{"bfclr",      two(0166300, 0),        two(0177700, 0170000),  "?sO2O3"},
+{"bfexts",     two(0165700, 0),        two(0177700, 0100000),  "/sO2O3D1"},
+{"bfextu",     two(0164700, 0),        two(0177700, 0100000),  "/sO2O3D1"},
+{"bfffo",      two(0166700, 0),        two(0177700, 0100000),  "/sO2O3D1"},
+{"bfins",      two(0167700, 0),        two(0177700, 0100000),  "D1?sO2O3"},
+{"bfset",      two(0167300, 0),        two(0177700, 0170000),  "?sO2O3"},
+{"bftst",      two(0164300, 0),        two(0177700, 0170000),  "/sO2O3"},
+{"bset",       one(0000700),           one(0170700),           "Dd$s"},
+{"bset",       one(0004300),           one(0177700),           "#b$s"},
+{"btst",       one(0000400),           one(0170700),           "Dd@s"},
+{"btst",       one(0004000),           one(0177700),           "#b@s"},
+
+{"bkpt",       one(0044110),           one(0177770),           "Qs"},
+{"bra",                one(0060000),           one(0177400),           "Bg"},
+{"bras",       one(0060000),           one(0177400),           "Bw"},
+{"bsr",                one(0060400),           one(0177400),           "Bg"},
+{"bsrs",       one(0060400),           one(0177400),           "Bw"},
+
+{"callm",      one(0003300),           one(0177700),           "#b!s"},
+{"cas2l",      two(0007374, 0),        two(0177777, 0107070),  "D3D6D2D5R1R4"}, /* JF FOO this is really a 3 word ins */
+{"cas2w",      two(0006374, 0),        two(0177777, 0107070),  "D3D6D2D5R1R4"}, /* JF ditto */
+{"casb",       two(0005300, 0),        two(0177700, 0177070),  "D3D2~s"},
+{"casl",       two(0007300, 0),        two(0177700, 0177070),  "D3D2~s"},
+{"casw",       two(0006300, 0),        two(0177700, 0177070),  "D3D2~s"},
+
+/*  {"chk",    one(0040600),           one(0170700),           ";wDd"}, JF FOO this looks wrong */
+{"chk2b",      two(0000300, 0004000),  two(0177700, 07777),    "!sR1"},
+{"chk2l",      two(0002300, 0004000),  two(0177700, 07777),    "!sR1"},
+{"chk2w",      two(0001300, 0004000),  two(0177700, 07777),    "!sR1"},
+{"chkl",       one(0040400),           one(0170700),           ";lDd"},
+{"chkw",       one(0040600),           one(0170700),           ";wDd"},
+{"clrb",       one(0041000),           one(0177700),           "$s"},
+{"clrl",       one(0041200),           one(0177700),           "$s"},
+{"clrw",       one(0041100),           one(0177700),           "$s"},
+
+{"cmp2b",      two(0000300, 0),        two(0177700, 07777),    "!sR1"},
+{"cmp2l",      two(0002300, 0),        two(0177700, 07777),    "!sR1"},
+{"cmp2w",      two(0001300, 0),        two(0177700, 07777),    "!sR1"},
+{"cmpal",      one(0130700),           one(0170700),           "*lAd"},
+{"cmpaw",      one(0130300),           one(0170700),           "*wAd"},
+{"cmpib",      one(0006000),           one(0177700),           "#b;b"},
+{"cmpil",      one(0006200),           one(0177700),           "#l;l"},
+{"cmpiw",      one(0006100),           one(0177700),           "#w;w"},
+{"cmpb",       one(0006000),           one(0177700),           "#b;b"},        /* cmpi written as cmp */
+{"cmpb",       one(0130000),           one(0170700),           ";bDd"},
+{"cmpw",       one(0006100),           one(0177700),           "#w;w"},
+{"cmpw",       one(0130100),           one(0170700),           "*wDd"},
+{"cmpw",       one(0130300),           one(0170700),           "*wAd"},        /* cmpa written as cmp */
+{"cmpl",       one(0006200),           one(0177700),           "#l;l"},
+{"cmpl",       one(0130200),           one(0170700),           "*lDd"},
+{"cmpl",       one(0130700),           one(0170700),           "*lAd"},
+{"cmpmb",      one(0130410),           one(0170770),           "+s+d"},
+{"cmpml",      one(0130610),           one(0170770),           "+s+d"},
+{"cmpmw",      one(0130510),           one(0170770),           "+s+d"},
+
+{"dbcc",       one(0052310),           one(0177770),           "DsBw"},
+{"dbcs",       one(0052710),           one(0177770),           "DsBw"},
+{"dbeq",       one(0053710),           one(0177770),           "DsBw"},
+{"dbf",                one(0050710),           one(0177770),           "DsBw"},
+{"dbge",       one(0056310),           one(0177770),           "DsBw"},
+{"dbgt",       one(0057310),           one(0177770),           "DsBw"},
+{"dbhi",       one(0051310),           one(0177770),           "DsBw"},
+{"dble",       one(0057710),           one(0177770),           "DsBw"},
+{"dbls",       one(0051710),           one(0177770),           "DsBw"},
+{"dblt",       one(0056710),           one(0177770),           "DsBw"},
+{"dbmi",       one(0055710),           one(0177770),           "DsBw"},
+{"dbne",       one(0053310),           one(0177770),           "DsBw"},
+{"dbpl",       one(0055310),           one(0177770),           "DsBw"},
+{"dbra",       one(0050710),           one(0177770),           "DsBw"},
+{"dbt",                one(0050310),           one(0177770),           "DsBw"},
+{"dbvc",       one(0054310),           one(0177770),           "DsBw"},
+{"dbvs",       one(0054710),           one(0177770),           "DsBw"},
+
+{"divsl",      two(0046100, 0006000),  two(0177700, 0107770),  ";lD3D1"},
+{"divsl",      two(0046100, 0004000),  two(0177700, 0107770),  ";lDD"},
+{"divsll",     two(0046100, 0004000),  two(0177700, 0107770),  ";lD3D1"},
+{"divsw",      one(0100700),           one(0170700),           ";wDd"},
+{"divs",       one(0100700),           one(0170700),           ";wDd"},
+{"divul",      two(0046100, 0002000),  two(0177700, 0107770),  ";lD3D1"},
+{"divul",      two(0046100, 0000000),  two(0177700, 0107770),  ";lDD"},
+{"divull",     two(0046100, 0000000),  two(0177700, 0107770),  ";lD3D1"},
+{"divuw",      one(0100300),           one(0170700),           ";wDd"},
+{"divu",       one(0100300),           one(0170700),           ";wDd"},
+{"eorb",       one(0005000),           one(0177700),           "#b$s"},        /* eori written as or */
+{"eorb",       one(0005074),           one(0177777),           "#bCs"},        /* eori to ccr */
+{"eorb",       one(0130400),           one(0170700),           "Dd$s"},        /* register to memory */
+{"eorib",      one(0005000),           one(0177700),           "#b$s"},
+{"eorib",      one(0005074),           one(0177777),           "#bCs"},        /* eori to ccr */
+{"eoril",      one(0005200),           one(0177700),           "#l$s"},
+{"eoriw",      one(0005100),           one(0177700),           "#w$s"},
+{"eoriw",      one(0005174),           one(0177777),           "#wSs"},        /* eori to sr */
+{"eorl",       one(0005200),           one(0177700),           "#l$s"},
+{"eorl",       one(0130600),           one(0170700),           "Dd$s"},
+{"eorw",       one(0005100),           one(0177700),           "#w$s"},
+{"eorw",       one(0005174),           one(0177777),           "#wSs"},        /* eori to sr */
+{"eorw",       one(0130500),           one(0170700),           "Dd$s"},
+
+{"exg",                one(0140500),           one(0170770),           "DdDs"},
+{"exg",                one(0140510),           one(0170770),           "AdAs"},
+{"exg",                one(0140610),           one(0170770),           "DdAs"},
+{"exg",                one(0140610),           one(0170770),           "AsDd"},
+
+{"extw",       one(0044200),           one(0177770),           "Ds"},
+{"extl",       one(0044300),           one(0177770),           "Ds"},
+{"extbl",      one(0044700),           one(0177770),           "Ds"},
+{"extb.l",     one(0044700),           one(0177770),           "Ds"},  /* Not sure we should support this one*/
+
+{"illegal",    one(0045374),           one(0177777),           ""},
+{"jmp",                one(0047300),           one(0177700),           "!s"},
+{"jsr",                one(0047200),           one(0177700),           "!s"},
+{"lea",                one(0040700),           one(0170700),           "!sAd"},
+{"linkw",      one(0047120),           one(0177770),           "As#w"},
+{"linkl",      one(0044010),           one(0177770),           "As#l"},
+{"link",       one(0047120),           one(0177770),           "As#w"},
+{"link",       one(0044010),           one(0177770),           "As#l"},
+
+{"lslb",       one(0160410),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lslb",       one(0160450),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+{"lslw",       one(0160510),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lslw",       one(0160550),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+{"lslw",       one(0161700),           one(0177700),           "~s"},  /* Shift memory */
+{"lsll",       one(0160610),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lsll",       one(0160650),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+
+{"lsrb",       one(0160010),           one(0170770),           "QdDs"} /* lsrb #Q,     Ds */,
+{"lsrb",       one(0160050),           one(0170770),           "DdDs"},        /* lsrb Dd,     Ds */
+{"lsrl",       one(0160210),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lsrl",       one(0160250),           one(0170770),           "DdDs"},        /* lsrb #Q,     Ds */
+{"lsrw",       one(0160110),           one(0170770),           "QdDs"},        /* lsrb #Q,     Ds */
+{"lsrw",       one(0160150),           one(0170770),           "DdDs"},        /* lsrb #Q,     Ds */
+{"lsrw",       one(0161300),           one(0177700),           "~s"},  /* Shift memory */
+
+{"moveal",     one(0020100),           one(0170700),           "*lAd"},
+{"moveaw",     one(0030100),           one(0170700),           "*wAd"},
+{"moveb",      one(0010000),           one(0170000),           ";b$d"},        /* move */
+{"movel",      one(0070000),           one(0170400),           "MsDd"},        /* moveq written as move */
+{"movel",      one(0020000),           one(0170000),           "*l$d"},
+{"movel",      one(0020100),           one(0170700),           "*lAd"},
+{"movel",      one(0047140),           one(0177770),           "AsUd"},        /* move to USP */
+{"movel",      one(0047150),           one(0177770),           "UdAs"},        /* move from USP */
+
+{"movec",      one(0047173),           one(0177777),           "R1Jj"},
+{"movec",      one(0047173),           one(0177777),           "R1#j"},
+{"movec",      one(0047172),           one(0177777),           "JjR1"},
+{"movec",      one(0047172),           one(0177777),           "#jR1"},
+
+/* JF added these next four for the assembler */
+{"moveml",     one(0044300),           one(0177700),           "Lw&s"},        /* movem reg to mem. */
+{"moveml",     one(0044340),           one(0177770),           "lw-s"},        /* movem reg to autodecrement. */
+{"moveml",     one(0046300),           one(0177700),           "!sLw"},        /* movem mem to reg. */
+{"moveml",     one(0046330),           one(0177770),           "+sLw"},        /* movem autoinc to reg. */
+
+{"moveml",     one(0044300),           one(0177700),           "#w&s"},        /* movem reg to mem. */
+{"moveml",     one(0044340),           one(0177770),           "#w-s"},        /* movem reg to autodecrement. */
+{"moveml",     one(0046300),           one(0177700),           "!s#w"},        /* movem mem to reg. */
+{"moveml",     one(0046330),           one(0177770),           "+s#w"},        /* movem autoinc to reg. */
+
+/* JF added these next four for the assembler */
+{"movemw",     one(0044200),           one(0177700),           "Lw&s"},        /* movem reg to mem. */
+{"movemw",     one(0044240),           one(0177770),           "lw-s"},        /* movem reg to autodecrement. */
+{"movemw",     one(0046200),           one(0177700),           "!sLw"},        /* movem mem to reg. */
+{"movemw",     one(0046230),           one(0177770),           "+sLw"},        /* movem autoinc to reg. */
+
+{"movemw",     one(0044200),           one(0177700),           "#w&s"},        /* movem reg to mem. */
+{"movemw",     one(0044240),           one(0177770),           "#w-s"},        /* movem reg to autodecrement. */
+{"movemw",     one(0046200),           one(0177700),           "!s#w"},        /* movem mem to reg. */
+{"movemw",     one(0046230),           one(0177770),           "+s#w"},        /* movem autoinc to reg. */
+
+{"movepl",     one(0000510),           one(0170770),           "dsDd"},        /* memory to register */
+{"movepl",     one(0000710),           one(0170770),           "Ddds"},        /* register to memory */
+{"movepw",     one(0000410),           one(0170770),           "dsDd"},        /* memory to register */
+{"movepw",     one(0000610),           one(0170770),           "Ddds"},        /* register to memory */
+{"moveq",      one(0070000),           one(0170400),           "MsDd"},
+{"movew",      one(0030000),           one(0170000),           "*w$d"},
+{"movew",      one(0030100),           one(0170700),           "*wAd"},        /* movea,       written as move */
+{"movew",      one(0040300),           one(0177700),           "Ss$s"},        /* Move from sr */
+{"movew",      one(0041300),           one(0177700),           "Cs$s"},        /* Move from ccr */
+{"movew",      one(0042300),           one(0177700),           ";wCd"},        /* move to ccr */
+{"movew",      one(0043300),           one(0177700),           ";wSd"},        /* move to sr */
+
+{"movesb",     two(0007000, 0),        two(0177700, 07777),    "~sR1"},         /* moves from memory */
+{"movesb",     two(0007000, 04000),    two(0177700, 07777),    "R1~s"},         /* moves to memory */
+{"movesl",     two(0007200, 0),        two(0177700, 07777),    "~sR1"},         /* moves from memory */
+{"movesl",     two(0007200, 04000),    two(0177700, 07777),    "R1~s"},         /* moves to memory */
+{"movesw",     two(0007100, 0),        two(0177700, 07777),    "~sR1"},         /* moves from memory */
+{"movesw",     two(0007100, 04000),    two(0177700, 07777),    "R1~s"},         /* moves to memory */
+
+{"mulsl",      two(0046000, 004000),   two(0177700, 0107770),  ";lD1"},
+{"mulsl",      two(0046000, 006000),   two(0177700, 0107770),  ";lD3D1"},
+{"mulsw",      one(0140700),           one(0170700),           ";wDd"},
+{"muls",       one(0140700),           one(0170700),           ";wDd"},
+{"mulul",      two(0046000, 000000),   two(0177700, 0107770),  ";lD1"},
+{"mulul",      two(0046000, 002000),   two(0177700, 0107770),  ";lD3D1"},
+{"muluw",      one(0140300),           one(0170700),           ";wDd"},
+{"mulu",       one(0140300),           one(0170700),           ";wDd"},
+{"nbcd",       one(0044000),           one(0177700),           "$s"},
+{"negb",       one(0042000),           one(0177700),           "$s"},
+{"negl",       one(0042200),           one(0177700),           "$s"},
+{"negw",       one(0042100),           one(0177700),           "$s"},
+{"negxb",      one(0040000),           one(0177700),           "$s"},
+{"negxl",      one(0040200),           one(0177700),           "$s"},
+{"negxw",      one(0040100),           one(0177700),           "$s"},
+{"nop",                one(0047161),           one(0177777),           ""},
+{"notb",       one(0043000),           one(0177700),           "$s"},
+{"notl",       one(0043200),           one(0177700),           "$s"},
+{"notw",       one(0043100),           one(0177700),           "$s"},
+
+{"orb",                one(0000000),           one(0177700),           "#b$s"},        /* ori written as or */
+{"orb",                one(0000074),           one(0177777),           "#bCs"},        /* ori to ccr */
+{"orb",                one(0100000),           one(0170700),           ";bDd"},        /* memory to register */
+{"orb",                one(0100400),           one(0170700),           "Dd~s"},        /* register to memory */
+{"orib",       one(0000000),           one(0177700),           "#b$s"},
+{"orib",       one(0000074),           one(0177777),           "#bCs"},        /* ori to ccr */
+{"oril",       one(0000200),           one(0177700),           "#l$s"},
+{"oriw",       one(0000100),           one(0177700),           "#w$s"},
+{"oriw",       one(0000174),           one(0177777),           "#wSs"},        /* ori to sr */
+{"orl",                one(0000200),           one(0177700),           "#l$s"},
+{"orl",                one(0100200),           one(0170700),           ";lDd"},        /* memory to register */
+{"orl",                one(0100600),           one(0170700),           "Dd~s"},        /* register to memory */
+{"orw",                one(0000100),           one(0177700),           "#w$s"},
+{"orw",                one(0000174),           one(0177777),           "#wSs"},        /* ori to sr */
+{"orw",                one(0100100),           one(0170700),           ";wDd"},        /* memory to register */
+{"orw",                one(0100500),           one(0170700),           "Dd~s"},        /* register to memory */
+
+{"pack",       one(0100500),           one(0170770),           "DsDd#w"},      /* pack Ds,     Dd,     #w */
+{"pack",       one(0100510),           one(0170770),           "-s-d#w"},      /* pack -(As),  -(Ad),  #w */
+{"pea",                one(0044100),           one(0177700),           "!s"},
+{"reset",      one(0047160),           one(0177777),           ""},
+
+{"rolb",       one(0160430),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rolb",       one(0160470),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"roll",       one(0160630),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"roll",       one(0160670),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rolw",       one(0160530),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rolw",       one(0160570),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rolw",       one(0163700),           one(0177700),           "~s"},  /* Rotate memory */
+{"rorb",       one(0160030),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rorb",       one(0160070),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rorl",       one(0160230),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rorl",       one(0160270),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rorw",       one(0160130),           one(0170770),           "QdDs"},        /* rorb #Q,     Ds */
+{"rorw",       one(0160170),           one(0170770),           "DdDs"},        /* rorb Dd,     Ds */
+{"rorw",       one(0163300),           one(0177700),           "~s"},  /* Rotate memory */
+
+{"roxlb",      one(0160420),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxlb",      one(0160460),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxll",      one(0160620),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxll",      one(0160660),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxlw",      one(0160520),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxlw",      one(0160560),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxlw",      one(0162700),           one(0177700),           "~s"},  /* Rotate memory */
+{"roxrb",      one(0160020),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxrb",      one(0160060),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxrl",      one(0160220),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxrl",      one(0160260),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxrw",      one(0160120),           one(0170770),           "QdDs"},        /* roxrb #Q,    Ds */
+{"roxrw",      one(0160160),           one(0170770),           "DdDs"},        /* roxrb Dd,    Ds */
+{"roxrw",      one(0162300),           one(0177700),           "~s"},  /* Rotate memory */
+
+{"rtd",                one(0047164),           one(0177777),           "#w"},
+{"rte",                one(0047163),           one(0177777),           ""},
+{"rtm",                one(0003300),           one(0177760),           "Rs"},
+{"rtr",                one(0047167),           one(0177777),           ""},
+{"rts",                one(0047165),           one(0177777),           ""},
+
+{"scc",                one(0052300),           one(0177700),           "$s"},
+{"scs",                one(0052700),           one(0177700),           "$s"},
+{"seq",                one(0053700),           one(0177700),           "$s"},
+{"sf",         one(0050700),           one(0177700),           "$s"},
+{"sge",                one(0056300),           one(0177700),           "$s"},
+{"sgt",                one(0057300),           one(0177700),           "$s"},
+{"shi",                one(0051300),           one(0177700),           "$s"},
+{"sle",                one(0057700),           one(0177700),           "$s"},
+{"sls",                one(0051700),           one(0177700),           "$s"},
+{"slt",                one(0056700),           one(0177700),           "$s"},
+{"smi",                one(0055700),           one(0177700),           "$s"},
+{"sne",                one(0053300),           one(0177700),           "$s"},
+{"spl",                one(0055300),           one(0177700),           "$s"},
+{"st",         one(0050300),           one(0177700),           "$s"},
+{"svc",                one(0054300),           one(0177700),           "$s"},
+{"svs",                one(0054700),           one(0177700),           "$s"},
+
+{"sbcd",       one(0100400),           one(0170770),           "DsDd"},
+{"sbcd",       one(0100410),           one(0170770),           "-s-d"},
+{"stop",       one(0047162),           one(0177777),           "#w"},
+
+{"subal",      one(0110700),           one(0170700),           "*lAd"},
+{"subaw",      one(0110300),           one(0170700),           "*wAd"},
+{"subb",       one(0050400),           one(0170700),           "Qd%s"},        /* subq written as sub */
+{"subb",       one(0002000),           one(0177700),           "#b$s"},        /* subi written as sub */
+{"subb",       one(0110000),           one(0170700),           ";bDd"},        /* subb ? ?,    Dd */
+{"subb",       one(0110400),           one(0170700),           "Dd~s"},        /* subb Dd,     ? ? */
+{"subib",      one(0002000),           one(0177700),           "#b$s"},
+{"subil",      one(0002200),           one(0177700),           "#l$s"},
+{"subiw",      one(0002100),           one(0177700),           "#w$s"},
+{"subl",       one(0050600),           one(0170700),           "Qd%s"},
+{"subl",       one(0002200),           one(0177700),           "#l$s"},
+{"subl",       one(0110700),           one(0170700),           "*lAd"},
+{"subl",       one(0110200),           one(0170700),           "*lDd"},
+{"subl",       one(0110600),           one(0170700),           "Dd~s"},
+{"subqb",      one(0050400),           one(0170700),           "Qd%s"},
+{"subql",      one(0050600),           one(0170700),           "Qd%s"},
+{"subqw",      one(0050500),           one(0170700),           "Qd%s"},
+{"subw",       one(0050500),           one(0170700),           "Qd%s"},
+{"subw",       one(0002100),           one(0177700),           "#w$s"},
+{"subw",       one(0110100),           one(0170700),           "*wDd"},
+{"subw",       one(0110300),           one(0170700),           "*wAd"},        /* suba written as sub */
+{"subw",       one(0110500),           one(0170700),           "Dd~s"},
+{"subxb",      one(0110400),           one(0170770),           "DsDd"},        /* subxb Ds,    Dd */
+{"subxb",      one(0110410),           one(0170770),           "-s-d"},        /* subxb -(As), -(Ad) */
+{"subxl",      one(0110600),           one(0170770),           "DsDd"},
+{"subxl",      one(0110610),           one(0170770),           "-s-d"},
+{"subxw",      one(0110500),           one(0170770),           "DsDd"},
+{"subxw",      one(0110510),           one(0170770),           "-s-d"},
+
+{"swap",       one(0044100),           one(0177770),           "Ds"},
+       
+{"tas",                one(0045300),           one(0177700),           "$s"},
+{"trap",       one(0047100),           one(0177760),           "Ts"},
+
+{"trapcc",     one(0052374),           one(0177777),           ""},
+{"trapcs",     one(0052774),           one(0177777),           ""},
+{"trapeq",     one(0053774),           one(0177777),           ""},
+{"trapf",      one(0050774),           one(0177777),           ""},
+{"trapge",     one(0056374),           one(0177777),           ""},
+{"trapgt",     one(0057374),           one(0177777),           ""},
+{"traphi",     one(0051374),           one(0177777),           ""},
+{"traple",     one(0057774),           one(0177777),           ""},
+{"trapls",     one(0051774),           one(0177777),           ""},
+{"traplt",     one(0056774),           one(0177777),           ""},
+{"trapmi",     one(0055774),           one(0177777),           ""},
+{"trapne",     one(0053374),           one(0177777),           ""},
+{"trappl",     one(0055374),           one(0177777),           ""},
+{"trapt",      one(0050374),           one(0177777),           ""},
+{"trapvc",     one(0054374),           one(0177777),           ""},
+{"trapvs",     one(0054774),           one(0177777),           ""},
+
+{"trapcc.w",   one(0052372),           one(0177777),           ""},
+{"trapcs.w",   one(0052772),           one(0177777),           ""},
+{"trapeq.w",   one(0053772),           one(0177777),           ""},
+{"trapf.w",    one(0050772),           one(0177777),           ""},
+{"trapge.w",   one(0056372),           one(0177777),           ""},
+{"trapgt.w",   one(0057372),           one(0177777),           ""},
+{"traphi.w",   one(0051372),           one(0177777),           ""},
+{"traple.w",   one(0057772),           one(0177777),           ""},
+{"trapls.w",   one(0051772),           one(0177777),           ""},
+{"traplt.w",   one(0056772),           one(0177777),           ""},
+{"trapmi.w",   one(0055772),           one(0177777),           ""},
+{"trapne.w",   one(0053372),           one(0177777),           ""},
+{"trappl.w",   one(0055372),           one(0177777),           ""},
+{"trapt.w",    one(0050372),           one(0177777),           ""},
+{"trapvc.w",   one(0054372),           one(0177777),           ""},
+{"trapvs.w",   one(0054772),           one(0177777),           ""},
+
+{"trapcc.l",   one(0052373),           one(0177777),           ""},
+{"trapcs.l",   one(0052773),           one(0177777),           ""},
+{"trapeq.l",   one(0053773),           one(0177777),           ""},
+{"trapf.l",    one(0050773),           one(0177777),           ""},
+{"trapge.l",   one(0056373),           one(0177777),           ""},
+{"trapgt.l",   one(0057373),           one(0177777),           ""},
+{"traphi.l",   one(0051373),           one(0177777),           ""},
+{"traple.l",   one(0057773),           one(0177777),           ""},
+{"trapls.l",   one(0051773),           one(0177777),           ""},
+{"traplt.l",   one(0056773),           one(0177777),           ""},
+{"trapmi.l",   one(0055773),           one(0177777),           ""},
+{"trapne.l",   one(0053373),           one(0177777),           ""},
+{"trappl.l",   one(0055373),           one(0177777),           ""},
+{"trapt.l",    one(0050373),           one(0177777),           ""},
+{"trapvc.l",   one(0054373),           one(0177777),           ""},
+{"trapvs.l",   one(0054773),           one(0177777),           ""},
+
+{"trapv",      one(0047166),           one(0177777),           ""},
+
+{"tstb",       one(0045000),           one(0177700),           ";b"},
+{"tstw",       one(0045100),           one(0177700),           "*w"},
+{"tstl",       one(0045200),           one(0177700),           "*l"},
+
+{"unlk",       one(0047130),           one(0177770),           "As"},
+{"unpk",       one(0100600),           one(0170770),           "DsDd#w"},
+{"unpk",       one(0100610),           one(0170770),           "-s-d#w"},
+       /* JF floating pt stuff moved down here */
+
+{"fabsb",      two(0xF000, 0x5818),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fabsd",      two(0xF000, 0x5418),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fabsl",      two(0xF000, 0x4018),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fabsp",      two(0xF000, 0x4C18),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fabss",      two(0xF000, 0x4418),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fabsw",      two(0xF000, 0x5018),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fabsx",      two(0xF000, 0x0018),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fabsx",      two(0xF000, 0x4818),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fabsx",      two(0xF000, 0x0018),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"facosb",     two(0xF000, 0x581C),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"facosd",     two(0xF000, 0x541C),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"facosl",     two(0xF000, 0x401C),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"facosp",     two(0xF000, 0x4C1C),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"facoss",     two(0xF000, 0x441C),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"facosw",     two(0xF000, 0x501C),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"facosx",     two(0xF000, 0x001C),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"facosx",     two(0xF000, 0x481C),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"facosx",     two(0xF000, 0x001C),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"faddb",      two(0xF000, 0x5822),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"faddd",      two(0xF000, 0x5422),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"faddl",      two(0xF000, 0x4022),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"faddp",      two(0xF000, 0x4C22),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fadds",      two(0xF000, 0x4422),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"faddw",      two(0xF000, 0x5022),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"faddx",      two(0xF000, 0x0022),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"faddx",      two(0xF000, 0x4822),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+/* {"faddx",   two(0xF000, 0x0022),    two(0xF1C0, 0xE07F),    "IiFt"}, JF removed */
+
+{"fasinb",     two(0xF000, 0x580C),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fasind",     two(0xF000, 0x540C),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fasinl",     two(0xF000, 0x400C),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fasinp",     two(0xF000, 0x4C0C),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fasins",     two(0xF000, 0x440C),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fasinw",     two(0xF000, 0x500C),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fasinx",     two(0xF000, 0x000C),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fasinx",     two(0xF000, 0x480C),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fasinx",     two(0xF000, 0x000C),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fatanb",     two(0xF000, 0x580A),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fatand",     two(0xF000, 0x540A),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fatanl",     two(0xF000, 0x400A),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fatanp",     two(0xF000, 0x4C0A),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fatans",     two(0xF000, 0x440A),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fatanw",     two(0xF000, 0x500A),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fatanx",     two(0xF000, 0x000A),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fatanx",     two(0xF000, 0x480A),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fatanx",     two(0xF000, 0x000A),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fatanhb",    two(0xF000, 0x580D),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fatanhd",    two(0xF000, 0x540D),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fatanhl",    two(0xF000, 0x400D),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fatanhp",    two(0xF000, 0x4C0D),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fatanhs",    two(0xF000, 0x440D),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fatanhw",    two(0xF000, 0x500D),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fatanhx",    two(0xF000, 0x000D),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fatanhx",    two(0xF000, 0x480D),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fatanhx",    two(0xF000, 0x000D),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fbeq",       one(0xF081),            one(0xF1BF),            "IdBc"},
+{"fbf",                one(0xF080),            one(0xF1BF),            "IdBc"},
+{"fbge",       one(0xF093),            one(0xF1BF),            "IdBc"},
+{"fbgl",       one(0xF096),            one(0xF1BF),            "IdBc"},
+{"fbgle",      one(0xF097),            one(0xF1BF),            "IdBc"},
+{"fbgt",       one(0xF092),            one(0xF1BF),            "IdBc"},
+{"fble",       one(0xF095),            one(0xF1BF),            "IdBc"},
+{"fblt",       one(0xF094),            one(0xF1BF),            "IdBc"},
+{"fbne",       one(0xF08E),            one(0xF1BF),            "IdBc"},
+{"fbnge",      one(0xF09C),            one(0xF1BF),            "IdBc"},
+{"fbngl",      one(0xF099),            one(0xF1BF),            "IdBc"},
+{"fbngle",     one(0xF098),            one(0xF1BF),            "IdBc"},
+{"fbngt",      one(0xF09D),            one(0xF1BF),            "IdBc"},
+{"fbnle",      one(0xF09A),            one(0xF1BF),            "IdBc"},
+{"fbnlt",      one(0xF09B),            one(0xF1BF),            "IdBc"},
+{"fboge",      one(0xF083),            one(0xF1BF),            "IdBc"},
+{"fbogl",      one(0xF086),            one(0xF1BF),            "IdBc"},
+{"fbogt",      one(0xF082),            one(0xF1BF),            "IdBc"},
+{"fbole",      one(0xF085),            one(0xF1BF),            "IdBc"},
+{"fbolt",      one(0xF084),            one(0xF1BF),            "IdBc"},
+{"fbor",       one(0xF087),            one(0xF1BF),            "IdBc"},
+{"fbseq",      one(0xF091),            one(0xF1BF),            "IdBc"},
+{"fbsf",       one(0xF090),            one(0xF1BF),            "IdBc"},
+{"fbsne",      one(0xF09E),            one(0xF1BF),            "IdBc"},
+{"fbst",       one(0xF09F),            one(0xF1BF),            "IdBc"},
+{"fbt",                one(0xF08F),            one(0xF1BF),            "IdBc"},
+{"fbueq",      one(0xF089),            one(0xF1BF),            "IdBc"},
+{"fbuge",      one(0xF08B),            one(0xF1BF),            "IdBc"},
+{"fbugt",      one(0xF08A),            one(0xF1BF),            "IdBc"},
+{"fbule",      one(0xF08D),            one(0xF1BF),            "IdBc"},
+{"fbult",      one(0xF08C),            one(0xF1BF),            "IdBc"},
+{"fbun",       one(0xF088),            one(0xF1BF),            "IdBc"},
+
+{"fcmpb",      two(0xF000, 0x5838),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fcmpd",      two(0xF000, 0x5438),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fcmpl",      two(0xF000, 0x4038),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fcmpp",      two(0xF000, 0x4C38),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fcmps",      two(0xF000, 0x4438),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fcmpw",      two(0xF000, 0x5038),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fcmpx",      two(0xF000, 0x0038),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fcmpx",      two(0xF000, 0x4838),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+/* {"fcmpx",   two(0xF000, 0x0038),    two(0xF1C0, 0xE07F),    "IiFt"}, JF removed */
+
+{"fcosb",      two(0xF000, 0x581D),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fcosd",      two(0xF000, 0x541D),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fcosl",      two(0xF000, 0x401D),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fcosp",      two(0xF000, 0x4C1D),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fcoss",      two(0xF000, 0x441D),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fcosw",      two(0xF000, 0x501D),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fcosx",      two(0xF000, 0x001D),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fcosx",      two(0xF000, 0x481D),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fcosx",      two(0xF000, 0x001D),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fcoshb",     two(0xF000, 0x5819),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fcoshd",     two(0xF000, 0x5419),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fcoshl",     two(0xF000, 0x4019),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fcoshp",     two(0xF000, 0x4C19),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fcoshs",     two(0xF000, 0x4419),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fcoshw",     two(0xF000, 0x5019),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fcoshx",     two(0xF000, 0x0019),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fcoshx",     two(0xF000, 0x4819),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fcoshx",     two(0xF000, 0x0019),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fdbeq",      two(0xF048, 0x0001),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbf",       two(0xF048, 0x0000),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbge",      two(0xF048, 0x0013),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbgl",      two(0xF048, 0x0016),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbgle",     two(0xF048, 0x0017),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbgt",      two(0xF048, 0x0012),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdble",      two(0xF048, 0x0015),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdblt",      two(0xF048, 0x0014),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbne",      two(0xF048, 0x000E),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbnge",     two(0xF048, 0x001C),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbngl",     two(0xF048, 0x0019),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbngle",    two(0xF048, 0x0018),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbngt",     two(0xF048, 0x001D),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbnle",     two(0xF048, 0x001A),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbnlt",     two(0xF048, 0x001B),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdboge",     two(0xF048, 0x0003),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbogl",     two(0xF048, 0x0006),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbogt",     two(0xF048, 0x0002),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbole",     two(0xF048, 0x0005),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbolt",     two(0xF048, 0x0004),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbor",      two(0xF048, 0x0007),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbseq",     two(0xF048, 0x0011),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbsf",      two(0xF048, 0x0010),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbsne",     two(0xF048, 0x001E),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbst",      two(0xF048, 0x001F),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbt",       two(0xF048, 0x000F),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbueq",     two(0xF048, 0x0009),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbuge",     two(0xF048, 0x000B),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbugt",     two(0xF048, 0x000A),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbule",     two(0xF048, 0x000D),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbult",     two(0xF048, 0x000C),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+{"fdbun",      two(0xF048, 0x0008),    two(0xF1F8, 0xFFFF),    "IiDsBw"},
+
+{"fdivb",      two(0xF000, 0x5820),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fdivd",      two(0xF000, 0x5420),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fdivl",      two(0xF000, 0x4020),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fdivp",      two(0xF000, 0x4C20),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fdivs",      two(0xF000, 0x4420),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fdivw",      two(0xF000, 0x5020),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fdivx",      two(0xF000, 0x0020),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fdivx",      two(0xF000, 0x4820),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+/* {"fdivx",   two(0xF000, 0x0020),    two(0xF1C0, 0xE07F),    "IiFt"}, JF */
+
+{"fetoxb",     two(0xF000, 0x5810),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fetoxd",     two(0xF000, 0x5410),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fetoxl",     two(0xF000, 0x4010),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fetoxp",     two(0xF000, 0x4C10),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fetoxs",     two(0xF000, 0x4410),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fetoxw",     two(0xF000, 0x5010),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fetoxx",     two(0xF000, 0x0010),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fetoxx",     two(0xF000, 0x4810),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fetoxx",     two(0xF000, 0x0010),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fetoxm1b",   two(0xF000, 0x5808),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fetoxm1d",   two(0xF000, 0x5408),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fetoxm1l",   two(0xF000, 0x4008),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fetoxm1p",   two(0xF000, 0x4C08),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fetoxm1s",   two(0xF000, 0x4408),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fetoxm1w",   two(0xF000, 0x5008),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fetoxm1x",   two(0xF000, 0x0008),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fetoxm1x",   two(0xF000, 0x4808),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fetoxm1x",   two(0xF000, 0x0008),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fgetexpb",   two(0xF000, 0x581E),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fgetexpd",   two(0xF000, 0x541E),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fgetexpl",   two(0xF000, 0x401E),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fgetexpp",   two(0xF000, 0x4C1E),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fgetexps",   two(0xF000, 0x441E),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fgetexpw",   two(0xF000, 0x501E),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fgetexpx",   two(0xF000, 0x001E),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fgetexpx",   two(0xF000, 0x481E),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fgetexpx",   two(0xF000, 0x001E),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fgetmanb",   two(0xF000, 0x581F),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fgetmand",   two(0xF000, 0x541F),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fgetmanl",   two(0xF000, 0x401F),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fgetmanp",   two(0xF000, 0x4C1F),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fgetmans",   two(0xF000, 0x441F),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fgetmanw",   two(0xF000, 0x501F),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fgetmanx",   two(0xF000, 0x001F),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fgetmanx",   two(0xF000, 0x481F),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fgetmanx",   two(0xF000, 0x001F),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fintb",      two(0xF000, 0x5801),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fintd",      two(0xF000, 0x5401),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fintl",      two(0xF000, 0x4001),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fintp",      two(0xF000, 0x4C01),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fints",      two(0xF000, 0x4401),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fintw",      two(0xF000, 0x5001),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fintx",      two(0xF000, 0x0001),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fintx",      two(0xF000, 0x4801),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fintx",      two(0xF000, 0x0001),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fintrzb",    two(0xF000, 0x5803),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fintrzd",    two(0xF000, 0x5403),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fintrzl",    two(0xF000, 0x4003),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fintrzp",    two(0xF000, 0x4C03),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fintrzs",    two(0xF000, 0x4403),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fintrzw",    two(0xF000, 0x5003),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fintrzx",    two(0xF000, 0x0003),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fintrzx",    two(0xF000, 0x4803),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fintrzx",    two(0xF000, 0x0003),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flog10b",    two(0xF000, 0x5815),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flog10d",    two(0xF000, 0x5415),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flog10l",    two(0xF000, 0x4015),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flog10p",    two(0xF000, 0x4C15),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flog10s",    two(0xF000, 0x4415),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flog10w",    two(0xF000, 0x5015),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flog10x",    two(0xF000, 0x0015),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flog10x",    two(0xF000, 0x4815),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flog10x",    two(0xF000, 0x0015),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flog2b",     two(0xF000, 0x5816),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flog2d",     two(0xF000, 0x5416),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flog2l",     two(0xF000, 0x4016),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flog2p",     two(0xF000, 0x4C16),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flog2s",     two(0xF000, 0x4416),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flog2w",     two(0xF000, 0x5016),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flog2x",     two(0xF000, 0x0016),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flog2x",     two(0xF000, 0x4816),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flog2x",     two(0xF000, 0x0016),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flognb",     two(0xF000, 0x5814),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flognd",     two(0xF000, 0x5414),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flognl",     two(0xF000, 0x4014),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flognp",     two(0xF000, 0x4C14),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flogns",     two(0xF000, 0x4414),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flognw",     two(0xF000, 0x5014),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flognx",     two(0xF000, 0x0014),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flognx",     two(0xF000, 0x4814),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flognx",     two(0xF000, 0x0014),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"flognp1b",   two(0xF000, 0x5806),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"flognp1d",   two(0xF000, 0x5406),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"flognp1l",   two(0xF000, 0x4006),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"flognp1p",   two(0xF000, 0x4C06),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"flognp1s",   two(0xF000, 0x4406),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"flognp1w",   two(0xF000, 0x5006),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"flognp1x",   two(0xF000, 0x0006),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"flognp1x",   two(0xF000, 0x4806),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"flognp1x",   two(0xF000, 0x0006),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fmodb",      two(0xF000, 0x5821),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fmodd",      two(0xF000, 0x5421),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fmodl",      two(0xF000, 0x4021),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fmodp",      two(0xF000, 0x4C21),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fmods",      two(0xF000, 0x4421),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fmodw",      two(0xF000, 0x5021),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fmodx",      two(0xF000, 0x0021),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fmodx",      two(0xF000, 0x4821),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+/* {"fmodx",   two(0xF000, 0x0021),    two(0xF1C0, 0xE07F),    "IiFt"}, JF */
+
+{"fmoveb",     two(0xF000, 0x5800),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},              /* fmove from <ea> to fp<n> */
+{"fmoveb",     two(0xF000, 0x7800),    two(0xF1C0, 0xFC7F),    "IiF7@b"},              /* fmove from fp<n> to <ea> */
+{"fmoved",     two(0xF000, 0x5400),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},              /* fmove from <ea> to fp<n> */
+{"fmoved",     two(0xF000, 0x7400),    two(0xF1C0, 0xFC7F),    "IiF7@F"},              /* fmove from fp<n> to <ea> */
+{"fmovel",     two(0xF000, 0x4000),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},              /* fmove from <ea> to fp<n> */
+{"fmovel",     two(0xF000, 0x6000),    two(0xF1C0, 0xFC7F),    "IiF7@l"},              /* fmove from fp<n> to <ea> */
+/* Warning:  The addressing modes on these are probably not right:
+   esp, Areg direct is only allowed for FPI */
+               /* fmove.l from/to system control registers: */
+{"fmovel",     two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "Iis8@s"},
+{"fmovel",     two(0xF000, 0x8000),    two(0xF1C0, 0xE3FF),    "Ii*ls8"},
+
+/* {"fmovel",  two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "Iis8@s"},
+{"fmovel",     two(0xF000, 0x8000),    two(0xF2C0, 0xE3FF),    "Ii*ss8"}, */
+
+{"fmovep",     two(0xF000, 0x4C00),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},              /* fmove from <ea> to fp<n> */
+{"fmovep",     two(0xF000, 0x6C00),    two(0xF1C0, 0xFC00),    "IiF7@pkC"},            /* fmove.p with k-factors: */
+{"fmovep",     two(0xF000, 0x7C00),    two(0xF1C0, 0xFC0F),    "IiF7@pDk"},            /* fmove.p with k-factors: */
+
+{"fmoves",     two(0xF000, 0x4400),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},              /* fmove from <ea> to fp<n> */
+{"fmoves",     two(0xF000, 0x6400),    two(0xF1C0, 0xFC7F),    "IiF7@f"},              /* fmove from fp<n> to <ea> */
+{"fmovew",     two(0xF000, 0x5000),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},              /* fmove from <ea> to fp<n> */
+{"fmovew",     two(0xF000, 0x7000),    two(0xF1C0, 0xFC7F),    "IiF7@w"},              /* fmove from fp<n> to <ea> */
+{"fmovex",     two(0xF000, 0x0000),    two(0xF1C0, 0xE07F),    "IiF8F7"},              /* fmove from <ea> to fp<n> */
+{"fmovex",     two(0xF000, 0x4800),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},              /* fmove from <ea> to fp<n> */
+{"fmovex",     two(0xF000, 0x6800),    two(0xF1C0, 0xFC7F),    "IiF7@x"},              /* fmove from fp<n> to <ea> */
+/* JF removed {"fmovex",       two(0xF000, 0x0000),    two(0xF1C0, 0xE07F),    "IiFt"},                / * fmove from <ea> to fp<n> */
+
+{"fmovecrx",   two(0xF000, 0x5C00),    two(0xF1FF, 0xFC00),    "Ii#CF7"},              /* fmovecr.x #ccc,      FPn */
+{"fmovecr",    two(0xF000, 0x5C00),    two(0xF1FF, 0xFC00),    "Ii#CF7"},
+
+/* Other fmovemx.  */
+{"fmovemx",    two(0xF020, 0xE000),    two(0xF1F8, 0xFF00),    "IdL3-s"},              /* fmovem.x to autodecrement,   static and dynamic */
+{"fmovemx",    two(0xF020, 0xE000),    two(0xF1F8, 0xFF00),    "Id#3-s"},              /* fmovem.x to autodecrement,   static and dynamic */
+
+{"fmovemx",    two(0xF020, 0xE800),    two(0xF1F8, 0xFF8F),    "IiDk-s"},              /* fmovem.x to autodecrement,   static and dynamic */
+
+{"fmovemx",    two(0xF000, 0xF000),    two(0xF1C0, 0xFF00),    "Id#3&s"},              /* fmovem.x to control, static and dynamic: */
+{"fmovemx",    two(0xF000, 0xF800),    two(0xF1C0, 0xFF8F),    "IiDk&s"},              /* fmovem.x to control, static and dynamic: */
+{"fmovemx",    two(0xF000, 0xD000),    two(0xF1C0, 0xFF00),    "Id&s#3"},              /* fmovem.x from control,       static and dynamic: */
+{"fmovemx",    two(0xF000, 0xD800),    two(0xF1C0, 0xFF8F),    "Ii&sDk"},              /* fmovem.x from control,       static and dynamic: */
+{"fmovemx",    two(0xF000, 0xF000),    two(0xF1C0, 0xFF00),    "Idl3&s"},              /* fmovem.x to control, static and dynamic: */
+{"fmovemx",    two(0xF000, 0xD000),    two(0xF1C0, 0xFF00),    "Id&sl3"},              /* fmovem.x from control,       static and dynamic: */
+
+{"fmovemx",    two(0xF018, 0xD000),    two(0xF1F8, 0xFF00),    "Id+sl3"},              /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovemx",    two(0xF018, 0xD000),    two(0xF1F8, 0xFF00),    "Id+s#3"},              /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovemx",    two(0xF018, 0xD800),    two(0xF1F8, 0xFF8F),    "Ii+sDk"},              /* fmovem.x from autoincrement, static and dynamic: */
+
+{"fmoveml",    two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "IiL8@s"},
+{"fmoveml",    two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "Ii#8@s"},
+{"fmoveml",    two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "Iis8@s"},
+
+{"fmoveml",    two(0xF000, 0x8000),    two(0xF2C0, 0xE3FF),    "Ii*sL8"},
+{"fmoveml",    two(0xF000, 0x8000),    two(0xF1C0, 0xE3FF),    "Ii*s#8"},
+{"fmoveml",    two(0xF000, 0x8000),    two(0xF1C0, 0xE3FF),    "Ii*ss8"},
+
+/* fmovemx with register lists */
+{"fmovem",     two(0xF020, 0xE000),    two(0xF1F8, 0xFF00),    "IdL3-s"},              /* fmovem.x to autodecrement,   static and dynamic */
+{"fmovem",     two(0xF000, 0xF000),    two(0xF1C0, 0xFF00),    "Idl3&s"},              /* fmovem.x to control, static and dynamic: */
+{"fmovem",     two(0xF018, 0xD000),    two(0xF1F8, 0xFF00),    "Id+sl3"},              /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovem",     two(0xF000, 0xD000),    two(0xF1C0, 0xFF00),    "Id&sl3"},              /* fmovem.x from control,       static and dynamic: */
+
+       /* Alternate mnemonics for GNU as and GNU CC */
+{"fmovem",     two(0xF020, 0xE000),    two(0xF1F8, 0xFF00),    "Id#3-s"},              /* fmovem.x to autodecrement,   static and dynamic */
+{"fmovem",     two(0xF020, 0xE800),    two(0xF1F8, 0xFF8F),    "IiDk-s"},              /* fmovem.x to autodecrement,   static and dynamic */
+
+{"fmovem",     two(0xF000, 0xF000),    two(0xF1C0, 0xFF00),    "Id#3&s"},              /* fmovem.x to control, static and dynamic: */
+{"fmovem",     two(0xF000, 0xF800),    two(0xF1C0, 0xFF8F),    "IiDk&s"},              /* fmovem.x to control, static and dynamic: */
+
+{"fmovem",     two(0xF018, 0xD000),    two(0xF1F8, 0xFF00),    "Id+s#3"},              /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovem",     two(0xF018, 0xD800),    two(0xF1F8, 0xFF8F),    "Ii+sDk"},              /* fmovem.x from autoincrement, static and dynamic: */
+  
+{"fmovem",     two(0xF000, 0xD000),    two(0xF1C0, 0xFF00),    "Id&s#3"},              /* fmovem.x from control,       static and dynamic: */
+{"fmovem",     two(0xF000, 0xD800),    two(0xF1C0, 0xFF8F),    "Ii&sDk"},              /* fmovem.x from control,       static and dynamic: */
+
+/* fmoveml a FP-control register */
+{"fmovem",     two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "Iis8@s"},
+{"fmovem",     two(0xF000, 0x8000),    two(0xF1C0, 0xE3FF),    "Ii*ss8"},
+
+/* fmoveml a FP-control reglist */
+{"fmovem",     two(0xF000, 0xA000),    two(0xF1C0, 0xE3FF),    "IiL8@s"},
+{"fmovem",     two(0xF000, 0x8000),    two(0xF2C0, 0xE3FF),    "Ii*sL8"},
+
+{"fmulb",      two(0xF000, 0x5823),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fmuld",      two(0xF000, 0x5423),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fmull",      two(0xF000, 0x4023),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fmulp",      two(0xF000, 0x4C23),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fmuls",      two(0xF000, 0x4423),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fmulw",      two(0xF000, 0x5023),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fmulx",      two(0xF000, 0x0023),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fmulx",      two(0xF000, 0x4823),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+/* {"fmulx",   two(0xF000, 0x0023),    two(0xF1C0, 0xE07F),    "IiFt"}, JF */
+
+{"fnegb",      two(0xF000, 0x581A),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fnegd",      two(0xF000, 0x541A),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fnegl",      two(0xF000, 0x401A),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fnegp",      two(0xF000, 0x4C1A),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fnegs",      two(0xF000, 0x441A),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fnegw",      two(0xF000, 0x501A),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fnegx",      two(0xF000, 0x001A),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fnegx",      two(0xF000, 0x481A),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fnegx",      two(0xF000, 0x001A),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fnop",       two(0xF280, 0x0000),    two(0xFFFF, 0xFFFF),    "Ii"},
+
+{"fremb",      two(0xF000, 0x5825),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fremd",      two(0xF000, 0x5425),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"freml",      two(0xF000, 0x4025),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fremp",      two(0xF000, 0x4C25),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"frems",      two(0xF000, 0x4425),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fremw",      two(0xF000, 0x5025),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fremx",      two(0xF000, 0x0025),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fremx",      two(0xF000, 0x4825),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+/* {"fremx",   two(0xF000, 0x0025),    two(0xF1C0, 0xE07F),    "IiFt"}, JF */
+
+{"frestore",   one(0xF140),            one(0xF1C0),            "Id&s"},
+{"frestore",   one(0xF158),            one(0xF1F8),            "Id+s"},
+{"fsave",      one(0xF100),            one(0xF1C0),            "Id&s"},
+{"fsave",      one(0xF120),            one(0xF1F8),            "Id-s"},
+
+{"fsincosb",   two(0xF000, 0x5830),    two(0xF1C0, 0xFC78),    "Ii;bF7FC"},
+{"fsincosd",   two(0xF000, 0x5430),    two(0xF1C0, 0xFC78),    "Ii;FF7FC"},
+{"fsincosl",   two(0xF000, 0x4030),    two(0xF1C0, 0xFC78),    "Ii;lF7FC"},
+{"fsincosp",   two(0xF000, 0x4C30),    two(0xF1C0, 0xFC78),    "Ii;pF7FC"},
+{"fsincoss",   two(0xF000, 0x4430),    two(0xF1C0, 0xFC78),    "Ii;fF7FC"},
+{"fsincosw",   two(0xF000, 0x5030),    two(0xF1C0, 0xFC78),    "Ii;wF7FC"},
+{"fsincosx",   two(0xF000, 0x0030),    two(0xF1C0, 0xE078),    "IiF8F7FC"},
+{"fsincosx",   two(0xF000, 0x4830),    two(0xF1C0, 0xFC78),    "Ii;xF7FC"},
+
+{"fscaleb",    two(0xF000, 0x5826),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fscaled",    two(0xF000, 0x5426),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fscalel",    two(0xF000, 0x4026),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fscalep",    two(0xF000, 0x4C26),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fscales",    two(0xF000, 0x4426),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fscalew",    two(0xF000, 0x5026),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fscalex",    two(0xF000, 0x0026),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fscalex",    two(0xF000, 0x4826),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+/* {"fscalex", two(0xF000, 0x0026),    two(0xF1C0, 0xE07F),    "IiFt"}, JF */
+
+/* $ is necessary to prevent the assembler from using PC-relative.
+   If @ were used, "label: fseq label" could produce "ftrapeq",
+   because "label" became "pc@label".  */
+{"fseq",       two(0xF040, 0x0001),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsf",                two(0xF040, 0x0000),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsge",       two(0xF040, 0x0013),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsgl",       two(0xF040, 0x0016),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsgle",      two(0xF040, 0x0017),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsgt",       two(0xF040, 0x0012),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsle",       two(0xF040, 0x0015),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fslt",       two(0xF040, 0x0014),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsne",       two(0xF040, 0x000E),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsnge",      two(0xF040, 0x001C),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsngl",      two(0xF040, 0x0019),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsngle",     two(0xF040, 0x0018),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsngt",      two(0xF040, 0x001D),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsnle",      two(0xF040, 0x001A),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsnlt",      two(0xF040, 0x001B),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsoge",      two(0xF040, 0x0003),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsogl",      two(0xF040, 0x0006),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsogt",      two(0xF040, 0x0002),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsole",      two(0xF040, 0x0005),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsolt",      two(0xF040, 0x0004),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsor",       two(0xF040, 0x0007),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsseq",      two(0xF040, 0x0011),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fssf",       two(0xF040, 0x0010),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fssne",      two(0xF040, 0x001E),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsst",       two(0xF040, 0x001F),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fst",                two(0xF040, 0x000F),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsueq",      two(0xF040, 0x0009),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsuge",      two(0xF040, 0x000B),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsugt",      two(0xF040, 0x000A),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsule",      two(0xF040, 0x000D),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsult",      two(0xF040, 0x000C),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+{"fsun",       two(0xF040, 0x0008),    two(0xF1C0, 0xFFFF),    "Ii$s"},
+
+{"fsgldivb",   two(0xF000, 0x5824),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsgldivd",   two(0xF000, 0x5424),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsgldivl",   two(0xF000, 0x4024),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsgldivp",   two(0xF000, 0x4C24),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsgldivs",   two(0xF000, 0x4424),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsgldivw",   two(0xF000, 0x5024),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsgldivx",   two(0xF000, 0x0024),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsgldivx",   two(0xF000, 0x4824),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsgldivx",   two(0xF000, 0x0024),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsglmulb",   two(0xF000, 0x5827),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsglmuld",   two(0xF000, 0x5427),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsglmull",   two(0xF000, 0x4027),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsglmulp",   two(0xF000, 0x4C27),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsglmuls",   two(0xF000, 0x4427),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsglmulw",   two(0xF000, 0x5027),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsglmulx",   two(0xF000, 0x0027),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsglmulx",   two(0xF000, 0x4827),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsglmulx",   two(0xF000, 0x0027),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsinb",      two(0xF000, 0x580E),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsind",      two(0xF000, 0x540E),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsinl",      two(0xF000, 0x400E),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsinp",      two(0xF000, 0x4C0E),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsins",      two(0xF000, 0x440E),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsinw",      two(0xF000, 0x500E),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsinx",      two(0xF000, 0x000E),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsinx",      two(0xF000, 0x480E),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsinx",      two(0xF000, 0x000E),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsinhb",     two(0xF000, 0x5802),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsinhd",     two(0xF000, 0x5402),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsinhl",     two(0xF000, 0x4002),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsinhp",     two(0xF000, 0x4C02),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsinhs",     two(0xF000, 0x4402),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsinhw",     two(0xF000, 0x5002),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsinhx",     two(0xF000, 0x0002),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsinhx",     two(0xF000, 0x4802),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsinhx",     two(0xF000, 0x0002),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsqrtb",     two(0xF000, 0x5804),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsqrtd",     two(0xF000, 0x5404),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsqrtl",     two(0xF000, 0x4004),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsqrtp",     two(0xF000, 0x4C04),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsqrts",     two(0xF000, 0x4404),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsqrtw",     two(0xF000, 0x5004),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsqrtx",     two(0xF000, 0x0004),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsqrtx",     two(0xF000, 0x4804),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsqrtx",     two(0xF000, 0x0004),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"fsubb",      two(0xF000, 0x5828),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"fsubd",      two(0xF000, 0x5428),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"fsubl",      two(0xF000, 0x4028),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"fsubp",      two(0xF000, 0x4C28),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"fsubs",      two(0xF000, 0x4428),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"fsubw",      two(0xF000, 0x5028),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"fsubx",      two(0xF000, 0x0028),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"fsubx",      two(0xF000, 0x4828),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"fsubx",      two(0xF000, 0x0028),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"ftanb",      two(0xF000, 0x580F),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftand",      two(0xF000, 0x540F),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftanl",      two(0xF000, 0x400F),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftanp",      two(0xF000, 0x4C0F),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftans",      two(0xF000, 0x440F),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftanw",      two(0xF000, 0x500F),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftanx",      two(0xF000, 0x000F),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftanx",      two(0xF000, 0x480F),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftanx",      two(0xF000, 0x000F),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"ftanhb",     two(0xF000, 0x5809),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftanhd",     two(0xF000, 0x5409),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftanhl",     two(0xF000, 0x4009),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftanhp",     two(0xF000, 0x4C09),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftanhs",     two(0xF000, 0x4409),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftanhw",     two(0xF000, 0x5009),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftanhx",     two(0xF000, 0x0009),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftanhx",     two(0xF000, 0x4809),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftanhx",     two(0xF000, 0x0009),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"ftentoxb",   two(0xF000, 0x5812),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftentoxd",   two(0xF000, 0x5412),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftentoxl",   two(0xF000, 0x4012),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftentoxp",   two(0xF000, 0x4C12),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftentoxs",   two(0xF000, 0x4412),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftentoxw",   two(0xF000, 0x5012),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftentoxx",   two(0xF000, 0x0012),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftentoxx",   two(0xF000, 0x4812),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftentoxx",   two(0xF000, 0x0012),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+{"ftrapeq",    two(0xF07C, 0x0001),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapf",     two(0xF07C, 0x0000),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapge",    two(0xF07C, 0x0013),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapgl",    two(0xF07C, 0x0016),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapgle",   two(0xF07C, 0x0017),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapgt",    two(0xF07C, 0x0012),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftraple",    two(0xF07C, 0x0015),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftraplt",    two(0xF07C, 0x0014),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapne",    two(0xF07C, 0x000E),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapnge",   two(0xF07C, 0x001C),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapngl",   two(0xF07C, 0x0019),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapngle",  two(0xF07C, 0x0018),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapngt",   two(0xF07C, 0x001D),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapnle",   two(0xF07C, 0x001A),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapnlt",   two(0xF07C, 0x001B),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapoge",   two(0xF07C, 0x0003),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapogl",   two(0xF07C, 0x0006),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapogt",   two(0xF07C, 0x0002),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapole",   two(0xF07C, 0x0005),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapolt",   two(0xF07C, 0x0004),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapor",    two(0xF07C, 0x0007),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapseq",   two(0xF07C, 0x0011),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapsf",    two(0xF07C, 0x0010),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapsne",   two(0xF07C, 0x001E),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapst",    two(0xF07C, 0x001F),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapt",     two(0xF07C, 0x000F),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapueq",   two(0xF07C, 0x0009),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapuge",   two(0xF07C, 0x000B),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapugt",   two(0xF07C, 0x000A),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapule",   two(0xF07C, 0x000D),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapult",   two(0xF07C, 0x000C),    two(0xF1FF, 0xFFFF),    "Ii"},
+{"ftrapun",    two(0xF07C, 0x0008),    two(0xF1FF, 0xFFFF),    "Ii"},
+        
+{"ftrapeqw",   two(0xF07A, 0x0001),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapfw",    two(0xF07A, 0x0000),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapgew",   two(0xF07A, 0x0013),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapglw",   two(0xF07A, 0x0016),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapglew",  two(0xF07A, 0x0017),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapgtw",   two(0xF07A, 0x0012),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftraplew",   two(0xF07A, 0x0015),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapltw",   two(0xF07A, 0x0014),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnew",   two(0xF07A, 0x000E),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapngew",  two(0xF07A, 0x001C),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnglw",  two(0xF07A, 0x0019),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnglew", two(0xF07A, 0x0018),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapngtw",  two(0xF07A, 0x001D),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnlew",  two(0xF07A, 0x001A),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapnltw",  two(0xF07A, 0x001B),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapogew",  two(0xF07A, 0x0003),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapoglw",  two(0xF07A, 0x0006),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapogtw",  two(0xF07A, 0x0002),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapolew",  two(0xF07A, 0x0005),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapoltw",  two(0xF07A, 0x0004),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftraporw",   two(0xF07A, 0x0007),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapseqw",  two(0xF07A, 0x0011),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapsfw",   two(0xF07A, 0x0010),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapsnew",  two(0xF07A, 0x001E),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapstw",   two(0xF07A, 0x001F),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftraptw",    two(0xF07A, 0x000F),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapueqw",  two(0xF07A, 0x0009),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapugew",  two(0xF07A, 0x000B),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapugtw",  two(0xF07A, 0x000A),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapulew",  two(0xF07A, 0x000D),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapultw",  two(0xF07A, 0x000C),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+{"ftrapunw",   two(0xF07A, 0x0008),    two(0xF1FF, 0xFFFF),    "Ii^w"},
+
+{"ftrapeql",   two(0xF07B, 0x0001),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapfl",    two(0xF07B, 0x0000),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapgel",   two(0xF07B, 0x0013),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapgll",   two(0xF07B, 0x0016),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapglel",  two(0xF07B, 0x0017),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapgtl",   two(0xF07B, 0x0012),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftraplel",   two(0xF07B, 0x0015),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapltl",   two(0xF07B, 0x0014),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnel",   two(0xF07B, 0x000E),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapngel",  two(0xF07B, 0x001C),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapngll",  two(0xF07B, 0x0019),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnglel", two(0xF07B, 0x0018),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapngtl",  two(0xF07B, 0x001D),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnlel",  two(0xF07B, 0x001A),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapnltl",  two(0xF07B, 0x001B),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapogel",  two(0xF07B, 0x0003),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapogll",  two(0xF07B, 0x0006),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapogtl",  two(0xF07B, 0x0002),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapolel",  two(0xF07B, 0x0005),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapoltl",  two(0xF07B, 0x0004),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftraporl",   two(0xF07B, 0x0007),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapseql",  two(0xF07B, 0x0011),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapsfl",   two(0xF07B, 0x0010),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapsnel",  two(0xF07B, 0x001E),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapstl",   two(0xF07B, 0x001F),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftraptl",    two(0xF07B, 0x000F),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapueql",  two(0xF07B, 0x0009),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapugel",  two(0xF07B, 0x000B),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapugtl",  two(0xF07B, 0x000A),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapulel",  two(0xF07B, 0x000D),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapultl",  two(0xF07B, 0x000C),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+{"ftrapunl",   two(0xF07B, 0x0008),    two(0xF1FF, 0xFFFF),    "Ii^l"},
+
+{"ftstb",      two(0xF000, 0x583A),    two(0xF1C0, 0xFC7F),    "Ii;b"},
+{"ftstd",      two(0xF000, 0x543A),    two(0xF1C0, 0xFC7F),    "Ii;F"},
+{"ftstl",      two(0xF000, 0x403A),    two(0xF1C0, 0xFC7F),    "Ii;l"},
+{"ftstp",      two(0xF000, 0x4C3A),    two(0xF1C0, 0xFC7F),    "Ii;p"},
+{"ftsts",      two(0xF000, 0x443A),    two(0xF1C0, 0xFC7F),    "Ii;f"},
+{"ftstw",      two(0xF000, 0x503A),    two(0xF1C0, 0xFC7F),    "Ii;w"},
+{"ftstx",      two(0xF000, 0x003A),    two(0xF1C0, 0xE07F),    "IiF8"},
+{"ftstx",      two(0xF000, 0x483A),    two(0xF1C0, 0xFC7F),    "Ii;x"},
+
+{"ftwotoxb",   two(0xF000, 0x5811),    two(0xF1C0, 0xFC7F),    "Ii;bF7"},
+{"ftwotoxd",   two(0xF000, 0x5411),    two(0xF1C0, 0xFC7F),    "Ii;FF7"},
+{"ftwotoxl",   two(0xF000, 0x4011),    two(0xF1C0, 0xFC7F),    "Ii;lF7"},
+{"ftwotoxp",   two(0xF000, 0x4C11),    two(0xF1C0, 0xFC7F),    "Ii;pF7"},
+{"ftwotoxs",   two(0xF000, 0x4411),    two(0xF1C0, 0xFC7F),    "Ii;fF7"},
+{"ftwotoxw",   two(0xF000, 0x5011),    two(0xF1C0, 0xFC7F),    "Ii;wF7"},
+{"ftwotoxx",   two(0xF000, 0x0011),    two(0xF1C0, 0xE07F),    "IiF8F7"},
+{"ftwotoxx",   two(0xF000, 0x4811),    two(0xF1C0, 0xFC7F),    "Ii;xF7"},
+{"ftwotoxx",   two(0xF000, 0x0011),    two(0xF1C0, 0xE07F),    "IiFt"},
+
+
+{"fjeq",       one(0xF081),            one(0xF1FF),            "IdBc"},
+{"fjf",                one(0xF080),            one(0xF1FF),            "IdBc"},
+{"fjge",       one(0xF093),            one(0xF1FF),            "IdBc"},
+{"fjgl",       one(0xF096),            one(0xF1FF),            "IdBc"},
+{"fjgle",      one(0xF097),            one(0xF1FF),            "IdBc"},
+{"fjgt",       one(0xF092),            one(0xF1FF),            "IdBc"},
+{"fjle",       one(0xF095),            one(0xF1FF),            "IdBc"},
+{"fjlt",       one(0xF094),            one(0xF1FF),            "IdBc"},
+{"fjne",       one(0xF08E),            one(0xF1FF),            "IdBc"},
+{"fjnge",      one(0xF09C),            one(0xF1FF),            "IdBc"},
+{"fjngl",      one(0xF099),            one(0xF1FF),            "IdBc"},
+{"fjngle",     one(0xF098),            one(0xF1FF),            "IdBc"},
+{"fjngt",      one(0xF09D),            one(0xF1FF),            "IdBc"},
+{"fjnle",      one(0xF09A),            one(0xF1FF),            "IdBc"},
+{"fjnlt",      one(0xF09B),            one(0xF1FF),            "IdBc"},
+{"fjoge",      one(0xF083),            one(0xF1FF),            "IdBc"},
+{"fjogl",      one(0xF086),            one(0xF1FF),            "IdBc"},
+{"fjogt",      one(0xF082),            one(0xF1FF),            "IdBc"},
+{"fjole",      one(0xF085),            one(0xF1FF),            "IdBc"},
+{"fjolt",      one(0xF084),            one(0xF1FF),            "IdBc"},
+{"fjor",       one(0xF087),            one(0xF1FF),            "IdBc"},
+{"fjseq",      one(0xF091),            one(0xF1FF),            "IdBc"},
+{"fjsf",       one(0xF090),            one(0xF1FF),            "IdBc"},
+{"fjsne",      one(0xF09E),            one(0xF1FF),            "IdBc"},
+{"fjst",       one(0xF09F),            one(0xF1FF),            "IdBc"},
+{"fjt",                one(0xF08F),            one(0xF1FF),            "IdBc"},
+{"fjueq",      one(0xF089),            one(0xF1FF),            "IdBc"},
+{"fjuge",      one(0xF08B),            one(0xF1FF),            "IdBc"},
+{"fjugt",      one(0xF08A),            one(0xF1FF),            "IdBc"},
+{"fjule",      one(0xF08D),            one(0xF1FF),            "IdBc"},
+{"fjult",      one(0xF08C),            one(0xF1FF),            "IdBc"},
+{"fjun",       one(0xF088),            one(0xF1FF),            "IdBc"},
+
+/* The assembler will ignore attempts to force a short offset */
+
+{"bhis",       one(0061000),           one(0177400),           "Bg"},
+{"blss",       one(0061400),           one(0177400),           "Bg"},
+{"bccs",       one(0062000),           one(0177400),           "Bg"},
+{"bcss",       one(0062400),           one(0177400),           "Bg"},
+{"bnes",       one(0063000),           one(0177400),           "Bg"},
+{"beqs",       one(0063400),           one(0177400),           "Bg"},
+{"bvcs",       one(0064000),           one(0177400),           "Bg"},
+{"bvss",       one(0064400),           one(0177400),           "Bg"},
+{"bpls",       one(0065000),           one(0177400),           "Bg"},
+{"bmis",       one(0065400),           one(0177400),           "Bg"},
+{"bges",       one(0066000),           one(0177400),           "Bg"},
+{"blts",       one(0066400),           one(0177400),           "Bg"},
+{"bgts",       one(0067000),           one(0177400),           "Bg"},
+{"bles",       one(0067400),           one(0177400),           "Bg"},
+
+/* Alternate mnemonics for SUN */
+
+{"jbsr",       one(0060400),           one(0177400),           "Bg"},
+{"jbsr",       one(0047200),           one(0177700),           "!s"},
+{"jra",                one(0060000),           one(0177400),           "Bg"},
+{"jra",                one(0047300),           one(0177700),           "!s"},
+  
+{"jhi",                one(0061000),           one(0177400),           "Bg"},
+{"jls",                one(0061400),           one(0177400),           "Bg"},
+{"jcc",                one(0062000),           one(0177400),           "Bg"},
+{"jcs",                one(0062400),           one(0177400),           "Bg"},
+{"jne",                one(0063000),           one(0177400),           "Bg"},
+{"jeq",                one(0063400),           one(0177400),           "Bg"},
+{"jvc",                one(0064000),           one(0177400),           "Bg"},
+{"jvs",                one(0064400),           one(0177400),           "Bg"},
+{"jpl",                one(0065000),           one(0177400),           "Bg"},
+{"jmi",                one(0065400),           one(0177400),           "Bg"},
+{"jge",                one(0066000),           one(0177400),           "Bg"},
+{"jlt",                one(0066400),           one(0177400),           "Bg"},
+{"jgt",                one(0067000),           one(0177400),           "Bg"},
+{"jle",                one(0067400),           one(0177400),           "Bg"},
+
+/* Short offsets are ignored */
+
+{"jbsrs",      one(0060400),           one(0177400),           "Bg"},
+{"jras",       one(0060000),           one(0177400),           "Bg"},
+{"jhis",       one(0061000),           one(0177400),           "Bg"},
+{"jlss",       one(0061400),           one(0177400),           "Bg"},
+{"jccs",       one(0062000),           one(0177400),           "Bg"},
+{"jcss",       one(0062400),           one(0177400),           "Bg"},
+{"jnes",       one(0063000),           one(0177400),           "Bg"},
+{"jeqs",       one(0063400),           one(0177400),           "Bg"},
+{"jvcs",       one(0064000),           one(0177400),           "Bg"},
+{"jvss",       one(0064400),           one(0177400),           "Bg"},
+{"jpls",       one(0065000),           one(0177400),           "Bg"},
+{"jmis",       one(0065400),           one(0177400),           "Bg"},
+{"jges",       one(0066000),           one(0177400),           "Bg"},
+{"jlts",       one(0066400),           one(0177400),           "Bg"},
+{"jgts",       one(0067000),           one(0177400),           "Bg"},
+{"jles",       one(0067400),           one(0177400),           "Bg"},
+
+{"movql",      one(0070000),           one(0170400),           "MsDd"},
+{"moveql",     one(0070000),           one(0170400),           "MsDd"},
+{"moval",      one(0020100),           one(0170700),           "*lAd"},
+{"movaw",      one(0030100),           one(0170700),           "*wAd"},
+{"movb",       one(0010000),           one(0170000),           ";b$d"},        /* mov */
+{"movl",       one(0070000),           one(0170400),           "MsDd"},        /* movq written as mov */
+{"movl",       one(0020000),           one(0170000),           "*l$d"},
+{"movl",       one(0020100),           one(0170700),           "*lAd"},
+{"movl",       one(0047140),           one(0177770),           "AsUd"},        /* mov to USP */
+{"movl",       one(0047150),           one(0177770),           "UdAs"},        /* mov from USP */
+{"movc",       one(0047173),           one(0177777),           "R1Jj"},
+{"movc",       one(0047173),           one(0177777),           "R1#j"},
+{"movc",       one(0047172),           one(0177777),           "JjR1"},
+{"movc",       one(0047172),           one(0177777),           "#jR1"},
+{"movml",      one(0044300),           one(0177700),           "#w&s"},        /* movm reg to mem. */
+{"movml",      one(0044340),           one(0177770),           "#w-s"},        /* movm reg to autodecrement. */
+{"movml",      one(0046300),           one(0177700),           "!s#w"},        /* movm mem to reg. */
+{"movml",      one(0046330),           one(0177770),           "+s#w"},        /* movm autoinc to reg. */
+{"movml",      one(0044300),           one(0177700),           "Lw&s"},        /* movm reg to mem. */
+{"movml",      one(0044340),           one(0177770),           "lw-s"},        /* movm reg to autodecrement. */
+{"movml",      one(0046300),           one(0177700),           "!sLw"},        /* movm mem to reg. */
+{"movml",      one(0046330),           one(0177770),           "+sLw"},        /* movm autoinc to reg. */
+{"movmw",      one(0044200),           one(0177700),           "#w&s"},        /* movm reg to mem. */
+{"movmw",      one(0044240),           one(0177770),           "#w-s"},        /* movm reg to autodecrement. */
+{"movmw",      one(0046200),           one(0177700),           "!s#w"},        /* movm mem to reg. */
+{"movmw",      one(0046230),           one(0177770),           "+s#w"},        /* movm autoinc to reg. */
+{"movmw",      one(0044200),           one(0177700),           "Lw&s"},        /* movm reg to mem. */
+{"movmw",      one(0044240),           one(0177770),           "lw-s"},        /* movm reg to autodecrement. */
+{"movmw",      one(0046200),           one(0177700),           "!sLw"},        /* movm mem to reg. */
+{"movmw",      one(0046230),           one(0177770),           "+sLw"},        /* movm autoinc to reg. */
+{"movpl",      one(0000510),           one(0170770),           "dsDd"},        /* memory to register */
+{"movpl",      one(0000710),           one(0170770),           "Ddds"},        /* register to memory */
+{"movpw",      one(0000410),           one(0170770),           "dsDd"},        /* memory to register */
+{"movpw",      one(0000610),           one(0170770),           "Ddds"},        /* register to memory */
+{"movq",       one(0070000),           one(0170400),           "MsDd"},
+{"movw",       one(0030000),           one(0170000),           "*w$d"},
+{"movw",       one(0030100),           one(0170700),           "*wAd"},        /* mova,        written as mov */
+{"movw",       one(0040300),           one(0177700),           "Ss$s"},        /* Move from sr */
+{"movw",       one(0041300),           one(0177700),           "Cs$s"},        /* Move from ccr */
+{"movw",       one(0042300),           one(0177700),           ";wCd"},        /* mov to ccr */
+{"movw",       one(0043300),           one(0177700),           ";wSd"},        /* mov to sr */
+
+{"movsb",      two(0007000, 0),        two(0177700, 07777),    "~sR1"},
+{"movsb",      two(0007000, 04000),    two(0177700, 07777),    "R1~s"},
+{"movsl",      two(0007200, 0),        two(0177700, 07777),    "~sR1"},
+{"movsl",      two(0007200, 04000),    two(0177700, 07777),    "R1~s"},
+{"movsw",      two(0007100, 0),        two(0177700, 07777),    "~sR1"},
+{"movsw",      two(0007100, 04000),    two(0177700, 07777),    "R1~s"},
+
+#ifdef m68851
+ /* name */    /* opcode */            /* match */             /* args */
+
+{"pbac",       one(0xf0c7),            one(0xffbf),            "Bc"},
+{"pbacw",      one(0xf087),            one(0xffbf),            "Bc"},
+{"pbas",       one(0xf0c6),            one(0xffbf),            "Bc"},
+{"pbasw",      one(0xf086),            one(0xffbf),            "Bc"},
+{"pbbc",       one(0xf0c1),            one(0xffbf),            "Bc"},
+{"pbbcw",      one(0xf081),            one(0xffbf),            "Bc"},
+{"pbbs",       one(0xf0c0),            one(0xffbf),            "Bc"},
+{"pbbsw",      one(0xf080),            one(0xffbf),            "Bc"},
+{"pbcc",       one(0xf0cf),            one(0xffbf),            "Bc"},
+{"pbccw",      one(0xf08f),            one(0xffbf),            "Bc"},
+{"pbcs",       one(0xf0ce),            one(0xffbf),            "Bc"},
+{"pbcsw",      one(0xf08e),            one(0xffbf),            "Bc"},
+{"pbgc",       one(0xf0cd),            one(0xffbf),            "Bc"},
+{"pbgcw",      one(0xf08d),            one(0xffbf),            "Bc"},
+{"pbgs",       one(0xf0cc),            one(0xffbf),            "Bc"},
+{"pbgsw",      one(0xf08c),            one(0xffbf),            "Bc"},
+{"pbic",       one(0xf0cb),            one(0xffbf),            "Bc"},
+{"pbicw",      one(0xf08b),            one(0xffbf),            "Bc"},
+{"pbis",       one(0xf0ca),            one(0xffbf),            "Bc"},
+{"pbisw",      one(0xf08a),            one(0xffbf),            "Bc"},
+{"pblc",       one(0xf0c3),            one(0xffbf),            "Bc"},
+{"pblcw",      one(0xf083),            one(0xffbf),            "Bc"},
+{"pbls",       one(0xf0c2),            one(0xffbf),            "Bc"},
+{"pblsw",      one(0xf082),            one(0xffbf),            "Bc"},
+{"pbsc",       one(0xf0c5),            one(0xffbf),            "Bc"},
+{"pbscw",      one(0xf085),            one(0xffbf),            "Bc"},
+{"pbss",       one(0xf0c4),            one(0xffbf),            "Bc"},
+{"pbssw",      one(0xf084),            one(0xffbf),            "Bc"},
+{"pbwc",       one(0xf0c9),            one(0xffbf),            "Bc"},
+{"pbwcw",      one(0xf089),            one(0xffbf),            "Bc"},
+{"pbws",       one(0xf0c8),            one(0xffbf),            "Bc"},
+{"pbwsw",      one(0xf088),            one(0xffbf),            "Bc"},
+
+
+{"pdbac",      two(0xf048, 0x0007),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbas",      two(0xf048, 0x0006),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbbc",      two(0xf048, 0x0001),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbbs",      two(0xf048, 0x0000),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbcc",      two(0xf048, 0x000f),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbcs",      two(0xf048, 0x000e),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbgc",      two(0xf048, 0x000d),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbgs",      two(0xf048, 0x000c),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbic",      two(0xf048, 0x000b),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbis",      two(0xf048, 0x000a),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdblc",      two(0xf048, 0x0003),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbls",      two(0xf048, 0x0002),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbsc",      two(0xf048, 0x0005),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbss",      two(0xf048, 0x0004),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbwc",      two(0xf048, 0x0009),    two(0xfff8, 0xffff),    "DsBw"},
+{"pdbws",      two(0xf048, 0x0008),    two(0xfff8, 0xffff),    "DsBw"},
+
+{"pflusha",    two(0xf000, 0x2400),    two(0xffff, 0xffff),    "" },
+
+{"pflush",     two(0xf000, 0x3010),    two(0xffc0, 0xfe10),    "T3T9" },
+{"pflush",     two(0xf000, 0x3810),    two(0xffc0, 0xfe10),    "T3T9&s" },
+{"pflush",     two(0xf000, 0x3008),    two(0xffc0, 0xfe18),    "D3T9" },
+{"pflush",     two(0xf000, 0x3808),    two(0xffc0, 0xfe18),    "D3T9&s" },
+{"pflush",     two(0xf000, 0x3000),    two(0xffc0, 0xfe1e),    "f3T9" },
+{"pflush",     two(0xf000, 0x3800),    two(0xffc0, 0xfe1e),    "f3T9&s" },
+
+{"pflushs",    two(0xf000, 0x3410),    two(0xfff8, 0xfe10),    "T3T9" },
+{"pflushs",    two(0xf000, 0x3c00),    two(0xfff8, 0xfe00),    "T3T9&s" },
+{"pflushs",    two(0xf000, 0x3408),    two(0xfff8, 0xfe18),    "D3T9" },
+{"pflushs",    two(0xf000, 0x3c08),    two(0xfff8, 0xfe18),    "D3T9&s" },
+{"pflushs",    two(0xf000, 0x3400),    two(0xfff8, 0xfe1e),    "f3T9" },
+{"pflushs",    two(0xf000, 0x3c00),    two(0xfff8, 0xfe1e),    "f3T9&s"},
+
+{"pflushr",    two(0xf000, 0xa000),    two(0xffc0, 0xffff),    "|s" },
+
+{"ploadr",     two(0xf000, 0x2210),    two(0xffc0, 0xfff0),    "T3&s" },
+{"ploadr",     two(0xf000, 0x2208),    two(0xffc0, 0xfff8),    "D3&s" },
+{"ploadr",     two(0xf000, 0x2200),    two(0xffc0, 0xfffe),    "f3&s" },
+{"ploadw",     two(0xf000, 0x2010),    two(0xffc0, 0xfff0),    "T3&s" },
+{"ploadw",     two(0xf000, 0x2008),    two(0xffc0, 0xfff8),    "D3&s" },
+{"ploadw",     two(0xf000, 0x2000),    two(0xffc0, 0xfffe),    "f3&s" },
+
+/* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */
+{"pmove",      two(0xf000, 0x4000),    two(0xffc0, 0xe3ff),    "*sP8" },
+{"pmove",      two(0xf000, 0x4200),    two(0xffc0, 0xe3ff),    "P8%s" },
+{"pmove",      two(0xf000, 0x4000),    two(0xffc0, 0xe3ff),    "|sW8" },
+{"pmove",      two(0xf000, 0x4200),    two(0xffc0, 0xe3ff),    "W8~s" },
+
+/* BADx, BACx */
+{"pmove",      two(0xf000, 0x6200),    two(0xffc0, 0xe3e3),    "*sX3" },
+{"pmove",      two(0xf000, 0x6000),    two(0xffc0, 0xe3e3),    "X3%s" },
+
+/* PSR, PCSR */
+/* {"pmove",   two(0xf000, 0x6100),    two(oxffc0, oxffff),    "*sZ8" }, */
+{"pmove",      two(0xf000, 0x6000),    two(0xffc0, 0xffff),    "*sY8" },
+{"pmove",      two(0xf000, 0x6200),    two(0xffc0, 0xffff),    "Y8%s" },
+{"pmove",      two(0xf000, 0x6600),    two(0xffc0, 0xffff),    "Z8%s" },
+
+{"prestore",   one(0xf140),            one(0xffc0),            "&s"},
+{"prestore",   one(0xf158),            one(0xfff8),            "+s"},
+{"psave",      one(0xf100),            one(0xffc0),            "&s"},
+{"psave",      one(0xf100),            one(0xffc0),            "+s"},
+
+{"psac",       two(0xf040, 0x0007),    two(0xffc0, 0xffff),    "@s"},
+{"psas",       two(0xf040, 0x0006),    two(0xffc0, 0xffff),    "@s"},
+{"psbc",       two(0xf040, 0x0001),    two(0xffc0, 0xffff),    "@s"},
+{"psbs",       two(0xf040, 0x0000),    two(0xffc0, 0xffff),    "@s"},
+{"pscc",       two(0xf040, 0x000f),    two(0xffc0, 0xffff),    "@s"},
+{"pscs",       two(0xf040, 0x000e),    two(0xffc0, 0xffff),    "@s"},
+{"psgc",       two(0xf040, 0x000d),    two(0xffc0, 0xffff),    "@s"},
+{"psgs",       two(0xf040, 0x000c),    two(0xffc0, 0xffff),    "@s"},
+{"psic",       two(0xf040, 0x000b),    two(0xffc0, 0xffff),    "@s"},
+{"psis",       two(0xf040, 0x000a),    two(0xffc0, 0xffff),    "@s"},
+{"pslc",       two(0xf040, 0x0003),    two(0xffc0, 0xffff),    "@s"},
+{"psls",       two(0xf040, 0x0002),    two(0xffc0, 0xffff),    "@s"},
+{"pssc",       two(0xf040, 0x0005),    two(0xffc0, 0xffff),    "@s"},
+{"psss",       two(0xf040, 0x0004),    two(0xffc0, 0xffff),    "@s"},
+{"pswc",       two(0xf040, 0x0009),    two(0xffc0, 0xffff),    "@s"},
+{"psws",       two(0xf040, 0x0008),    two(0xffc0, 0xffff),    "@s"},
+
+{"ptestr",     two(0xf000, 0x8210),    two(0xffc0, 0xe3f0),    "T3&sQ8" },
+{"ptestr",     two(0xf000, 0x8310),    two(0xffc0, 0xe310),    "T3&sQ8A9" },
+{"ptestr",     two(0xf000, 0x8208),    two(0xffc0, 0xe3f8),    "D3&sQ8" },
+{"ptestr",     two(0xf000, 0x8308),    two(0xffc0, 0xe318),    "D3&sQ8A9" },
+{"ptestr",     two(0xf000, 0x8200),    two(0xffc0, 0xe3fe),    "f3&sQ8" },
+{"ptestr",     two(0xf000, 0x8300),    two(0xffc0, 0xe31e),    "f3&sQ8A9" },
+
+{"ptestw",     two(0xf000, 0x8010),    two(0xffc0, 0xe3f0),    "T3&sQ8" },
+{"ptestw",     two(0xf000, 0x8110),    two(0xffc0, 0xe310),    "T3&sQ8A9" },
+{"ptestw",     two(0xf000, 0x8008),    two(0xffc0, 0xe3f8),    "D3&sQ8" },
+{"ptestw",     two(0xf000, 0x8108),    two(0xffc0, 0xe318),    "D3&sQ8A9" },
+{"ptestw",     two(0xf000, 0x8000),    two(0xffc0, 0xe3fe),    "f3&sQ8" },
+{"ptestw",     two(0xf000, 0x8100),    two(0xffc0, 0xe31e),    "f3&sQ8A9" },
+
+{"ptrapacw",   two(0xf07a, 0x0007),    two(0xffff, 0xffff),    "#w"},
+{"ptrapacl",   two(0xf07b, 0x0007),    two(0xffff, 0xffff),    "#l"},
+{"ptrapac",    two(0xf07c, 0x0007),    two(0xffff, 0xffff),    ""},
+
+{"ptrapasw",   two(0xf07a, 0x0006),    two(0xffff, 0xffff),    "#w"},
+{"ptrapasl",   two(0xf07b, 0x0006),    two(0xffff, 0xffff),    "#l"},
+{"ptrapas",    two(0xf07c, 0x0006),    two(0xffff, 0xffff),    ""},
+
+{"ptrapbcw",   two(0xf07a, 0x0001),    two(0xffff, 0xffff),    "#w"},
+{"ptrapbcl",   two(0xf07b, 0x0001),    two(0xffff, 0xffff),    "#l"},
+{"ptrapbc",    two(0xf07c, 0x0001),    two(0xffff, 0xffff),    ""},
+
+{"ptrapbsw",   two(0xf07a, 0x0000),    two(0xffff, 0xffff),    "#w"},
+{"ptrapbsl",   two(0xf07b, 0x0000),    two(0xffff, 0xffff),    "#l"},
+{"ptrapbs",    two(0xf07c, 0x0000),    two(0xffff, 0xffff),    ""},
+
+{"ptrapccw",   two(0xf07a, 0x000f),    two(0xffff, 0xffff),    "#w"},
+{"ptrapccl",   two(0xf07b, 0x000f),    two(0xffff, 0xffff),    "#l"},
+{"ptrapcc",    two(0xf07c, 0x000f),    two(0xffff, 0xffff),    ""},
+
+{"ptrapcsw",   two(0xf07a, 0x000e),    two(0xffff, 0xffff),    "#w"},
+{"ptrapcsl",   two(0xf07b, 0x000e),    two(0xffff, 0xffff),    "#l"},
+{"ptrapcs",    two(0xf07c, 0x000e),    two(0xffff, 0xffff),    ""},
+
+{"ptrapgcw",   two(0xf07a, 0x000d),    two(0xffff, 0xffff),    "#w"},
+{"ptrapgcl",   two(0xf07b, 0x000d),    two(0xffff, 0xffff),    "#l"},
+{"ptrapgc",    two(0xf07c, 0x000d),    two(0xffff, 0xffff),    ""},
+
+{"ptrapgsw",   two(0xf07a, 0x000c),    two(0xffff, 0xffff),    "#w"},
+{"ptrapgsl",   two(0xf07b, 0x000c),    two(0xffff, 0xffff),    "#l"},
+{"ptrapgs",    two(0xf07c, 0x000c),    two(0xffff, 0xffff),    ""},
+
+{"ptrapicw",   two(0xf07a, 0x000b),    two(0xffff, 0xffff),    "#w"},
+{"ptrapicl",   two(0xf07b, 0x000b),    two(0xffff, 0xffff),    "#l"},
+{"ptrapic",    two(0xf07c, 0x000b),    two(0xffff, 0xffff),    ""},
+
+{"ptrapisw",   two(0xf07a, 0x000a),    two(0xffff, 0xffff),    "#w"},
+{"ptrapisl",   two(0xf07b, 0x000a),    two(0xffff, 0xffff),    "#l"},
+{"ptrapis",    two(0xf07c, 0x000a),    two(0xffff, 0xffff),    ""},
+
+{"ptraplcw",   two(0xf07a, 0x0003),    two(0xffff, 0xffff),    "#w"},
+{"ptraplcl",   two(0xf07b, 0x0003),    two(0xffff, 0xffff),    "#l"},
+{"ptraplc",    two(0xf07c, 0x0003),    two(0xffff, 0xffff),    ""},
+
+{"ptraplsw",   two(0xf07a, 0x0002),    two(0xffff, 0xffff),    "#w"},
+{"ptraplsl",   two(0xf07b, 0x0002),    two(0xffff, 0xffff),    "#l"},
+{"ptrapls",    two(0xf07c, 0x0002),    two(0xffff, 0xffff),    ""},
+
+{"ptrapscw",   two(0xf07a, 0x0005),    two(0xffff, 0xffff),    "#w"},
+{"ptrapscl",   two(0xf07b, 0x0005),    two(0xffff, 0xffff),    "#l"},
+{"ptrapsc",    two(0xf07c, 0x0005),    two(0xffff, 0xffff),    ""},
+
+{"ptrapssw",   two(0xf07a, 0x0004),    two(0xffff, 0xffff),    "#w"},
+{"ptrapssl",   two(0xf07b, 0x0004),    two(0xffff, 0xffff),    "#l"},
+{"ptrapss",    two(0xf07c, 0x0004),    two(0xffff, 0xffff),    ""},
+
+{"ptrapwcw",   two(0xf07a, 0x0009),    two(0xffff, 0xffff),    "#w"},
+{"ptrapwcl",   two(0xf07b, 0x0009),    two(0xffff, 0xffff),    "#l"},
+{"ptrapwc",    two(0xf07c, 0x0009),    two(0xffff, 0xffff),    ""},
+
+{"ptrapwsw",   two(0xf07a, 0x0008),    two(0xffff, 0xffff),    "#w"},
+{"ptrapwsl",   two(0xf07b, 0x0008),    two(0xffff, 0xffff),    "#l"},
+{"ptrapws",    two(0xf07c, 0x0008),    two(0xffff, 0xffff),    ""},
+
+{"pvalid",     two(0xf000, 0x2800),    two(0xffc0, 0xffff),    "Vs&s"},
+{"pvalid",     two(0xf000, 0x2c00),    two(0xffc0, 0xfff8),    "A3&s" },
+
+#endif /* m68851 */
+
+};
+
+int numopcodes=sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);
+
+struct m68k_opcode *endop = m68k_opcodes+sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);
diff --git a/gdb/m68k-pinsn.c b/gdb/m68k-pinsn.c
new file mode 100644 (file)
index 0000000..608bc25
--- /dev/null
@@ -0,0 +1,774 @@
+/* Print m68k instructions for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "m68k-opcode.h"
+#include "gdbcore.h"
+
+/* 68k instructions are never longer than this many bytes.  */
+#define MAXLEN 22
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
+
+extern char *reg_names[];
+char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
+                    "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
+
+static unsigned char *print_insn_arg ();
+static unsigned char *print_indexed ();
+static void print_base ();
+static int fetch_arg ();
+
+#define NEXTBYTE(p)  (p += 2, ((char *)p)[-1])
+
+#define NEXTWORD(p)  \
+  (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
+
+#define NEXTLONG(p)  \
+  (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+#define NEXTSINGLE(p) \
+  (p += 4, *((float *)(p - 4)))
+
+#define NEXTDOUBLE(p) \
+  (p += 8, *((double *)(p - 8)))
+
+#define NEXTEXTEND(p) \
+  (p += 12, 0.0)       /* Need a function to convert from extended to double
+                          precision... */
+
+#define NEXTPACKED(p) \
+  (p += 12, 0.0)       /* Need a function to convert from packed to double
+                          precision.   Actually, it's easier to print a
+                          packed number than a double anyway, so maybe
+                          there should be a special case to handle this... */
+\f
+/* Print the m68k instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  unsigned char buffer[MAXLEN];
+  register int i;
+  register unsigned char *p;
+  register char *d;
+  register int bestmask;
+  int best;
+
+  read_memory (memaddr, buffer, MAXLEN);
+
+  bestmask = 0;
+  best = -1;
+  for (i = 0; i < NOPCODES; i++)
+    {
+      register unsigned int opcode = m68k_opcodes[i].opcode;
+      register unsigned int match = m68k_opcodes[i].match;
+      if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
+         && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
+         && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
+         && ((0xff & buffer[3] & match) == (0xff & opcode)))
+       {
+         /* Don't use for printout the variants of divul and divsl
+            that have the same register number in two places.
+            The more general variants will match instead.  */
+         for (d = m68k_opcodes[i].args; *d; d += 2)
+           if (d[1] == 'D')
+             break;
+
+         /* Don't use for printout the variants of most floating
+            point coprocessor instructions which use the same
+            register number in two places, as above. */
+         if (*d == 0)
+           for (d = m68k_opcodes[i].args; *d; d += 2)
+             if (d[1] == 't')
+               break;
+
+         if (*d == 0 && match > bestmask)
+           {
+             best = i;
+             bestmask = match;
+           }
+       }
+    }
+
+  /* Handle undefined instructions.  */
+  if (best < 0)
+    {
+      fprintf_filtered (stream, "0%o", (buffer[0] << 8) + buffer[1]);
+      return 2;
+    }
+
+  fprintf_filtered (stream, "%s", m68k_opcodes[best].name);
+
+  /* Point at first word of argument data,
+     and at descriptor for first argument.  */
+  p = buffer + 2;
+  
+  /* Why do this this way? -MelloN */
+  for (d = m68k_opcodes[best].args; *d; d += 2)
+    {
+      if (d[0] == '#')
+       {
+         if (d[1] == 'l' && p - buffer < 6)
+           p = buffer + 6;
+         else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
+           p = buffer + 4;
+       }
+      if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
+       p = buffer + 4;
+      if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
+       p = buffer + 6;
+      if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
+       p = buffer + 4;
+    }
+
+  d = m68k_opcodes[best].args;
+
+  if (*d)
+    fputs_filtered (" ", stream);
+
+  while (*d)
+    {
+      p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream);
+      d += 2;
+      if (*d && *(d - 2) != 'I' && *d != 'k')
+       fputs_filtered (",", stream);
+    }
+  return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, buffer, p, addr, stream)
+     char *d;
+     unsigned char *buffer;
+     register unsigned char *p;
+     CORE_ADDR addr;           /* PC for this arg to be relative to */
+     FILE *stream;
+{
+  register int val;
+  register int place = d[1];
+  int regno;
+  register char *regname;
+  register unsigned char *p1;
+  register double flval;
+  int flt_p;
+
+  switch (*d)
+    {
+    case 'C':
+      fprintf_filtered (stream, "ccr");
+      break;
+
+    case 'S':
+      fprintf_filtered (stream, "sr");
+      break;
+
+    case 'U':
+      fprintf_filtered (stream, "usp");
+      break;
+
+    case 'J':
+      {
+       static struct { char *name; int value; } names[]
+         = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
+            {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
+            {"msp", 0x803}, {"isp", 0x804}};
+
+       val = fetch_arg (buffer, place, 12);
+       for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
+         if (names[regno].value == val)
+           {
+             fprintf_filtered (stream, names[regno].name);
+             break;
+           }
+       if (regno < 0)
+         fprintf_filtered (stream, "%d", val);
+      }
+      break;
+
+    case 'Q':
+      val = fetch_arg (buffer, place, 3);
+      /* 0 means 8, except for the bkpt instruction... */
+      if (val == 0 && d[1] != 's')
+       val = 8;
+      fprintf_filtered (stream, "#%d", val);
+      break;
+
+    case 'M':
+      val = fetch_arg (buffer, place, 8);
+      if (val & 0x80)
+       val = val - 0x100;
+      fprintf_filtered (stream, "#%d", val);
+      break;
+
+    case 'T':
+      val = fetch_arg (buffer, place, 4);
+      fprintf_filtered (stream, "#%d", val);
+      break;
+
+    case 'D':
+      fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
+      break;
+
+    case 'A':
+      fprintf_filtered (stream, "%s",
+                       reg_names[fetch_arg (buffer, place, 3) + 010]);
+      break;
+
+    case 'R':
+      fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
+      break;
+
+    case 'F':
+      fprintf_filtered (stream, "fp%d", fetch_arg (buffer, place, 3));
+      break;
+
+    case 'O':
+      val = fetch_arg (buffer, place, 6);
+      if (val & 0x20)
+       fprintf_filtered (stream, "%s", reg_names [val & 7]);
+      else
+       fprintf_filtered (stream, "%d", val);
+      break;
+
+    case '+':
+      fprintf_filtered (stream, "%s@+",
+                       reg_names[fetch_arg (buffer, place, 3) + 8]);
+      break;
+
+    case '-':
+      fprintf_filtered (stream, "%s@-",
+              reg_names[fetch_arg (buffer, place, 3) + 8]);
+      break;
+
+    case 'k':
+      if (place == 'k')
+       fprintf_filtered (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
+      else if (place == 'C')
+       {
+         val = fetch_arg (buffer, place, 7);
+         if ( val > 63 )               /* This is a signed constant. */
+           val -= 128;
+         fprintf_filtered (stream, "{#%d}", val);
+       }
+      else
+       error ("Invalid arg format in opcode table: \"%c%c\".",
+              *d, place);
+      break;
+
+    case '#':
+    case '^':
+      p1 = buffer + (*d == '#' ? 2 : 4);
+      if (place == 's')
+       val = fetch_arg (buffer, place, 4);
+      else if (place == 'C')
+       val = fetch_arg (buffer, place, 7);
+      else if (place == '8')
+       val = fetch_arg (buffer, place, 3);
+      else if (place == '3')
+       val = fetch_arg (buffer, place, 8);
+      else if (place == 'b')
+       val = NEXTBYTE (p1);
+      else if (place == 'w')
+       val = NEXTWORD (p1);
+      else if (place == 'l')
+       val = NEXTLONG (p1);
+      else
+       error ("Invalid arg format in opcode table: \"%c%c\".",
+              *d, place);
+      fprintf_filtered (stream, "#%d", val);
+      break;
+
+    case 'B':
+      if (place == 'b')
+       val = NEXTBYTE (p);
+      else if (place == 'w')
+       val = NEXTWORD (p);
+      else if (place == 'l')
+       val = NEXTLONG (p);
+      else if (place == 'g')
+       {
+         val = ((char *)buffer)[1];
+         if (val == 0)
+           val = NEXTWORD (p);
+         else if (val == -1)
+           val = NEXTLONG (p);
+       }
+      else if (place == 'c')
+       {
+         if (buffer[1] & 0x40)         /* If bit six is one, long offset */
+           val = NEXTLONG (p);
+         else
+           val = NEXTWORD (p);
+       }
+      else
+       error ("Invalid arg format in opcode table: \"%c%c\".",
+              *d, place);
+
+      print_address (addr + val, stream);
+      break;
+
+    case 'd':
+      val = NEXTWORD (p);
+      fprintf_filtered (stream, "%s@(%d)",
+                       reg_names[fetch_arg (buffer, place, 3)], val);
+      break;
+
+    case 's':
+      fprintf_filtered (stream, "%s",
+                       fpcr_names[fetch_arg (buffer, place, 3)]);
+      break;
+
+    case 'I':
+      val = fetch_arg (buffer, 'd', 3);                  /* Get coprocessor ID... */
+      if (val != 1)                            /* Unusual coprocessor ID? */
+       fprintf_filtered (stream, "(cpid=%d) ", val);
+      if (place == 'i')
+       p += 2;                      /* Skip coprocessor extended operands */
+      break;
+
+    case '*':
+    case '~':
+    case '%':
+    case ';':
+    case '@':
+    case '!':
+    case '$':
+    case '?':
+    case '/':
+    case '&':
+
+      if (place == 'd')
+       {
+         val = fetch_arg (buffer, 'x', 6);
+         val = ((val & 7) << 3) + ((val >> 3) & 7);
+       }
+      else
+       val = fetch_arg (buffer, 's', 6);
+
+      /* Get register number assuming address register.  */
+      regno = (val & 7) + 8;
+      regname = reg_names[regno];
+      switch (val >> 3)
+       {
+       case 0:
+         fprintf_filtered (stream, "%s", reg_names[val]);
+         break;
+
+       case 1:
+         fprintf_filtered (stream, "%s", regname);
+         break;
+
+       case 2:
+         fprintf_filtered (stream, "%s@", regname);
+         break;
+
+       case 3:
+         fprintf_filtered (stream, "%s@+", regname);
+         break;
+
+       case 4:
+         fprintf_filtered (stream, "%s@-", regname);
+         break;
+
+       case 5:
+         val = NEXTWORD (p);
+         fprintf_filtered (stream, "%s@(%d)", regname, val);
+         break;
+
+       case 6:
+         p = print_indexed (regno, p, addr, stream);
+         break;
+
+       case 7:
+         switch (val & 7)
+           {
+           case 0:
+             val = NEXTWORD (p);
+             fprintf_filtered (stream, "@#");
+             print_address (val, stream);
+             break;
+
+           case 1:
+             val = NEXTLONG (p);
+             fprintf_filtered (stream, "@#");
+             print_address (val, stream);
+             break;
+
+           case 2:
+             val = NEXTWORD (p);
+             print_address (addr + val, stream);
+             break;
+
+           case 3:
+             p = print_indexed (-1, p, addr, stream);
+             break;
+
+           case 4:
+             flt_p = 1;        /* Assume it's a float... */
+             switch( place )
+             {
+               case 'b':
+                 val = NEXTBYTE (p);
+                 flt_p = 0;
+                 break;
+
+               case 'w':
+                 val = NEXTWORD (p);
+                 flt_p = 0;
+                 break;
+
+               case 'l':
+                 val = NEXTLONG (p);
+                 flt_p = 0;
+                 break;
+
+               case 'f':
+                 flval = NEXTSINGLE(p);
+                 break;
+
+               case 'F':
+                 flval = NEXTDOUBLE(p);
+                 break;
+
+               case 'x':
+                 flval = NEXTEXTEND(p);
+                 break;
+
+               case 'p':
+                 flval = NEXTPACKED(p);
+                 break;
+
+               default:
+                 error ("Invalid arg format in opcode table: \"%c%c\".",
+                      *d, place);
+             }
+             if ( flt_p )      /* Print a float? */
+               fprintf_filtered (stream, "#%g", flval);
+             else
+               fprintf_filtered (stream, "#%d", val);
+             break;
+
+           default:
+             fprintf_filtered (stream, "<invalid address mode 0%o>", val);
+           }
+       }
+      break;
+
+    case 'L':
+    case 'l':
+       if (place == 'w')
+         {
+           char doneany;
+           p1 = buffer + 2;
+           val = NEXTWORD (p1);
+           /* Move the pointer ahead if this point is farther ahead
+              than the last.  */
+           p = p1 > p ? p1 : p;
+           if (val == 0)
+             {
+               fputs_filtered ("#0", stream);
+               break;
+             }
+           if (*d == 'l')
+             {
+               register int newval = 0;
+               for (regno = 0; regno < 16; ++regno)
+                 if (val & (0x8000 >> regno))
+                   newval |= 1 << regno;
+               val = newval;
+             }
+           val &= 0xffff;
+           doneany = 0;
+           for (regno = 0; regno < 16; ++regno)
+             if (val & (1 << regno))
+               {
+                 int first_regno;
+                 if (doneany)
+                   fputs_filtered ("/", stream);
+                 doneany = 1;
+                 fprintf_filtered (stream, "%s", reg_names[regno]);
+                 first_regno = regno;
+                 while (val & (1 << (regno + 1)))
+                   ++regno;
+                 if (regno > first_regno)
+                   fprintf_filtered (stream, "-%s", reg_names[regno]);
+               }
+         }
+       else if (place == '3')
+         {
+           /* `fmovem' insn.  */
+           char doneany;
+           val = fetch_arg (buffer, place, 8);
+           if (val == 0)
+             {
+               fputs_filtered ("#0", stream);
+               break;
+             }
+           if (*d == 'l')
+             {
+               register int newval = 0;
+               for (regno = 0; regno < 8; ++regno)
+                 if (val & (0x80 >> regno))
+                   newval |= 1 << regno;
+               val = newval;
+             }
+           val &= 0xff;
+           doneany = 0;
+           for (regno = 0; regno < 8; ++regno)
+             if (val & (1 << regno))
+               {
+                 int first_regno;
+                 if (doneany)
+                   fputs_filtered ("/", stream);
+                 doneany = 1;
+                 fprintf_filtered (stream, "fp%d", regno);
+                 first_regno = regno;
+                 while (val & (1 << (regno + 1)))
+                   ++regno;
+                 if (regno > first_regno)
+                   fprintf_filtered (stream, "-fp%d", regno);
+               }
+         }
+       else
+         abort ();
+      break;
+
+    default:
+      error ("Invalid arg format in opcode table: \"%c\".", *d);
+    }
+
+  return (unsigned char *) p;
+}
+
+/* Fetch BITS bits from a position in the instruction specified by CODE.
+   CODE is a "place to put an argument", or 'x' for a destination
+   that is a general address (mode and register).
+   BUFFER contains the instruction.  */
+
+static int
+fetch_arg (buffer, code, bits)
+     unsigned char *buffer;
+     char code;
+     int bits;
+{
+  register int val;
+  switch (code)
+    {
+    case 's':
+      val = buffer[1];
+      break;
+
+    case 'd':                  /* Destination, for register or quick.  */
+      val = (buffer[0] << 8) + buffer[1];
+      val >>= 9;
+      break;
+
+    case 'x':                  /* Destination, for general arg */
+      val = (buffer[0] << 8) + buffer[1];
+      val >>= 6;
+      break;
+
+    case 'k':
+      val = (buffer[3] >> 4);
+      break;
+
+    case 'C':
+      val = buffer[3];
+      break;
+
+    case '1':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 12;
+      break;
+
+    case '2':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 6;
+      break;
+
+    case '3':
+    case 'j':
+      val = (buffer[2] << 8) + buffer[3];
+      break;
+
+    case '4':
+      val = (buffer[4] << 8) + buffer[5];
+      val >>= 12;
+      break;
+
+    case '5':
+      val = (buffer[4] << 8) + buffer[5];
+      val >>= 6;
+      break;
+
+    case '6':
+      val = (buffer[4] << 8) + buffer[5];
+      break;
+
+    case '7':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 7;
+      break;
+      
+    case '8':
+      val = (buffer[2] << 8) + buffer[3];
+      val >>= 10;
+      break;
+
+    default:
+      abort ();
+    }
+
+  switch (bits)
+    {
+    case 3:
+      return val & 7;
+    case 4:
+      return val & 017;
+    case 5:
+      return val & 037;
+    case 6:
+      return val & 077;
+    case 7:
+      return val & 0177;
+    case 8:
+      return val & 0377;
+    case 12:
+      return val & 07777;
+    default:
+      abort ();
+    }
+}
+
+/* Print an indexed argument.  The base register is BASEREG (-1 for pc).
+   P points to extension word, in buffer.
+   ADDR is the nominal core address of that extension word.  */
+
+static unsigned char *
+print_indexed (basereg, p, addr, stream)
+     int basereg;
+     unsigned char *p;
+     FILE *stream;
+     CORE_ADDR addr;
+{
+  register int word;
+  static char *scales[] = {"", "*2", "*4", "*8"};
+  register int base_disp;
+  register int outer_disp;
+  char buf[40];
+
+  word = NEXTWORD (p);
+
+  /* Generate the text for the index register.
+     Where this will be output is not yet determined.  */
+  sprintf (buf, "[%s.%c%s]",
+          reg_names[(word >> 12) & 0xf],
+          (word & 0x800) ? 'l' : 'w',
+          scales[(word >> 9) & 3]);
+
+  /* Handle the 68000 style of indexing.  */
+
+  if ((word & 0x100) == 0)
+    {
+      print_base (basereg,
+                 ((word & 0x80) ? word | 0xff00 : word & 0xff)
+                 + ((basereg == -1) ? addr : 0),
+                 stream);
+      fputs_filtered (buf, stream);
+      return p;
+    }
+
+  /* Handle the generalized kind.  */
+  /* First, compute the displacement to add to the base register.  */
+
+  if (word & 0200)
+    basereg = -2;
+  if (word & 0100)
+    buf[0] = 0;
+  base_disp = 0;
+  switch ((word >> 4) & 3)
+    {
+    case 2:
+      base_disp = NEXTWORD (p);
+      break;
+    case 3:
+      base_disp = NEXTLONG (p);
+    }
+  if (basereg == -1)
+    base_disp += addr;
+
+  /* Handle single-level case (not indirect) */
+
+  if ((word & 7) == 0)
+    {
+      print_base (basereg, base_disp, stream);
+      fputs_filtered (buf, stream);
+      return p;
+    }
+
+  /* Two level.  Compute displacement to add after indirection.  */
+
+  outer_disp = 0;
+  switch (word & 3)
+    {
+    case 2:
+      outer_disp = NEXTWORD (p);
+      break;
+    case 3:
+      outer_disp = NEXTLONG (p);
+    }
+
+  fprintf_filtered (stream, "%d(", outer_disp);
+  print_base (basereg, base_disp, stream);
+
+  /* If postindexed, print the closeparen before the index.  */
+  if (word & 4)
+    fprintf_filtered (stream, ")%s", buf);
+  /* If preindexed, print the closeparen after the index.  */
+  else
+    fprintf_filtered (stream, "%s)", buf);
+
+  return p;
+}
+
+/* Print a base register REGNO and displacement DISP, on STREAM.
+   REGNO = -1 for pc, -2 for none (suppressed).  */
+
+static void
+print_base (regno, disp, stream)
+     int regno;
+     int disp;
+     FILE *stream;
+{
+  if (regno == -2)
+    fprintf_filtered (stream, "%d", disp);
+  else if (regno == -1)
+    fprintf_filtered (stream, "0x%x", disp);
+  else
+    fprintf_filtered (stream, "%d(%s)", disp, reg_names[regno]);
+}
diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
new file mode 100644 (file)
index 0000000..edb87db
--- /dev/null
@@ -0,0 +1,26 @@
+/* Target dependent code for the Motorola 68000 series.
+   Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "ieee-float.h"
+
+const struct ext_format ext_format_68881 [] = {
+/* tot sbyte smask expbyte manbyte */
+ { 12, 0,    0x80, 0,1,           4,8  },              /* mc68881 */
+};
diff --git a/gdb/main.c b/gdb/main.c
new file mode 100644 (file)
index 0000000..5845079
--- /dev/null
@@ -0,0 +1,2127 @@
+/* Top level for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+int fclose ();
+#include "defs.h"
+#include "gdbcmd.h"
+#include "param.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "signals.h"
+#include "target.h"
+#include "breakpoint.h"
+
+#include <getopt.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+/* readline defines this.  */
+#undef savestring
+
+#ifdef USG
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include <string.h>
+#include <sys/file.h>
+#include <setjmp.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#ifdef SET_STACK_LIMIT_HUGE
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <ctype.h>
+
+int original_stack_limit;
+#endif
+
+
+/* If this definition isn't overridden by the header files, assume
+   that isatty and fileno exist on this system.  */
+#ifndef ISATTY
+#define ISATTY(FP)     (isatty (fileno (FP)))
+#endif
+
+/* Initialization file name for gdb.  This is overridden in some configs.  */
+
+#ifndef        GDBINIT_FILENAME
+#define        GDBINIT_FILENAME        ".gdbinit"
+#endif
+char gdbinit[] = GDBINIT_FILENAME;
+
+/* Version number of GDB, as a string.  */
+
+extern char *version;
+
+/* Flag for whether we want all the "from_tty" gubbish printed.  */
+
+int caution = 1;                       /* Default is yes, sigh. */
+
+/*
+ * Define all cmd_list_element's
+ */
+
+/* Chain containing all defined commands.  */
+
+struct cmd_list_element *cmdlist;
+
+/* Chain containing all defined info subcommands.  */
+
+struct cmd_list_element *infolist;
+
+/* Chain containing all defined enable subcommands. */
+
+struct cmd_list_element *enablelist;
+
+/* Chain containing all defined disable subcommands. */
+
+struct cmd_list_element *disablelist;
+
+/* Chain containing all defined delete subcommands. */
+
+struct cmd_list_element *deletelist;
+
+/* Chain containing all defined "enable breakpoint" subcommands. */
+
+struct cmd_list_element *enablebreaklist;
+
+/* Chain containing all defined set subcommands */
+
+struct cmd_list_element *setlist;
+
+/* Chain containing all defined show subcommands.  */
+struct cmd_list_element *showlist;
+
+/* Chain containing all defined \"set history\".  */
+
+struct cmd_list_element *sethistlist;
+
+/* Chain containing all defined \"show history\".  */
+struct cmd_list_element *showhistlist;
+
+/* Chain containing all defined \"unset history\".  */
+
+struct cmd_list_element *unsethistlist;
+
+/* stdio stream that command input is being read from.  */
+
+FILE *instream;
+
+/* Current working directory.  */
+
+char *current_directory;
+
+/* The directory name is actually stored here (usually).  */
+static char dirbuf[MAXPATHLEN];
+
+/* Function to call before reading a command, if nonzero.
+   The function receives two args: an input stream,
+   and a prompt string.  */
+   
+void (*window_hook) ();
+
+extern int frame_file_full_name;
+int epoch_interface;
+int xgdb_verbose;
+
+/* The external commands we call... */
+extern void init_source_path ();
+extern void directory_command ();
+extern void exec_file_command ();
+extern void symbol_file_command ();
+extern void core_file_command ();
+extern void tty_command ();
+
+extern void help_list ();
+extern void initialize_all_files ();
+extern void init_malloc ();
+
+/* Forward declarations for this file */
+void free_command_lines ();
+char *gdb_readline ();
+char *command_line_input ();
+static void initialize_main ();
+static void initialize_cmd_lists ();
+static void init_signals ();
+static void quit_command ();
+void command_loop ();
+static void source_command ();
+static void print_gdb_version ();
+static void float_handler ();
+static void cd_command ();
+static void read_command_file ();
+
+char *getenv ();
+
+/* gdb prints this when reading a command interactively */
+static char *prompt;
+
+/* Buffer used for reading command lines, and the size
+   allocated for it so far.  */
+
+char *line;
+int linesize = 100;
+
+/* Baud rate specified for talking to serial target systems.  Default
+   is left as a zero pointer, so targets can choose their own defaults.  */
+
+char *baud_rate;
+
+/* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT.  */
+
+#ifndef STOP_SIGNAL
+#ifdef SIGTSTP
+#define STOP_SIGNAL SIGTSTP
+#endif
+#endif
+\f
+/* This is how `error' returns to command level.  */
+
+jmp_buf to_top_level;
+
+void
+return_to_top_level ()
+{
+  quit_flag = 0;
+  immediate_quit = 0;
+  bpstat_clear_actions(stop_bpstat);   /* Clear queued breakpoint commands */
+  clear_momentary_breakpoints ();
+  disable_current_display ();
+  do_cleanups (0);
+  longjmp (to_top_level, 1);
+}
+
+/* Call FUNC with arg ARGS, catching any errors.
+   If there is no error, return the value returned by FUNC.
+   If there is an error, return zero after printing ERRSTRING
+    (which is in addition to the specific error message already printed).  */
+
+int
+catch_errors (func, args, errstring)
+     int (*func) ();
+     int args;
+     char *errstring;
+{
+  jmp_buf saved;
+  int val;
+  struct cleanup *saved_cleanup_chain;
+
+  saved_cleanup_chain = save_cleanups ();
+
+  bcopy (to_top_level, saved, sizeof (jmp_buf));
+
+  if (setjmp (to_top_level) == 0)
+    val = (*func) (args);
+  else
+    {
+      if (errstring)
+       fprintf (stderr, "%s\n", errstring);
+      val = 0;
+    }
+
+  restore_cleanups (saved_cleanup_chain);
+
+  bcopy (saved, to_top_level, sizeof (jmp_buf));
+  return val;
+}
+
+/* Handler for SIGHUP.  */
+
+static void
+disconnect ()
+{
+  kill_inferior_fast ();
+  signal (SIGHUP, SIG_DFL);
+  kill (getpid (), SIGHUP);
+}
+\f
+/* Clean up on error during a "source" command (or execution of a
+   user-defined command).  */
+
+static void
+source_cleanup (stream)
+     FILE *stream;
+{
+  /* Restore the previous input stream.  */
+  instream = stream;
+}
+
+/* Read commands from STREAM.  */
+static void
+read_command_file (stream)
+     FILE *stream;
+{
+  struct cleanup *cleanups;
+
+  cleanups = make_cleanup (source_cleanup, instream);
+  instream = stream;
+  command_loop ();
+  do_cleanups (cleanups);
+}
+\f
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int count;
+  static int inhibit_gdbinit = 0;
+  static int quiet = 0;
+  static int batch = 0;
+
+  /* Pointers to various arguments from command line.  */
+  char *symarg = NULL;
+  char *execarg = NULL;
+  char *corearg = NULL;
+  char *cdarg = NULL;
+  char *ttyarg = NULL;
+
+  /* Pointers to all arguments of +command option.  */
+  char **cmdarg;
+  /* Allocated size of cmdarg.  */
+  int cmdsize;
+  /* Number of elements of cmdarg used.  */
+  int ncmd;
+
+  /* Indices of all arguments of +directory option.  */
+  char **dirarg;
+  /* Allocated size.  */
+  int dirsize;
+  /* Number of elements used.  */
+  int ndir;
+  
+  register int i;
+
+  /* This needs to happen before the first use of malloc.  */
+  init_malloc ();
+
+#if defined (ALIGN_STACK_ON_STARTUP)
+  i = (int) &count & 0x3;
+  if (i != 0)
+    alloca (4 - i);
+#endif
+
+  cmdsize = 1;
+  cmdarg = (char **) xmalloc (cmdsize * sizeof (*cmdarg));
+  ncmd = 0;
+  dirsize = 1;
+  dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
+  ndir = 0;
+
+  quit_flag = 0;
+  line = (char *) xmalloc (linesize);
+  line[0] = '\0';              /* Terminate saved (now empty) cmd line */
+  instream = stdin;
+
+  getwd (dirbuf);
+  current_directory = dirbuf;
+
+#ifdef SET_STACK_LIMIT_HUGE
+  {
+    struct rlimit rlim;
+
+    /* Set the stack limit huge so that alloca (particularly stringtab
+     * in dbxread.c) does not fail. */
+    getrlimit (RLIMIT_STACK, &rlim);
+    original_stack_limit = rlim.rlim_cur;
+    rlim.rlim_cur = rlim.rlim_max;
+    setrlimit (RLIMIT_STACK, &rlim);
+  }
+#endif /* SET_STACK_LIMIT_HUGE */
+
+  /* Parse arguments and options.  */
+  {
+    int c;
+    static int print_help;
+    /* When var field is 0, use flag field to record the equivalent
+       short option (or arbitrary numbers starting at 10 for those
+       with no equivalent).  */
+    static struct option long_options[] =
+      {
+       {"quiet", 0, &quiet, 1},
+       {"nx", 0, &inhibit_gdbinit, 1},
+       {"batch", 0, &batch, 1},
+       {"epoch", 0, &epoch_interface, 1},
+       {"fullname", 0, &frame_file_full_name, 1},
+       {"help", 0, &print_help, 1},
+       {"se", 1, 0, 10},
+       {"symbols", 1, 0, 's'},
+       {"s", 1, 0, 's'},
+       {"exec", 1, 0, 'e'},
+       {"core", 1, 0, 'c'},
+       {"c", 1, 0, 'c'},
+       {"command", 1, 0, 'x'},
+       {"x", 1, 0, 'x'},
+       {"directory", 1, 0, 'd'},
+       {"cd", 1, 0, 11},
+       {"tty", 1, 0, 't'},
+       {"b", 1, 0, 'b'},
+/* Allow machine descriptions to add more options... */
+#ifdef ADDITIONAL_OPTIONS
+       ADDITIONAL_OPTIONS
+#endif
+      };
+
+    while (1)
+      {
+       c = getopt_long_only (argc, argv, "",
+                             long_options, &option_index);
+       if (c == EOF)
+         break;
+
+       /* Long option that takes an argument.  */
+       if (c == 0 && long_options[option_index].flag == 0)
+         c = long_options[option_index].val;
+
+       switch (c)
+         {
+         case 0:
+           /* Long option that just sets a flag.  */
+           break;
+         case 10:
+           symarg = optarg;
+           execarg = optarg;
+           break;
+         case 11:
+           cdarg = optarg;
+           break;
+         case 's':
+           symarg = optarg;
+           break;
+         case 'e':
+           execarg = optarg;
+           break;
+         case 'c':
+           corearg = optarg;
+           break;
+         case 'x':
+           cmdarg[ncmd++] = optarg;
+           if (ncmd >= cmdsize)
+             {
+               cmdsize *= 2;
+               cmdarg = (char **) xrealloc ((char *)cmdarg,
+                                            cmdsize * sizeof (*cmdarg));
+             }
+           break;
+         case 'd':
+           dirarg[ndir++] = optarg;
+           if (ndir >= dirsize)
+             {
+               dirsize *= 2;
+               dirarg = (char **) xrealloc ((char *)dirarg,
+                                            dirsize * sizeof (*dirarg));
+             }
+           break;
+         case 't':
+           ttyarg = optarg;
+           break;
+         case 'q':
+           quiet = 1;
+           break;
+         case 'b':
+           baud_rate = optarg;
+           break;
+#ifdef ADDITIONAL_OPTION_CASES
+         ADDITIONAL_OPTION_CASES
+#endif
+         case '?':
+           fprintf (stderr,
+                    "Use `%s +help' for a complete list of options.\n",
+                    argv[0]);
+           exit (1);
+         }
+
+      }
+    if (print_help)
+      {
+       fputs ("\
+This is GDB, the GNU debugger.  Use the command\n\
+    gdb [options] [executable [core-file]]\n\
+to enter the debugger.\n\
+\n\
+Options available are:\n\
+  -help             Print this message.\n\
+  -quiet            Do not print version number on startup.\n\
+  -fullname         Output information used by emacs-GDB interface.\n\
+  -epoch            Output information used by epoch emacs-GDB interface.\n\
+  -batch            Exit after processing options.\n\
+  -nx               Do not read .gdbinit file.\n\
+  -tty=TTY          Use TTY for input/output by the program being debugged.\n\
+  -cd=DIR           Change current directory to DIR.\n\
+  -directory=DIR    Search for source files in DIR.\n\
+  -command=FILE     Execute GDB commands from FILE.\n\
+  -symbols=SYMFILE  Read symbols from SYMFILE.\n\
+  -exec=EXECFILE    Use EXECFILE as the executable.\n\
+  -se=FILE          Use FILE as symbol file and executable file.\n\
+  -core=COREFILE    Analyze the core dump COREFILE.\n\
+  -b BAUDRATE       Set serial port baud rate used for remote debugging\n\
+", stderr);
+#ifdef ADDITIONAL_OPTION_HELP
+       fputs (ADDITIONAL_OPTION_HELP, stderr);
+#endif
+       fputs ("\n\
+For more information, type \"help\" from within GDB, or consult the\n\
+GDB manual (available as on-line info or a printed manual).\n", stderr);
+       /* Exiting after printing this message seems like
+          the most useful thing to do.  */
+       exit (0);
+      }
+    
+    /* OK, that's all the options.  The other arguments are filenames.  */
+    count = 0;
+    for (; optind < argc; optind++)
+      switch (++count)
+       {
+       case 1:
+         symarg = argv[optind];
+         execarg = argv[optind];
+         break;
+       case 2:
+         corearg = argv[optind];
+         break;
+       case 3:
+         fprintf (stderr,
+                  "Excess command line arguments ignored. (%s%s)\n",
+                  argv[optind], (optind == argc - 1) ? "" : " ...");
+         break;
+       }
+    if (batch)
+      quiet = 1;
+  }
+
+  /* Run the init function of each source file */
+
+  initialize_cmd_lists ();     /* This needs to be done first */
+  initialize_all_files ();
+  initialize_main ();          /* But that omits this file!  Do it now */
+  init_signals ();
+
+  if (!quiet)
+    {
+      /* Print all the junk in one place, with a blank line after it
+        to separate it from important stuff like "no such file".  
+        Also, we skip most of the noise, like Emacs, if started with
+        a file name rather than with no arguments.  */
+      if (execarg == 0) {
+       print_gdb_version (1);
+       printf ("Type \"help\" for a list of commands.\n\n");
+      }
+    }
+
+  /* Now perform all the actions indicated by the arguments.  */
+  if (cdarg != NULL)
+    {
+      if (!setjmp (to_top_level))
+       {
+         cd_command (cdarg, 0);
+         init_source_path ();
+       }
+    }
+  for (i = 0; i < ndir; i++)
+    if (!setjmp (to_top_level))
+      directory_command (dirarg[i], 0);
+  free (dirarg);
+  if (execarg != NULL
+      && symarg != NULL
+      && strcmp (execarg, symarg) == 0)
+    {
+      /* The exec file and the symbol-file are the same.  If we can't open
+        it, better only print one error message.  */
+      if (!setjmp (to_top_level))
+       {
+         exec_file_command (execarg, !batch);
+         symbol_file_command (symarg, !batch);
+       }
+    }
+  else
+    {
+      if (execarg != NULL)
+       if (!setjmp (to_top_level))
+         exec_file_command (execarg, !batch);
+      if (symarg != NULL)
+       if (!setjmp (to_top_level))
+         symbol_file_command (symarg, !batch);
+    }
+  if (corearg != NULL)
+    if (!setjmp (to_top_level))
+      core_file_command (corearg, !batch);
+    else if (!setjmp (to_top_level))
+      attach_command (corearg, !batch);
+
+  if (ttyarg != NULL)
+    if (!setjmp (to_top_level))
+      tty_command (ttyarg, !batch);
+
+#ifdef ADDITIONAL_OPTION_HANDLER
+  ADDITIONAL_OPTION_HANDLER;
+#endif
+
+  {
+    struct stat homebuf, cwdbuf;
+    char *homedir, *homeinit;
+
+    /* Read init file, if it exists in home directory  */
+    homedir = getenv ("HOME");
+    if (homedir)
+      {
+       homeinit = (char *) alloca (strlen (getenv ("HOME")) +
+                                   strlen (gdbinit) + 10);
+       strcpy (homeinit, getenv ("HOME"));
+       strcat (homeinit, "/");
+       strcat (homeinit, gdbinit);
+       if (!inhibit_gdbinit && access (homeinit, R_OK) == 0)
+         if (!setjmp (to_top_level))
+           source_command (homeinit, 0);
+
+       /* Do stats; no need to do them elsewhere since we'll only
+          need them if homedir is set.  Make sure that they are
+          zero in case one of them fails (this guarantees that they
+          won't match if either exists).  */
+       
+       bzero (&homebuf, sizeof (struct stat));
+       bzero (&cwdbuf, sizeof (struct stat));
+       
+       stat (homeinit, &homebuf);
+       stat (gdbinit, &cwdbuf); /* We'll only need this if
+                                        homedir was set.  */
+      }
+    
+    /* Read the input file in the current directory, *if* it isn't
+       the same file (it should exist, also).  */
+
+    if (!homedir
+       || bcmp ((char *) &homebuf,
+                (char *) &cwdbuf,
+                sizeof (struct stat)))
+      if (!inhibit_gdbinit && access (gdbinit, R_OK) == 0)
+       if (!setjmp (to_top_level))
+         source_command (gdbinit, 0);
+  }
+
+  for (i = 0; i < ncmd; i++)
+    if (!setjmp (to_top_level))
+      {
+       if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0')
+         read_command_file (stdin);
+       else
+         source_command (cmdarg[i], !batch);
+      }
+  free (cmdarg);
+
+  if (batch)
+    {
+      /* We have hit the end of the batch file.  */
+      exit (0);
+    }
+
+  /* Do any host- or target-specific hacks.  This is used for i960 targets
+     to force the user to set a nindy target and spec its parameters.  */
+
+#ifdef BEFORE_MAIN_LOOP_HOOK
+  BEFORE_MAIN_LOOP_HOOK;
+#endif
+
+  /* The command loop.  */
+
+  while (1)
+    {
+      if (!setjmp (to_top_level))
+       {
+         command_loop ();
+          quit_command ((char *)0, instream == stdin);
+       }
+    }
+  /* No exit -- exit is through quit_command.  */
+}
+
+/* Execute the line P as a command.
+   Pass FROM_TTY as second argument to the defining function.  */
+
+void
+execute_command (p, from_tty)
+     char *p;
+     int from_tty;
+{
+  register struct cmd_list_element *c;
+  register struct command_line *cmdlines;
+
+  free_all_values ();
+
+  /* This can happen when command_line_input hits end of file.  */
+  if (p == NULL)
+      return;
+  
+  while (*p == ' ' || *p == '\t') p++;
+  if (*p)
+    {
+      char *arg;
+      
+      c = lookup_cmd (&p, cmdlist, "", 0, 1);
+      /* Pass null arg rather than an empty one.  */
+      arg = *p ? p : 0;
+      if (c->class == class_user)
+       {
+         struct cleanup *old_chain;
+         
+         if (*p)
+           error ("User-defined commands cannot take arguments.");
+         cmdlines = c->user_commands;
+         if (cmdlines == 0)
+           /* Null command */
+           return;
+
+         /* Set the instream to 0, indicating execution of a
+            user-defined function.  */
+         old_chain =  make_cleanup (source_cleanup, instream);
+         instream = (FILE *) 0;
+         while (cmdlines)
+           {
+             execute_command (cmdlines->line, 0);
+             cmdlines = cmdlines->next;
+           }
+         do_cleanups (old_chain);
+       }
+      else if (c->type == set_cmd || c->type == show_cmd)
+       do_setshow_command (arg, from_tty & caution, c);
+      else if (c->function == NO_FUNCTION)
+       error ("That is not a command, just a help topic.");
+      else
+       (*c->function) (arg, from_tty & caution);
+    }
+}
+
+/* ARGSUSED */
+static void
+do_nothing (foo)
+     int foo;
+{
+}
+
+/* Read commands from `instream' and execute them
+   until end of file or error reading instream.  */
+void
+command_loop ()
+{
+  struct cleanup *old_chain;
+  char *command;
+  int stdin_is_tty = ISATTY (stdin);
+
+  while (!feof (instream))
+    {
+      if (window_hook && instream == stdin)
+       (*window_hook) (instream, prompt);
+
+      quit_flag = 0;
+      if (instream == stdin && stdin_is_tty)
+       reinitialize_more_filter ();
+      old_chain = make_cleanup (do_nothing, 0);
+      command = command_line_input (instream == stdin ? prompt : 0,
+                                     instream == stdin);
+      if (command == 0)
+       return;
+      execute_command (command, instream == stdin);
+      /* Do any commands attached to breakpoint we stopped at.  */
+      bpstat_do_actions (&stop_bpstat);
+      do_cleanups (old_chain);
+    }
+}
+\f
+/* Commands call this if they do not want to be repeated by null lines.  */
+
+void
+dont_repeat ()
+{
+  /* If we aren't reading from standard input, we are saving the last
+     thing read from stdin in line and don't want to delete it.  Null lines
+     won't repeat here in any case.  */
+  if (instream == stdin)
+    *line = 0;
+}
+\f
+/* Read a line from the stream "instream" without command line editing.
+
+   It prints PRROMPT once at the start.
+
+   If RETURN_RESULT is set it allocates
+   space for whatever the user types and returns the result.
+   If not, it just discards what the user types and returns a garbage
+   non-NULL value.
+
+   No matter what return_result is, a NULL return means end of file.  */
+char *
+gdb_readline (prrompt, return_result)
+     char *prrompt;
+     int return_result;
+{
+  int c;
+  char *result;
+  int input_index = 0;
+  int result_size = 80;
+
+  if (prrompt)
+    {
+      printf (prrompt);
+      fflush (stdout);
+    }
+  
+  if (return_result)
+    result = (char *) xmalloc (result_size);
+
+  while (1)
+    {
+      /* Read from stdin if we are executing a user defined command.
+        This is the right thing for prompt_for_continue, at least.  */
+      c = fgetc (instream ? instream : stdin);
+      if (c == EOF || c == '\n')
+       break;
+      if (return_result)
+       {
+         result[input_index++] = c;
+         while (input_index >= result_size)
+           {
+             result_size *= 2;
+             result = (char *) xrealloc (result, result_size);
+           }
+       }
+    }
+
+  if (c == EOF)
+    {
+      if (return_result)
+       free (result);
+      return NULL;
+    }
+
+  if (return_result)
+    {
+      result[input_index++] = '\0';
+      return result;
+    }
+  else
+    /* Return any old non-NULL pointer.  */
+    return (char *) "non-NULL";
+}
+
+/* Declaration for fancy readline with command line editing.  */
+char *readline ();
+
+/* Variables which control command line editing and history
+   substitution.  These variables are given default values at the end
+   of this file.  */
+static int command_editing_p;
+static int history_expansion_p;
+static int write_history_p;
+static int history_size;
+static char *history_filename;
+
+/* Variables which are necessary for fancy command line editing.  */
+char *gdb_completer_word_break_characters =
+  " \t\n!@#$%^&*()-+=|~`}{[]\"';:?/>.<,";
+
+/* Functions that are used as part of the fancy command line editing.  */
+
+/* This can be used for functions which don't want to complete on symbols
+   but don't want to complete on anything else either.  */
+/* ARGSUSED */
+char **
+noop_completer (text)
+     char *text;
+{
+  return NULL;
+}
+
+/* Generate symbol names one by one for the completer.  If STATE is
+   zero, then we need to initialize, otherwise the initialization has
+   already taken place.  TEXT is what we expect the symbol to start
+   with.  RL_LINE_BUFFER is available to be looked at; it contains the
+   entire text of the line.  RL_POINT is the offset in that line of
+   the cursor.  You should pretend that the line ends at RL_POINT.
+   The result is NULL if there are no more completions, else a char
+   string which is a possible completion.  */
+char *
+symbol_completion_function (text, state)
+     char *text;
+     int state;
+{
+  static char **list = (char **)NULL;
+  static int index;
+  char *output;
+  extern char *rl_line_buffer;
+  extern int rl_point;
+  char *tmp_command, *p;
+  struct cmd_list_element *c, *result_list;
+
+  if (!state)
+    {
+      /* Free the storage used by LIST, but not by the strings inside.  This is
+        because rl_complete_internal () frees the strings. */
+      if (list)
+       free (list);
+      list = 0;
+      index = 0;
+
+      /* Decide whether to complete on a list of gdb commands or on
+        symbols.  */
+      tmp_command = (char *) alloca (rl_point + 1);
+      p = tmp_command;
+      
+      strncpy (tmp_command, rl_line_buffer, rl_point);
+      tmp_command[rl_point] = '\0';
+
+      if (rl_point == 0)
+       {
+         /* An empty line we want to consider ambiguous; that is,
+            it could be any command.  */
+         c = (struct cmd_list_element *) -1;
+         result_list = 0;
+       }
+      else
+       c = lookup_cmd_1 (&p, cmdlist, &result_list, 1);
+
+      /* Move p up to the next interesting thing.  */
+      while (*p == ' ' || *p == '\t')
+       p++;
+
+      if (!c)
+       /* He's typed something unrecognizable.  Sigh.  */
+       list = (char **) 0;
+      else if (c == (struct cmd_list_element *) -1)
+       {
+         /* If we didn't recognize everything up to the thing that
+            needs completing, and we don't know what command it is
+            yet, we are in trouble.  Part of the trouble might be
+            that the list of delimiters used by readline includes
+            '-', which we use in commands.  Check for this.  */
+         if (p + strlen(text) != tmp_command + rl_point) {
+           if (tmp_command[rl_point - strlen(text) - 1] == '-')
+             text = p;
+           else {
+             /* This really should not produce an error.  Better would
+                be to pretend to hit RETURN here; this would produce a
+                response like "Ambiguous command: foo, foobar, etc",
+                and leave the line available for re-entry with ^P.  Instead,
+                this error blows away the user's typed input without
+                any way to get it back.  */
+             error ("  Unrecognized command.");
+           }
+         }
+         
+         /* He's typed something ambiguous.  This is easier.  */
+         if (result_list)
+           list = complete_on_cmdlist (*result_list->prefixlist, text);
+         else
+           list = complete_on_cmdlist (cmdlist, text);
+       }
+      else
+       {
+         /* If we've gotten this far, gdb has recognized a full
+            command.  There are several possibilities:
+
+            1) We need to complete on the command.
+            2) We need to complete on the possibilities coming after
+            the command.
+            2) We need to complete the text of what comes after the
+            command.   */
+
+         if (!*p && *text)
+           /* Always (might be longer versions of thie command).  */
+           list = complete_on_cmdlist (result_list, text);
+         else if (!*p && !*text)
+           {
+             if (c->prefixlist)
+               list = complete_on_cmdlist (*c->prefixlist, "");
+             else
+               list = (*c->completer) ("");
+           }
+         else
+           {
+             if (c->prefixlist && !c->allow_unknown)
+               {
+#if 0
+                 /* Something like "info adsfkdj".  But error() is not
+                    the proper response; just return no completions
+                    instead.  */
+                 *p = '\0';
+                 error ("\"%s\" command requires a subcommand.",
+                        tmp_command);
+#else
+                 list = NULL;
+#endif
+               }
+             else
+               list = (*c->completer) (text);
+           }
+       }
+    }
+
+  /* If the debugged program wasn't compiled with symbols, or if we're
+     clearly completing on a command and no command matches, return
+     NULL.  */
+  if (!list)
+    return ((char *)NULL);
+
+  output = list[index];
+  if (output)
+    index++;
+
+  return (output);
+}
+\f
+#ifdef STOP_SIGNAL
+static void
+stop_sig ()
+{
+#if STOP_SIGNAL == SIGTSTP
+  signal (SIGTSTP, SIG_DFL);
+  sigsetmask (0);
+  kill (getpid (), SIGTSTP);
+  signal (SIGTSTP, stop_sig);
+#else
+  signal (STOP_SIGNAL, stop_sig);
+#endif
+  printf ("%s", prompt);
+  fflush (stdout);
+
+  /* Forget about any previous command -- null line now will do nothing.  */
+  dont_repeat ();
+}
+#endif /* STOP_SIGNAL */
+
+#if 0
+Writing the history file upon a terminating signal is not useful,
+  because the info is rarely relevant and is in the core dump anyway.
+  It is an annoyance to have the file cluttering up the place.
+/* The list of signals that would terminate us if not caught.
+   We catch them, but just so that we can write the history file,
+   and so forth. */
+int terminating_signals[] = {
+  SIGHUP, SIGINT, SIGILL, SIGTRAP, SIGIOT,
+  SIGEMT, SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS,
+  SIGPIPE, SIGALRM, SIGTERM,
+#ifdef SIGXCPU
+  SIGXCPU,
+#endif
+#ifdef SIGXFSZ
+  SIGXFSZ,
+#endif
+#ifdef SIGVTALRM
+  SIGVTALRM,
+#endif
+#ifdef SIGPROF
+  SIGPROF,
+#endif
+#ifdef SIGLOST
+  SIGLOST,
+#endif
+#ifdef SIGUSR1
+  SIGUSR1, SIGUSR2
+#endif
+    };
+
+#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (int))
+
+static void
+catch_termination (sig)
+     int sig;
+{
+  /* We are probably here because GDB has a bug.  Write out the history
+     so that we might have a better chance of reproducing it.  */
+  /* Tell the user what we are doing so he can delete the file if
+     it is unwanted.  */
+  write_history (history_filename);
+  printf ("\n%s written.\n", history_filename);
+  signal (sig, SIG_DFL);
+  kill (getpid (), sig);
+}
+#endif
+
+/* Initialize signal handlers. */
+static void
+init_signals ()
+{
+  extern void request_quit ();
+#if 0
+  register int i;
+
+  for (i = 0; i < TERMSIGS_LENGTH; i++)
+    signal (terminating_signals[i], catch_termination);
+#endif
+
+  signal (SIGINT, request_quit);
+
+  /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get
+     passed to the inferior, which we don't want.  It would be
+     possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but
+     on BSD4.3 systems using vfork, that will (apparently) affect the
+     GDB process as well as the inferior (the signal handling tables
+     being shared between the two, apparently).  Since we establish
+     a handler for SIGQUIT, when we call exec it will set the signal
+     to SIG_DFL for us.  */
+  signal (SIGQUIT, do_nothing);
+  if (signal (SIGHUP, do_nothing) != SIG_IGN)
+    signal (SIGHUP, disconnect);
+  signal (SIGFPE, float_handler);
+}
+\f
+/* Read one line from the command input stream `instream'
+   into the local static buffer `linebuffer' (whose current length
+   is `linelength').
+   The buffer is made bigger as necessary.
+   Returns the address of the start of the line.
+
+   NULL is returned for end of file.
+
+   *If* the instream == stdin & stdin is a terminal, the line read
+   is copied into the file line saver (global var char *line,
+   length linesize) so that it can be duplicated.
+
+   This routine either uses fancy command line editing or
+   simple input as the user has requested.  */
+
+char *
+command_line_input (prrompt, repeat)
+     char *prrompt;
+     int repeat;
+{
+  static char *linebuffer = 0;
+  static int linelength = 0;
+  register char *p;
+  char *p1;
+  char *rl;
+  char *local_prompt = prrompt;
+  register int c;
+  char *nline;
+  char got_eof = 0;
+
+  if (linebuffer == 0)
+    {
+      linelength = 80;
+      linebuffer = (char *) xmalloc (linelength);
+    }
+
+  p = linebuffer;
+
+  /* Control-C quits instantly if typed while in this loop
+     since it should not wait until the user types a newline.  */
+  immediate_quit++;
+#ifdef STOP_SIGNAL
+  signal (STOP_SIGNAL, stop_sig);
+#endif
+
+  while (1)
+    {
+      /* Don't use fancy stuff if not talking to stdin.  */
+      if (command_editing_p && instream == stdin
+         && ISATTY (instream))
+       rl = readline (local_prompt);
+      else
+       rl = gdb_readline (local_prompt, 1);
+
+      if (!rl || rl == (char *) EOF)
+       {
+         got_eof = 1;
+         break;
+       }
+      if (strlen(rl) + 1 + (p - linebuffer) > linelength)
+       {
+         linelength = strlen(rl) + 1 + (p - linebuffer);
+         nline = (char *) xrealloc (linebuffer, linelength);
+         p += nline - linebuffer;
+         linebuffer = nline;
+       }
+      p1 = rl;
+      /* Copy line.  Don't copy null at end.  (Leaves line alone
+         if this was just a newline)  */
+      while (*p1)
+       *p++ = *p1++;
+
+      free (rl);                       /* Allocated in readline.  */
+
+      if (p == linebuffer || *(p - 1) != '\\')
+       break;
+
+      p--;                     /* Put on top of '\'.  */
+      local_prompt = (char *) 0;
+  }
+
+#ifdef STOP_SIGNAL
+  signal (SIGTSTP, SIG_DFL);
+#endif
+  immediate_quit--;
+
+  if (got_eof)
+    return NULL;
+
+  /* Do history expansion if that is wished.  */
+  if (history_expansion_p && instream == stdin
+      && ISATTY (instream))
+    {
+      char *history_value;
+      int expanded;
+
+      *p = '\0';               /* Insert null now.  */
+      expanded = history_expand (linebuffer, &history_value);
+      if (expanded)
+       {
+         /* Print the changes.  */
+         printf ("%s\n", history_value);
+
+         /* If there was an error, call this function again.  */
+         if (expanded < 0)
+           {
+             free (history_value);
+             return command_line_input (prrompt, repeat);
+           }
+         if (strlen (history_value) > linelength)
+           {
+             linelength = strlen (history_value) + 1;
+             linebuffer = (char *) xrealloc (linebuffer, linelength);
+           }
+         strcpy (linebuffer, history_value);
+         p = linebuffer + strlen(linebuffer);
+         free (history_value);
+       }
+    }
+
+  /* If we just got an empty line, and that is supposed
+     to repeat the previous command, return the value in the
+     global buffer.  */
+  if (repeat)
+    {
+      if (p == linebuffer)
+       return line;
+      p1 = linebuffer;
+      while (*p1 == ' ' || *p1 == '\t')
+       p1++;
+      if (!*p1)
+       return line;
+    }
+
+  *p = 0;
+
+  /* Add line to history if appropriate.  */
+  if (instream == stdin
+      && ISATTY (stdin) && *linebuffer)
+    add_history (linebuffer);
+
+  /* Note: lines consisting soley of comments are added to the command
+     history.  This is useful when you type a command, and then
+     realize you don't want to execute it quite yet.  You can comment
+     out the command and then later fetch it from the value history
+     and remove the '#'.  The kill ring is probably better, but some
+     people are in the habit of commenting things out.  */
+  p1 = linebuffer;
+  while ((c = *p1++) != '\0')
+    {
+      if (c == '"')
+       while ((c = *p1++) != '"')
+         {
+           /* Make sure an escaped '"' doesn't make us think the string
+              is ended.  */
+           if (c == '\\')
+             parse_escape (&p1);
+           if (c == '\0')
+             break;
+         }
+      else if (c == '\'')
+       while ((c = *p1++) != '\'')
+         {
+           /* Make sure an escaped '\'' doesn't make us think the string
+              is ended.  */
+           if (c == '\\')
+             parse_escape (&p1);
+           if (c == '\0')
+             break;
+         }
+      else if (c == '#')
+       {
+         /* Found a comment.  */
+         p1[-1] = '\0';
+         break;
+       }
+    }
+
+  /* Save into global buffer if appropriate.  */
+  if (repeat)
+    {
+      if (linelength > linesize)
+       {
+         line = xrealloc (line, linelength);
+         linesize = linelength;
+       }
+      strcpy (line, linebuffer);
+      return line;
+    }
+
+  return linebuffer;
+}
+\f
+/* Read lines from the input stream
+   and accumulate them in a chain of struct command_line's
+   which is then returned.  */
+
+struct command_line *
+read_command_lines ()
+{
+  struct command_line *first = 0;
+  register struct command_line *next, *tail = 0;
+  register char *p, *p1;
+  struct cleanup *old_chain = 0;
+
+  while (1)
+    {
+      dont_repeat ();
+      p = command_line_input (0, instream == stdin);
+      if (p == NULL)
+       /* Treat end of file like "end".  */
+       break;
+      
+      /* Remove leading and trailing blanks.  */
+      while (*p == ' ' || *p == '\t') p++;
+      p1 = p + strlen (p);
+      while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t')) p1--;
+
+      /* Is this "end"?  */
+      if (p1 - p == 3 && !strncmp (p, "end", 3))
+       break;
+
+      /* No => add this line to the chain of command lines.  */
+      next = (struct command_line *) xmalloc (sizeof (struct command_line));
+      next->line = savestring (p, p1 - p);
+      next->next = 0;
+      if (tail)
+       {
+         tail->next = next;
+       }
+      else
+       {
+         /* We just read the first line.
+            From now on, arrange to throw away the lines we have
+            if we quit or get an error while inside this function.  */
+         first = next;
+         old_chain = make_cleanup (free_command_lines, &first);
+       }
+      tail = next;
+    }
+
+  dont_repeat ();
+
+  /* Now we are about to return the chain to our caller,
+     so freeing it becomes his responsibility.  */
+  if (first)
+    discard_cleanups (old_chain);
+  return first;
+}
+
+/* Free a chain of struct command_line's.  */
+
+void
+free_command_lines (lptr)
+      struct command_line **lptr;
+{
+  register struct command_line *l = *lptr;
+  register struct command_line *next;
+
+  while (l)
+    {
+      next = l->next;
+      free (l->line);
+      free (l);
+      l = next;
+    }
+}
+\f
+/* Add an element to the list of info subcommands.  */
+
+void
+add_info (name, fun, doc)
+     char *name;
+     void (*fun) ();
+     char *doc;
+{
+  add_cmd (name, no_class, fun, doc, &infolist);
+}
+
+/* Add an alias to the list of info subcommands.  */
+
+void
+add_info_alias (name, oldname, abbrev_flag)
+     char *name;
+     char *oldname;
+     int abbrev_flag;
+{
+  add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist);
+}
+
+/* The "info" command is defined as a prefix, with allow_unknown = 0.
+   Therefore, its own definition is called only for "info" with no args.  */
+
+/* ARGSUSED */
+static void
+info_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  printf ("\"info\" must be followed by the name of an info command.\n");
+  help_list (infolist, "info ", -1, stdout);
+}
+
+/* The "show" command with no arguments shows all the settings.  */
+
+/* ARGSUSED */
+static void
+show_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  cmd_show_list (showlist, from_tty, "");
+}
+\f
+/* Add an element to the list of commands.  */
+
+void
+add_com (name, class, fun, doc)
+     char *name;
+     enum command_class class;
+     void (*fun) ();
+     char *doc;
+{
+  add_cmd (name, class, fun, doc, &cmdlist);
+}
+
+/* Add an alias or abbreviation command to the list of commands.  */
+
+void
+add_com_alias (name, oldname, class, abbrev_flag)
+     char *name;
+     char *oldname;
+     enum command_class class;
+     int abbrev_flag;
+{
+  add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist);
+}
+
+void
+error_no_arg (why)
+     char *why;
+{
+  error ("Argument required (%s).", why);
+}
+
+static void
+help_command (command, from_tty)
+     char *command;
+     int from_tty; /* Ignored */
+{
+  help_cmd (command, stdout);
+}
+\f
+static void
+validate_comname (comname)
+     char *comname;
+{
+  register char *p;
+
+  if (comname == 0)
+    error_no_arg ("name of command to define");
+
+  p = comname;
+  while (*p)
+    {
+      if (!(*p >= 'A' && *p <= 'Z')
+         && !(*p >= 'a' && *p <= 'z')
+         && !(*p >= '0' && *p <= '9')
+         && *p != '-')
+       error ("Junk in argument list: \"%s\"", p);
+      p++;
+    }
+}
+
+static void
+define_command (comname, from_tty)
+     char *comname;
+     int from_tty;
+{
+  register struct command_line *cmds;
+  register struct cmd_list_element *c, *newc;
+  char *tem = comname;
+  extern void not_just_help_class_command ();
+
+  validate_comname (comname);
+
+  c = lookup_cmd (&tem, cmdlist, "", -1, 1);
+  if (c)
+    {
+      if (c->class == class_user || c->class == class_alias)
+       tem = "Redefine command \"%s\"? ";
+      else
+       tem = "Really redefine built-in command \"%s\"? ";
+      if (!query (tem, comname))
+       error ("Command \"%s\" not redefined.", comname);
+    }
+
+  if (from_tty)
+    {
+      printf ("Type commands for definition of \"%s\".\n\
+End with a line saying just \"end\".\n", comname);
+      fflush (stdout);
+    }
+  comname = savestring (comname, strlen (comname));
+
+  cmds = read_command_lines ();
+
+  if (c && c->class == class_user)
+    free_command_lines (&c->user_commands);
+
+  newc = add_cmd (comname, class_user, not_just_help_class_command,
+          (c && c->class == class_user)
+          ? c->doc : savestring ("User-defined.", 13), &cmdlist);
+  newc->user_commands = cmds;
+}
+
+static void
+document_command (comname, from_tty)
+     char *comname;
+     int from_tty;
+{
+  struct command_line *doclines;
+  register struct cmd_list_element *c;
+  char *tem = comname;
+
+  validate_comname (comname);
+
+  c = lookup_cmd (&tem, cmdlist, "", 0, 1);
+
+  if (c->class != class_user)
+    error ("Command \"%s\" is built-in.", comname);
+
+  if (from_tty)
+    printf ("Type documentation for \"%s\".\n\
+End with a line saying just \"end\".\n", comname);
+
+  doclines = read_command_lines ();
+
+  if (c->doc) free (c->doc);
+
+  {
+    register struct command_line *cl1;
+    register int len = 0;
+
+    for (cl1 = doclines; cl1; cl1 = cl1->next)
+      len += strlen (cl1->line) + 1;
+
+    c->doc = (char *) xmalloc (len + 1);
+    *c->doc = 0;
+
+    for (cl1 = doclines; cl1; cl1 = cl1->next)
+      {
+       strcat (c->doc, cl1->line);
+       if (cl1->next)
+         strcat (c->doc, "\n");
+      }
+  }
+
+  free_command_lines (&doclines);
+}
+\f
+static void
+print_gdb_version (shout)
+     int shout;
+{
+  printf ("GDB %s, Copyright (C) 1991 Free Software Foundation, Inc.\n",
+         version);
+  if (shout)
+    printf ("\
+There is ABSOLUTELY NO WARRANTY for GDB; type \"info warranty\" for details.\n\
+GDB is free software and you are welcome to distribute copies of it\n\
+ under certain conditions; type \"info copying\" to see the conditions.\n");
+}
+
+static void
+version_info (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  immediate_quit++;
+  print_gdb_version (0);
+  immediate_quit--;
+}
+\f
+/* xgdb calls this to reprint the usual GDB prompt.  */
+
+void
+print_prompt ()
+{
+  printf ("%s", prompt);
+  fflush (stdout);
+}
+\f
+static void
+quit_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (inferior_pid != 0)
+    {
+      if (query ("The program is running.  Quit anyway? "))
+       {
+         target_kill (args, from_tty);
+       }
+      else
+       error ("Not confirmed.");
+    }
+  /* Save the history information if it is appropriate to do so.  */
+  if (write_history_p && history_filename)
+    write_history (history_filename);
+  exit (0);
+}
+
+int
+input_from_terminal_p ()
+{
+  return (instream == stdin) & caution;
+}
+\f
+static void
+pwd_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (args) error ("The \"pwd\" command does not take an argument: %s", args);
+  getwd (dirbuf);
+
+  if (strcmp (dirbuf, current_directory))
+    printf ("Working directory %s\n (canonically %s).\n",
+           current_directory, dirbuf);
+  else
+    printf ("Working directory %s.\n", current_directory);
+}
+
+static void
+cd_command (dir, from_tty)
+     char *dir;
+     int from_tty;
+{
+  int len;
+  int change;
+
+  if (dir == 0)
+    error_no_arg ("new working directory");
+
+  dir = tilde_expand (dir);
+  make_cleanup (free, dir);
+
+  len = strlen (dir);
+  dir = savestring (dir, len - (len > 1 && dir[len-1] == '/'));
+  if (dir[0] == '/')
+    current_directory = dir;
+  else
+    {
+      current_directory = concat (current_directory, "/", dir);
+      free (dir);
+    }
+
+  /* Now simplify any occurrences of `.' and `..' in the pathname.  */
+
+  change = 1;
+  while (change)
+    {
+      char *p;
+      change = 0;
+
+      for (p = current_directory; *p;)
+       {
+         if (!strncmp (p, "/./", 2)
+             && (p[2] == 0 || p[2] == '/'))
+           strcpy (p, p + 2);
+         else if (!strncmp (p, "/..", 3)
+                  && (p[3] == 0 || p[3] == '/')
+                  && p != current_directory)
+           {
+             char *q = p;
+             while (q != current_directory && q[-1] != '/') q--;
+             if (q != current_directory)
+               {
+                 strcpy (q-1, p+3);
+                 p = q-1;
+               }
+           }
+         else p++;
+       }
+    }
+
+  if (chdir (dir) < 0)
+    perror_with_name (dir);
+
+  forget_cached_source_info ();
+
+  if (from_tty)
+    pwd_command ((char *) 0, 1);
+}
+\f
+static void
+source_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  FILE *stream;
+  struct cleanup *cleanups;
+  char *file = args;
+
+  if (file == 0)
+    /* Let source without arguments read .gdbinit.  */
+    file = gdbinit;
+
+  file = tilde_expand (file);
+  make_cleanup (free, file);
+
+  stream = fopen (file, "r");
+  if (stream == 0)
+    perror_with_name (file);
+
+  cleanups = make_cleanup (fclose, stream);
+
+  read_command_file (stream);
+
+  do_cleanups (cleanups);
+}
+
+/* ARGSUSED */
+static void
+echo_command (text, from_tty)
+     char *text;
+     int from_tty;
+{
+  char *p = text;
+  register int c;
+
+  if (text)
+    while (c = *p++)
+      {
+       if (c == '\\')
+         {
+           /* \ at end of argument is used after spaces
+              so they won't be lost.  */
+           if (*p == 0)
+             return;
+
+           c = parse_escape (&p);
+           if (c >= 0)
+             fputc (c, stdout);
+         }
+       else
+         fputc (c, stdout);
+      }
+}
+
+/* ARGSUSED */
+static void
+dump_me_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (query ("Should GDB dump core? "))
+    {
+      signal (SIGQUIT, SIG_DFL);
+      kill (getpid (), SIGQUIT);
+    }
+}
+\f
+/* Functions to manipulate command line editing control variables.  */
+
+/* Number of commands to print in each call to editing_info.  */
+#define Hist_print 10
+static void
+editing_info (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  /* Index for history commands.  Relative to history_base.  */
+  int offset;
+
+  /* Number of the history entry which we are planning to display next.
+     Relative to history_base.  */
+  static int num = 0;
+
+  /* The first command in the history which doesn't exist (i.e. one more
+     than the number of the last command).  Relative to history_base.  */
+  int hist_len;
+
+  struct _hist_entry *history_get();
+  extern int history_base;
+
+#if 0
+  /* This is all reported by individual "show" commands.  */
+  printf_filtered ("Interactive command editing is %s.\n",
+         command_editing_p ? "on" : "off");
+
+  printf_filtered ("History expansion of command input is %s.\n",
+         history_expansion_p ? "on" : "off");
+  printf_filtered ("Writing of a history record upon exit is %s.\n",
+         write_history_p ? "enabled" : "disabled");
+  printf_filtered ("The size of the history list (number of stored commands) is %d.\n",
+         history_size);
+  printf_filtered ("The name of the history record is \"%s\".\n\n",
+         history_filename ? history_filename : "");
+#endif /* 0 */
+
+  /* Print out some of the commands from the command history.  */
+  /* First determine the length of the history list.  */
+  hist_len = history_size;
+  for (offset = 0; offset < history_size; offset++)
+    {
+      if (!history_get (history_base + offset))
+       {
+         hist_len = offset;
+         break;
+       }
+    }
+
+  if (args)
+    {
+      if (args[0] == '+' && args[1] == '\0')
+       /* "info editing +" should print from the stored position.  */
+       ;
+      else
+       /* "info editing <exp>" should print around command number <exp>.  */
+       num = (parse_and_eval_address (args) - history_base) - Hist_print / 2;
+    }
+  /* "info editing" means print the last Hist_print commands.  */
+  else
+    {
+      num = hist_len - Hist_print;
+    }
+
+  if (num < 0)
+    num = 0;
+
+  /* If there are at least Hist_print commands, we want to display the last
+     Hist_print rather than, say, the last 6.  */
+  if (hist_len - num < Hist_print)
+    {
+      num = hist_len - Hist_print;
+      if (num < 0)
+       num = 0;
+    }
+
+#if 0
+  /* No need for a header now that "info editing" only prints one thing.  */
+  if (num == hist_len - Hist_print)
+    printf_filtered ("The list of the last %d commands is:\n\n", Hist_print);
+  else
+    printf_filtered ("Some of the stored commands are:\n\n");
+#endif /* 0 */
+
+  for (offset = num; offset < num + Hist_print && offset < hist_len; offset++)
+    {
+      printf_filtered ("%5d  %s\n", history_base + offset,
+             (history_get (history_base + offset))->line);
+    }
+
+  /* The next command we want to display is the next one that we haven't
+     displayed yet.  */
+  num += Hist_print;
+  
+  /* If the user repeats this command with return, it should do what
+     "info editing +" does.  This is unnecessary if arg is null,
+     because "info editing +" is not useful after "info editing".  */
+  if (from_tty && args)
+    {
+      args[0] = '+';
+      args[1] = '\0';
+    }
+}
+
+/* Called by do_setshow_command.  */
+static void
+set_history_size_command (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  if (history_size == UINT_MAX)
+    unstifle_history ();
+  else
+    stifle_history (history_size);
+}
+
+static void
+set_history (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  printf ("\"set history\" must be followed by the name of a history subcommand.\n");
+  help_list (sethistlist, "set history ", -1, stdout);
+}
+
+static void
+show_history (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  cmd_show_list (showhistlist, from_tty);
+}
+
+int info_verbose = 0;          /* Default verbose msgs off */
+
+/* Called by do_setshow_command.  An elaborate joke.  */
+static void 
+set_verbose (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  char *cmdname = "verbose";
+  struct cmd_list_element *showcmd;
+  
+  showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, 1);
+
+  if (info_verbose)
+    {
+      c->doc = "Set verbose printing of informational messages.";
+      showcmd->doc = "Show verbose printing of informational messages.";
+    }
+  else
+    {
+      c->doc = "Set verbosity.";
+      showcmd->doc = "Show verbosity.";
+    }
+}
+
+static void
+float_handler ()
+{
+  /* This message is based on ANSI C, section 4.7.  Note that integer
+     divide by zero causes this, so "float" is a misnomer.  */
+  error ("Erroneous arithmetic operation.");
+}
+
+/* Return whether we are running a batch file or from terminal.  */
+int
+batch_mode ()
+{
+  return !(instream == stdin && ISATTY (stdin));
+}
+
+\f
+static void
+initialize_cmd_lists ()
+{
+  cmdlist = (struct cmd_list_element *) 0;
+  infolist = (struct cmd_list_element *) 0;
+  enablelist = (struct cmd_list_element *) 0;
+  disablelist = (struct cmd_list_element *) 0;
+  deletelist = (struct cmd_list_element *) 0;
+  enablebreaklist = (struct cmd_list_element *) 0;
+  setlist = (struct cmd_list_element *) 0;
+  showlist = NULL;
+  sethistlist = (struct cmd_list_element *) 0;
+  showhistlist = NULL;
+  unsethistlist = (struct cmd_list_element *) 0;
+}
+
+static void
+initialize_main ()
+{
+  struct cmd_list_element *c;
+  
+  char *tmpenv;
+  
+#ifdef DEFAULT_PROMPT
+  prompt = savestring (DEFAULT_PROMPT, strlen(DEFAULT_PROMPT));
+#else
+  prompt = savestring ("(gdb) ", 6);
+#endif
+
+  /* Set the important stuff up for command editing.  */
+  command_editing_p = 1;
+  history_expansion_p = 0;
+  write_history_p = 0;
+  
+  if (tmpenv = getenv ("HISTSIZE"))
+    history_size = atoi (tmpenv);
+  else
+    history_size = 256;
+
+  stifle_history (history_size);
+
+  if (tmpenv = getenv ("GDBHISTFILE"))
+    history_filename = savestring (tmpenv, strlen(tmpenv));
+  else
+    /* We include the current directory so that if the user changes
+       directories the file written will be the same as the one
+       that was read.  */
+    history_filename = concat (current_directory, "/.gdb_history", "");
+
+  read_history (history_filename);
+
+  /* Setup important stuff for command line editing.  */
+  rl_completion_entry_function = (int (*)()) symbol_completion_function;
+  rl_completer_word_break_characters = gdb_completer_word_break_characters;
+  rl_readline_name = "gdb";
+
+  /* Define the classes of commands.
+     They will appear in the help list in the reverse of this order.  */
+
+  add_cmd ("obscure", class_obscure, NO_FUNCTION, "Obscure features.", &cmdlist);
+  add_cmd ("aliases", class_alias, NO_FUNCTION, "Aliases of other commands.", &cmdlist);
+  add_cmd ("user-defined", class_user, NO_FUNCTION, "User-defined commands.\n\
+The commands in this class are those defined by the user.\n\
+Use the \"define\" command to define a command.", &cmdlist);
+  add_cmd ("support", class_support, NO_FUNCTION, "Support facilities.", &cmdlist);
+  add_cmd ("status", class_info, NO_FUNCTION, "Status inquiries.", &cmdlist);
+  add_cmd ("files", class_files, NO_FUNCTION, "Specifying and examining files.", &cmdlist);
+  add_cmd ("breakpoints", class_breakpoint, NO_FUNCTION, "Making program stop at certain points.", &cmdlist);
+  add_cmd ("data", class_vars, NO_FUNCTION, "Examining data.", &cmdlist);
+  add_cmd ("stack", class_stack, NO_FUNCTION, "Examining the stack.\n\
+The stack is made up of stack frames.  Gdb assigns numbers to stack frames\n\
+counting from zero for the innermost (currently executing) frame.\n\n\
+At any time gdb identifies one frame as the \"selected\" frame.\n\
+Variable lookups are done with respect to the selected frame.\n\
+When the program being debugged stops, gdb selects the innermost frame.\n\
+The commands below can be used to select other frames by number or address.",
+          &cmdlist);
+  add_cmd ("running", class_run, NO_FUNCTION, "Running the program.", &cmdlist);
+
+  add_com ("pwd", class_files, pwd_command,
+          "Print working directory.  This is used for your program as well.");
+  add_com ("cd", class_files, cd_command,
+          "Set working directory to DIR for debugger and program being debugged.\n\
+The change does not take effect for the program being debugged\n\
+until the next time it is started.");
+
+  add_show_from_set
+    (add_set_cmd ("prompt", class_support, var_string, (char *)&prompt,
+          "Set gdb's prompt",
+          &setlist),
+     &showlist);
+  
+  add_com ("echo", class_support, echo_command,
+          "Print a constant string.  Give string as argument.\n\
+C escape sequences may be used in the argument.\n\
+No newline is added at the end of the argument;\n\
+use \"\\n\" if you want a newline to be printed.\n\
+Since leading and trailing whitespace are ignored in command arguments,\n\
+if you want to print some you must use \"\\\" before leading whitespace\n\
+to be printed or after trailing whitespace.");
+  add_com ("document", class_support, document_command,
+          "Document a user-defined command.\n\
+Give command name as argument.  Give documentation on following lines.\n\
+End with a line of just \"end\".");
+  add_com ("define", class_support, define_command,
+          "Define a new command name.  Command name is argument.\n\
+Definition appears on following lines, one command per line.\n\
+End with a line of just \"end\".\n\
+Use the \"document\" command to give documentation for the new command.\n\
+Commands defined in this way do not take arguments.");
+
+#ifdef __STDC__
+  add_com ("source", class_support, source_command,
+          "Read commands from a file named FILE.\n\
+Note that the file \"" GDBINIT_FILENAME "\" is read automatically in this way\n\
+when gdb is started.");
+#else
+  /* Punt file name, we can't help it easily.  */
+  add_com ("source", class_support, source_command,
+          "Read commands from a file named FILE.\n\
+Note that the file \".gdbinit\" is read automatically in this way\n\
+when gdb is started.");
+#endif
+
+  add_com ("quit", class_support, quit_command, "Exit gdb.");
+  add_com ("help", class_support, help_command, "Print list of commands.");
+  add_com_alias ("q", "quit", class_support, 1);
+  add_com_alias ("h", "help", class_support, 1);
+
+
+  c = add_set_cmd ("verbose", class_support, var_boolean, (char *)&info_verbose,
+                  "Set ",
+                  &setlist),
+  add_show_from_set (c, &showlist);
+  c->function = set_verbose;
+  set_verbose (NULL, 0, c);
+  
+  add_com ("dump-me", class_obscure, dump_me_command,
+          "Get fatal error; make debugger dump its core.");
+
+  add_show_from_set
+    (add_set_cmd ("editing", class_support, var_boolean, (char *)&command_editing_p,
+          "Set command line editing.\n\
+Use \"on\" to enable to enable the editing, and \"off\" to disable it.\n\
+Without an argument, command line editing is enabled.", &setlist),
+     &showlist);
+
+  add_prefix_cmd ("history", class_support, set_history,
+                 "Generic command for setting command history parameters.",
+                 &sethistlist, "set history ", 0, &setlist);
+  add_prefix_cmd ("history", class_support, show_history,
+                 "Generic command for showing command history parameters.",
+                 &showhistlist, "show history ", 0, &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("expansion", no_class, var_boolean, (char *)&history_expansion_p,
+          "Set history expansion on command input.\n\
+Without an argument, history expansion is enabled.", &sethistlist),
+     &showhistlist);
+
+  add_show_from_set
+    (add_set_cmd ("write", no_class, var_boolean, (char *)&write_history_p,
+          "Set saving of the history record on exit.\n\
+Use \"on\" to enable to enable the saving, and \"off\" to disable it.\n\
+Without an argument, saving is enabled.", &sethistlist),
+     &showhistlist);
+
+  c = add_set_cmd ("size", no_class, var_uinteger, (char *)&history_size,
+                  "Set the size of the command history, \n\
+ie. the number of previous commands to keep a record of.", &sethistlist);
+  add_show_from_set (c, &showhistlist);
+  c->function = set_history_size_command;
+
+  add_show_from_set
+    (add_set_cmd ("filename", no_class, var_filename, (char *)&history_filename,
+          "Set the filename in which to record the command history\n\
+ (the list of previous commands of which a record is kept).", &sethistlist),
+     &showhistlist);
+
+  add_show_from_set
+    (add_set_cmd ("caution", class_support, var_boolean,
+                 (char *)&caution,
+          "Set expected caution of user.\n\
+If on (the default), more warnings are printed, and the user is asked whether\n\
+they really want to do various major commands.", &setlist),
+     &showlist);
+
+  add_prefix_cmd ("info", class_info, info_command,
+                 "Generic command for printing status.",
+                 &infolist, "info ", 0, &cmdlist);
+  add_com_alias ("i", "info", class_info, 1);
+
+  add_prefix_cmd ("show", class_info, show_command,
+                 "Generic command for showing things set with \"set\".",
+                 &showlist, "show ", 0, &cmdlist);
+  /* Another way to get at the same thing.  */
+  add_info ("set", show_command, "Show all GDB settings.");
+
+  add_info ("editing", editing_info, "Status of command editor.");
+
+  add_info ("version", version_info, "Report what version of GDB this is.");
+}
diff --git a/gdb/mcheck.c b/gdb/mcheck.c
new file mode 100755 (executable)
index 0000000..8b63d72
--- /dev/null
@@ -0,0 +1,119 @@
+/* Standard debugging hooks for `malloc'.
+   Copyright 1990 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#include "ansidecl.h"
+#include <stdlib.h>
+#include "gmalloc.h"
+
+/* Old hook values.  */
+static void EXFUN((*old_free_hook), (PTR ptr));
+static PTR EXFUN((*old_malloc_hook), (size_t size));
+static PTR EXFUN((*old_realloc_hook), (PTR ptr, size_t size));
+
+/* Function to call when something awful happens. */
+static void EXFUN((*abortfunc), (void)) = abort;
+
+/* Arbitrary magical numbers.  */
+#define MAGICWORD      0xfedabeeb
+#define MAGICBYTE      ((char) 0xd7)
+
+struct hdr
+  {
+    size_t size;               /* Exact size requested by user.  */
+    unsigned int magic;                /* Magic number to check header integrity.  */
+  };
+
+static void
+DEFUN(checkhdr, (hdr), CONST struct hdr *hdr)
+{
+  if (hdr->magic != MAGICWORD || ((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+    (*abortfunc)();
+}
+
+static void
+DEFUN(freehook, (ptr), PTR ptr)
+{
+  struct hdr *hdr = ((struct hdr *) ptr) - 1;
+  checkhdr(hdr);
+  hdr->magic = 0;
+  __free_hook = old_free_hook;
+  free(hdr);
+  __free_hook = freehook;
+}
+
+static PTR
+DEFUN(mallochook, (size), size_t size)
+{
+  struct hdr *hdr;
+
+  __malloc_hook = old_malloc_hook;
+  hdr = (struct hdr *) malloc(sizeof(struct hdr) + size + 1);
+  __malloc_hook = mallochook;
+  if (hdr == NULL)
+    return NULL;
+
+  hdr->size = size;
+  hdr->magic = MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  return (PTR) (hdr + 1);
+}
+
+static PTR
+DEFUN(reallochook, (ptr, size), PTR ptr AND size_t size)
+{
+  struct hdr *hdr = ((struct hdr *) ptr) - 1;
+
+  checkhdr(hdr);
+  __free_hook = old_free_hook;
+  __malloc_hook = old_malloc_hook;
+  __realloc_hook = old_realloc_hook;
+  hdr = (struct hdr *) realloc((PTR) hdr, sizeof(struct hdr) + size + 1);
+  __free_hook = freehook;
+  __malloc_hook = mallochook;
+  __realloc_hook = reallochook;
+  if (hdr == NULL)
+    return NULL;
+
+  hdr->size = size;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  return (PTR) (hdr + 1);
+}
+
+void
+DEFUN(mcheck, (func), void EXFUN((*func), (void)))
+{
+  static int mcheck_used = 0;
+
+  if (func)
+    abortfunc = func;
+
+  /* These hooks may not be safely inserted if malloc is already in use.  */
+  if (!__malloc_initialized && !mcheck_used)
+    {
+      old_free_hook = __free_hook;
+      __free_hook = freehook;
+      old_malloc_hook = __malloc_hook;
+      __malloc_hook = mallochook;
+      old_realloc_hook = __realloc_hook;
+      __realloc_hook = reallochook;
+      mcheck_used = 1;
+    }
+}
diff --git a/gdb/mem-break.c b/gdb/mem-break.c
new file mode 100644 (file)
index 0000000..eebe7e2
--- /dev/null
@@ -0,0 +1,178 @@
+/* Simulate breakpoints by patching locations in the target system.
+   Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+
+#ifdef BREAKPOINT
+/* This file is only useful if BREAKPOINT is set.  If not, we punt.  */
+
+#include <stdio.h>
+#include "breakpoint.h"
+#include "inferior.h"
+#include "target.h"
+
+/* This is the sequence of bytes we insert for a breakpoint.  On some
+   machines, breakpoints are handled by the target environment and we
+   don't have to worry about them here.  */
+
+static char break_insn[] = BREAKPOINT;
+
+/* This is only to check that BREAKPOINT fits in BREAKPOINT_MAX bytes.  */
+
+static char check_break_insn_size[BREAKPOINT_MAX] = BREAKPOINT;
+
+/* Insert a breakpoint on machines that don't have any better breakpoint
+   support.  We read the contents of the target location and stash it,
+   then overwrite it with a breakpoint instruction.  ADDR is the target
+   location in the target machine.  CONTENTS_CACHE is a pointer to 
+   memory allocated for saving the target contents.  It is guaranteed
+   by the caller to be long enough to save sizeof BREAKPOINT bytes.
+   FIXME: This size is target_arch dependent and should be available in
+   the target_arch transfer vector, if we ever have one...  */
+
+int
+memory_insert_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  int val;
+
+  val = target_read_memory (addr, contents_cache, sizeof break_insn);
+
+  if (val == 0)
+    val = target_write_memory (addr, break_insn, sizeof break_insn);
+
+  return val;
+}
+
+
+int
+memory_remove_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  return target_write_memory (addr, contents_cache, sizeof break_insn);
+}
+
+
+#if 0
+/* This should move back into breakpoint.c, sad to say.   Encapsulate
+    sizeof (BREAKPOINT) by export it as an int from mem-break.c.  */
+
+/* Like target_read_memory() but if breakpoints are inserted, return
+   the shadow contents instead of the breakpoints themselves.  */
+int
+read_memory_nobpt (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     unsigned len;
+{
+  int status;
+  struct breakpoint *b;
+  ALL_BREAKPOINTS (b)
+    {
+      if (b->address == NULL || !b->inserted)
+       continue;
+      else if (b->address + sizeof (break_insn) <= memaddr)
+       /* The breakpoint is entirely before the chunk of memory
+          we are reading.  */
+       continue;
+      else if (b->address >= memaddr + len)
+       /* The breakpoint is entirely after the chunk of memory we
+          are reading.  */
+       continue;
+      else
+       {
+         /* Copy the breakpoint from the shadow contents, and recurse
+            for the things before and after.  */
+         
+         /* Addresses and length of the part of the breakpoint that
+            we need to copy.  */
+         CORE_ADDR membpt = b->address;
+         unsigned int bptlen = sizeof (break_insn);
+         /* Offset within shadow_contents.  */
+         int bptoffset = 0;
+         
+         if (membpt < memaddr)
+           {
+             /* Only copy the second part of the breakpoint.  */
+             bptlen -= memaddr - membpt;
+             bptoffset = memaddr - membpt;
+             membpt = memaddr;
+           }
+
+         if (membpt + bptlen > memaddr + len)
+           {
+             /* Only copy the first part of the breakpoint.  */
+             bptlen -= (membpt + bptlen) - (memaddr + len);
+           }
+
+         bcopy (b->shadow_contents + bptoffset,
+                myaddr + membpt - memaddr, bptlen);
+
+         if (membpt > memaddr)
+           {
+             /* Copy the section of memory before the breakpoint.  */
+             status = read_memory_nobpt (memaddr, myaddr, membpt - memaddr);
+             if (status != 0)
+               return status;
+           }
+
+         if (membpt + bptlen < memaddr + len)
+           {
+             /* Copy the section of memory after the breakpoint.  */
+             status = read_memory_nobpt
+               (membpt + bptlen,
+                myaddr + membpt + bptlen - memaddr,
+                memaddr + len - (membpt + bptlen));
+             if (status != 0)
+               return status;
+           }
+         return 0;
+       }
+    }
+  /* Nothing overlaps.  Just call read_memory_noerr.  */
+  return target_read_memory (memaddr, myaddr, len);
+}
+#endif /* 0 */
+
+#else  /* BREAKPOINT */
+
+char nogo[] = "Breakpoints not implemented for this target.";
+
+int
+memory_insert_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  error (nogo);
+  return 0;    /* lint */
+}
+
+int
+memory_remove_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  error (nogo);
+  return 0;    /* lint */
+}
+
+#endif /* BREAKPOINT */
diff --git a/gdb/mips-opcode.h b/gdb/mips-opcode.h
new file mode 100755 (executable)
index 0000000..fd92c78
--- /dev/null
@@ -0,0 +1,363 @@
+/* Mips opcde list for GDB, the GNU debugger.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+   Contributed by Nobuyuki Hikichi(hikichi@sra.junet)
+   Made to work for little-endian machines, and debugged
+   by Per Bothner (bothner@cs.wisc.edu).
+   Many fixes contributed by Frank Yellin (fy@lucid.com).
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifdef BITS_BIG_ENDIAN
+#define BIT_FIELDS_2(a,b) a;b;
+#define BIT_FIELDS_4(a,b,c,d) a;b;c;d;
+#define BIT_FIELDS_6(a,b,c,d,e,f) a;b;c;d;e;f;
+#else
+#define BIT_FIELDS_2(a,b) b;a;
+#define BIT_FIELDS_4(a,b,c,d) d;c;b;a;
+#define BIT_FIELDS_6(a,b,c,d,e,f) f;e;d;c;b;a;
+#endif
+
+struct op_i_fmt
+{
+BIT_FIELDS_4(
+  unsigned op : 6,
+  unsigned rs : 5,
+  unsigned rt : 5,
+  unsigned immediate : 16)
+};
+
+struct op_j_fmt
+{
+BIT_FIELDS_2(
+  unsigned op : 6,
+  unsigned target : 26)
+};
+
+struct op_r_fmt
+{
+BIT_FIELDS_6(
+  unsigned op : 6,
+  unsigned rs : 5,
+  unsigned rt : 5,
+  unsigned rd : 5,
+  unsigned shamt : 5,
+  unsigned funct : 6)
+};
+
+
+struct fop_i_fmt
+{
+BIT_FIELDS_4(
+  unsigned op : 6,
+  unsigned rs : 5,
+  unsigned rt : 5,
+  unsigned immediate : 16)
+};
+
+struct op_b_fmt
+{
+BIT_FIELDS_4(
+  unsigned op : 6,
+  unsigned rs : 5,
+  unsigned rt : 5,
+  short delta : 16)
+};
+
+struct fop_r_fmt
+{
+BIT_FIELDS_6(
+  unsigned op : 6,
+  unsigned fmt : 5,
+  unsigned ft : 5,
+  unsigned fs : 5,
+  unsigned fd : 5,
+  unsigned funct : 6)
+};
+
+struct mips_opcode
+{
+  char *name;
+  unsigned long opcode;
+  unsigned long match;
+  char *args;
+  int bdelay; /* Nonzero if delayed branch.  */
+};
+
+/* args format;
+
+   "s" rs: source register specifier
+   "t" rt: target register
+   "i" immediate
+   "a" target address
+   "c" branch condition
+   "d" rd: destination register specifier
+   "h" shamt: shift amount
+   "f" funct: function field
+
+  for fpu
+   "S" fs source 1 register
+   "T" ft source 2 register
+   "D" distination register
+*/
+
+#define one(x) (x << 26)
+#define op_func(x, y) ((x << 26) | y)
+#define op_cond(x, y) ((x << 26) | (y << 16))
+#define op_rs_func(x, y, z) ((x << 26) | (y << 21) | z)
+#define op_rs_b11(x, y, z) ((x << 26) | (y << 21) | z)
+#define op_o16(x, y) ((x << 26) | (y << 16))
+#define op_bc(x, y, z) ((x << 26) | (y << 21) | (z << 16))
+
+struct mips_opcode mips_opcodes[] = 
+{
+/* These first opcodes are special cases of the ones in the comments */
+  {"nop",      0,              0xffffffff,          /*li*/     "", 0},
+  {"li",       op_bc(9,0,0),   op_bc(0x3f,31,0),    /*addiu*/  "t,j", 0},
+  {"b",                one(4),         0xffff0000,          /*beq*/    "b", 1},
+  {"move",     op_func(0, 33), op_cond(0x3f,31)|0x7ff,/*addu*/ "d,s", 0},
+
+  {"sll",      op_func(0, 0),  op_func(0x3f, 0x3f),            "d,t,h", 0},
+  {"srl",      op_func(0, 2),  op_func(0x3f, 0x3f),            "d,t,h", 0},
+  {"sra",      op_func(0, 3),  op_func(0x3f, 0x3f),            "d,t,h", 0},
+  {"sllv",     op_func(0, 4),  op_func(0x3f, 0x7ff),           "d,t,s", 0},
+  {"srlv",     op_func(0, 6),  op_func(0x3f, 0x7ff),           "d,t,s", 0},
+  {"srav",     op_func(0, 7),  op_func(0x3f, 0x7ff),           "d,t,s", 0},
+  {"jr",       op_func(0, 8),  op_func(0x3f, 0x1fffff),        "s", 1},
+  {"jalr",     op_func(0, 9),  op_func(0x3f, 0x1f07ff),        "d,s", 1},
+  {"syscall",  op_func(0, 12), op_func(0x3f, 0x3f),            "", 0},
+  {"break",    op_func(0, 13), op_func(0x3f, 0x3f),            "", 0},
+  {"mfhi",      op_func(0, 16), op_func(0x3f, 0x03ff07ff),      "d", 0},
+  {"mthi",      op_func(0, 17), op_func(0x3f, 0x1fffff),        "s", 0},
+  {"mflo",      op_func(0, 18), op_func(0x3f, 0x03ff07ff),      "d", 0},
+  {"mtlo",      op_func(0, 19), op_func(0x3f, 0x1fffff),        "s", 0},
+  {"mult",     op_func(0, 24), op_func(0x3f, 0xffff),          "s,t", 0},
+  {"multu",    op_func(0, 25), op_func(0x3f, 0xffff),          "s,t", 0},
+  {"div",      op_func(0, 26), op_func(0x3f, 0xffff),          "s,t", 0},
+  {"divu",     op_func(0, 27), op_func(0x3f, 0xffff),          "s,t", 0},
+  {"add",      op_func(0, 32), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"addu",     op_func(0, 33), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"sub",      op_func(0, 34), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"subu",     op_func(0, 35), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"and",      op_func(0, 36), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"or",       op_func(0, 37), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"xor",      op_func(0, 38), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"nor",      op_func(0, 39), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"slt",      op_func(0, 42), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+  {"sltu",     op_func(0, 43), op_func(0x3f, 0x7ff),           "d,s,t", 0},
+
+  {"bltz",     op_cond (1, 0), op_cond(0x3f, 0x1f),            "s,b", 1},
+  {"bgez",     op_cond (1, 1), op_cond(0x3f, 0x1f),            "s,b", 1},
+  {"bltzal",   op_cond (1, 16),op_cond(0x3f, 0x1f),            "s,b", 1},
+  {"bgezal",   op_cond (1, 17),op_cond(0x3f, 0x1f),            "s,b", 1},
+
+
+  {"j",                one(2),         one(0x3f),                      "a", 1},
+  {"jal",      one(3),         one(0x3f),                      "a", 1},
+  {"beq",      one(4),         one(0x3f),                      "s,t,b", 1},
+  {"bne",      one(5),         one(0x3f),                      "s,t,b", 1},
+  {"blez",     one(6),         one(0x3f) | 0x1f0000,           "s,b", 1},
+  {"bgtz",     one(7),         one(0x3f) | 0x1f0000,           "s,b", 1},
+  {"addi",     one(8),         one(0x3f),                      "t,s,j", 0},
+  {"addiu",    one(9),         one(0x3f),                      "t,s,j", 0},
+  {"slti",     one(10),        one(0x3f),                      "t,s,j", 0},
+  {"sltiu",    one(11),        one(0x3f),                      "t,s,j", 0},
+  {"andi",     one(12),        one(0x3f),                      "t,s,i", 0},
+  {"ori",      one(13),        one(0x3f),                      "t,s,i", 0},
+  {"xori",     one(14),        one(0x3f),                      "t,s,i", 0},
+       /* rs field is don't care field? */
+  {"lui",      one(15),        one(0x3f),                      "t,i", 0},
+
+/* co processor 0 instruction */
+  {"mfc0",     op_rs_b11 (16, 0, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"cfc0",     op_rs_b11 (16, 2, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"mtc0",     op_rs_b11 (16, 4, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"ctc0",     op_rs_b11 (16, 6, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+
+  {"bc0f",     op_o16(16, 0x100),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc0f",     op_o16(16, 0x180),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc0t",     op_o16(16, 0x101),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc0t",     op_o16(16, 0x181),      op_o16(0x3f, 0x3ff),    "b", 1},
+
+  {"tlbr",     op_rs_func(16, 0x10, 1), ~0, "", 0},
+  {"tlbwi",    op_rs_func(16, 0x10, 2), ~0, "", 0},
+  {"tlbwr",    op_rs_func(16, 0x10, 6), ~0, "", 0},
+  {"tlbp",     op_rs_func(16, 0x10, 8), ~0, "", 0},
+  {"rfe",      op_rs_func(16, 0x10, 16), ~0, "", 0},
+
+  {"mfc1",     op_rs_b11 (17, 0, 0),   op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+  {"cfc1",     op_rs_b11 (17, 2, 0),   op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+  {"mtc1",     op_rs_b11 (17, 4, 0),   op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+  {"ctc1",     op_rs_b11 (17, 6, 0),   op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+
+  {"bc1f",     op_o16(17, 0x100),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc1f",     op_o16(17, 0x180),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc1t",     op_o16(17, 0x101),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc1t",     op_o16(17, 0x181),      op_o16(0x3f, 0x3ff),    "b", 1},
+
+/* fpu instruction */
+  {"add.s",    op_rs_func(17, 0x10, 0),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"add.d",    op_rs_func(17, 0x11, 0),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"sub.s",    op_rs_func(17, 0x10, 1),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"sub.d",    op_rs_func(17, 0x11, 1),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"mul.s",    op_rs_func(17, 0x10, 2),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"mul.d",    op_rs_func(17, 0x11, 2),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"div.s",    op_rs_func(17, 0x10, 3),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"div.d",    op_rs_func(17, 0x11, 3),
+                       op_rs_func(0x3f, 0x1f, 0x3f),   "D,S,T", 0},
+  {"abs.s",    op_rs_func(17, 0x10, 5),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"abs.d",    op_rs_func(17, 0x11, 5),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"mov.s",    op_rs_func(17, 0x10, 6),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"mov.d",    op_rs_func(17, 0x11, 6),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"neg.s",    op_rs_func(17, 0x10, 7),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"neg.d",    op_rs_func(17, 0x11, 7),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.s.s",  op_rs_func(17, 0x10, 32),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.s.d",  op_rs_func(17, 0x11, 32),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.s.w",  op_rs_func(17, 0x14, 32),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.d.s",  op_rs_func(17, 0x10, 33),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.d.d",  op_rs_func(17, 0x11, 33),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.d.w",  op_rs_func(17, 0x14, 33),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.w.s",  op_rs_func(17, 0x10, 36),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"cvt.w.d",  op_rs_func(17, 0x11, 36),
+                       op_rs_func(0x3f, 0x1f, 0x1f003f),       "D,S", 0},
+  {"c.f.s",    op_rs_func(17, 0x10, 48),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.f.d",    op_rs_func(17, 0x11, 48),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.un.s",   op_rs_func(17, 0x10, 49),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.un.d",   op_rs_func(17, 0x11, 49),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.eq.s",   op_rs_func(17, 0x10, 50),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.eq.d",   op_rs_func(17, 0x11, 50),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ueq.s",  op_rs_func(17, 0x10, 51),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ueq.d",  op_rs_func(17, 0x11, 51),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.olt.s",  op_rs_func(17, 0x10, 52),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.olt.d",  op_rs_func(17, 0x11, 52),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ult.s",  op_rs_func(17, 0x10, 53),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ult.d",  op_rs_func(17, 0x11, 53),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ole.s",  op_rs_func(17, 0x10, 54),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ole.d",  op_rs_func(17, 0x11, 54),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ule.s",  op_rs_func(17, 0x10, 55),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ule.d",  op_rs_func(17, 0x11, 55),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.sf.s",   op_rs_func(17, 0x10, 56),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.sf.d",   op_rs_func(17, 0x11, 56),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ngle.s", op_rs_func(17, 0x10, 57),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ngle.d", op_rs_func(17, 0x11, 57),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.seq.s",  op_rs_func(17, 0x10, 58),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.seq.d",  op_rs_func(17, 0x11, 58),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ngl.s",  op_rs_func(17, 0x10, 59),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ngl.d",  op_rs_func(17, 0x11, 59),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.lt.s",   op_rs_func(17, 0x10, 60),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.lt.d",   op_rs_func(17, 0x11, 60),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.nge.s",  op_rs_func(17, 0x10, 61),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.nge.d",  op_rs_func(17, 0x11, 61),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.le.s",   op_rs_func(17, 0x10, 62),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.le.d",   op_rs_func(17, 0x11, 62),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ngt.s",  op_rs_func(17, 0x10, 63),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+  {"c.ngt.d",  op_rs_func(17, 0x11, 63),
+                       op_rs_func(0x3f, 0x1f, 0x7ff),  "S,T", 0},
+
+/* co processor 2 instruction */
+  {"mfc2",     op_rs_b11 (18, 0, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"cfc2",     op_rs_b11 (18, 2, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"mtc2",     op_rs_b11 (18, 4, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"ctc2",     op_rs_b11 (18, 6, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"bc2f",     op_o16(18, 0x100),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc2f",     op_o16(18, 0x180),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc2f",     op_o16(18, 0x101),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc2t",     op_o16(18, 0x181),      op_o16(0x3f, 0x3ff),    "b", 1},
+
+/* co processor 3 instruction */
+  {"mtc3",     op_rs_b11 (19, 0, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"cfc3",     op_rs_b11 (19, 2, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"mtc3",     op_rs_b11 (19, 4, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"ctc3",     op_rs_b11 (19, 6, 0),   op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+  {"bc3f",     op_o16(19, 0x100),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc3f",     op_o16(19, 0x180),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc3t",     op_o16(19, 0x101),      op_o16(0x3f, 0x3ff),    "b", 1},
+  {"bc3t",     op_o16(19, 0x181),      op_o16(0x3f, 0x3ff),    "b", 1},
+
+  {"lb",       one(32),        one(0x3f),              "t,j(s)", 0},
+  {"lh",       one(33),        one(0x3f),              "t,j(s)", 0},
+  {"lwl",      one(34),        one(0x3f),              "t,j(s)", 0},
+  {"lw",       one(35),        one(0x3f),              "t,j(s)", 0},
+  {"lbu",      one(36),        one(0x3f),              "t,j(s)", 0},
+  {"lhu",      one(37),        one(0x3f),              "t,j(s)", 0},
+  {"lwr",      one(38),        one(0x3f),              "t,j(s)", 0},
+  {"sb",       one(40),        one(0x3f),              "t,j(s)", 0},
+  {"sh",       one(41),        one(0x3f),              "t,j(s)", 0},
+  {"swl",      one(42),        one(0x3f),              "t,j(s)", 0},
+  {"swr",       one(46),        one(0x3f),              "t,j(s)", 0},
+  {"sw",       one(43),        one(0x3f),              "t,j(s)", 0},
+  {"lwc0",     one(48),        one(0x3f),              "t,j(s)", 0},
+/* for fpu */
+  {"lwc1",     one(49),        one(0x3f),              "T,j(s)", 0},
+  {"lwc2",     one(50),        one(0x3f),              "t,j(s)", 0},
+  {"lwc3",     one(51),        one(0x3f),              "t,j(s)", 0},
+  {"swc0",     one(56),        one(0x3f),              "t,j(s)", 0},
+/* for fpu */
+  {"swc1",     one(57),        one(0x3f),              "T,j(s)", 0},
+  {"swc2",     one(58),        one(0x3f),              "t,j(s)", 0},
+  {"swc3",     one(59),        one(0x3f),              "t,j(s)", 0},
+};
diff --git a/gdb/mips-pinsn.c b/gdb/mips-pinsn.c
new file mode 100644 (file)
index 0000000..b348339
--- /dev/null
@@ -0,0 +1,149 @@
+/* Print mips instructions for GDB, the GNU debugger.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+   Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp)
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "mips-opcode.h"
+
+/* Mips instructions are never longer than this many bytes.  */
+#define MAXLEN 4
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof mips_opcodes / sizeof mips_opcodes[0])
+
+#define MKLONG(p)  *(unsigned long*)p
+
+extern char *reg_names[];
+
+\f
+/* subroutine */
+static unsigned char *
+print_insn_arg (d, l, stream, pc)
+     char *d;
+     register unsigned long int *l;
+     FILE *stream;
+     CORE_ADDR pc;
+{
+  switch (*d)
+    {
+    case ',':
+    case '(':
+    case ')':
+      fputc (*d, stream);
+      break;
+
+    case 's':
+      fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rs]);
+      break;
+
+    case 't':
+      fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rt]);
+      break;
+
+    case 'i':
+      fprintf (stream, "%d", ((struct op_i_fmt *) l)->immediate);
+      break;
+
+    case 'j': /* same as i, but sign-extended */
+      fprintf (stream, "%d", ((struct op_b_fmt *) l)->delta);
+      break;
+
+    case 'a':
+      print_address ((pc & 0xF0000000) | (((struct op_j_fmt *)l)->target << 2),
+                    stream);
+      break;
+
+    case 'b':
+      print_address ((((struct op_b_fmt *) l)->delta << 2) + pc + 4, stream);
+      break;
+
+    case 'd':
+      fprintf (stream, "%s", reg_names[((struct op_r_fmt *) l)->rd]);
+      break;
+
+    case 'h':
+      fprintf (stream, "0x%x", ((struct op_r_fmt *) l)->shamt);
+      break;
+
+    case 'S':
+      fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fs);
+      break;
+
+    case 'T':
+      fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->ft);
+      break;
+
+    case 'D':
+      fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fd);
+      break;
+
+    default:
+      fprintf (stream, "# internal error, undefined modifier(%c)", *d);
+      break;
+    }
+}
+\f
+/* Print the mips instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes, which
+   is always 4.  */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  unsigned char buffer[MAXLEN];
+  register int i;
+  register char *d;
+  unsigned long int l;
+
+  read_memory (memaddr, buffer, MAXLEN);
+
+  for (i = 0; i < NOPCODES; i++)
+    {
+      register unsigned int opcode = mips_opcodes[i].opcode;
+      register unsigned int match = mips_opcodes[i].match;
+      if ((*(unsigned int*)buffer & match) == opcode)
+       break;
+    }
+
+  l = MKLONG (buffer);
+  /* Handle undefined instructions.  */
+  if (i == NOPCODES)
+    {
+      fprintf (stream, "0x%x",l);
+      return 4;
+    }
+
+  fprintf (stream, "%s", mips_opcodes[i].name);
+
+  if (!(d = mips_opcodes[i].args))
+    return 4;
+
+  fputc (' ', stream);
+
+  while (*d)
+    print_insn_arg (d++, &l, stream, memaddr);
+
+  return 4;
+}
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
new file mode 100644 (file)
index 0000000..abdd206
--- /dev/null
@@ -0,0 +1,679 @@
+/* Work with core dump and executable files, for GDB on MIPS. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+/* Low level interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1988, 1989, 1990  Free Software Foundation, Inc.
+   Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* FIXME: Can a MIPS porter/tester determine which of these include
+   files we still need?   -- gnu@cygnus.com */
+#include <stdio.h>
+#include <mips/inst.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcmd.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#include "gdbcore.h"
+
+#ifndef        MIPSMAGIC
+#ifdef MIPSEL
+#define MIPSMAGIC      MIPSELMAGIC
+#else
+#define MIPSMAGIC      MIPSEBMAGIC
+#endif
+#endif
+
+#define VM_MIN_ADDRESS (unsigned)0x400000
+
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+\f
+#define PROC_LOW_ADDR(proc) ((proc)->adr) /* least address */
+#define PROC_HIGH_ADDR(proc) ((proc)->pad2) /* upper address bound */
+#define PROC_FRAME_OFFSET(proc) ((proc)->framesize)
+#define PROC_FRAME_REG(proc) ((proc)->framereg)
+#define PROC_REG_MASK(proc) ((proc)->regmask)
+#define PROC_FREG_MASK(proc) ((proc)->fregmask)
+#define PROC_REG_OFFSET(proc) ((proc)->regoffset)
+#define PROC_FREG_OFFSET(proc) ((proc)->fregoffset)
+#define PROC_PC_REG(proc) ((proc)->pcreg)
+#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->isym)
+#define _PROC_MAGIC_ 0x0F0F0F0F
+#define PROC_DESC_IS_DUMMY(proc) ((proc)->isym == _PROC_MAGIC_)
+#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->isym = _PROC_MAGIC_)
+
+struct linked_proc_info
+{
+  struct mips_extra_func_info info;
+  struct linked_proc_info *next;
+} * linked_proc_desc_table = NULL;
+
+\f
+#define READ_FRAME_REG(fi, regno) read_next_frame_reg((fi)->next, regno)
+
+int
+read_next_frame_reg(fi, regno)
+     FRAME fi;
+     int regno;
+{
+#define SIGFRAME_BASE   sizeof(struct sigcontext)
+#define SIGFRAME_PC_OFF (-SIGFRAME_BASE+ 2*sizeof(int))
+#define SIGFRAME_SP_OFF (-SIGFRAME_BASE+32*sizeof(int))
+#define SIGFRAME_RA_OFF (-SIGFRAME_BASE+34*sizeof(int))
+  for (; fi; fi = fi->next)
+      if (in_sigtramp(fi->pc, 0)) {
+         /* No idea if this code works. --PB. */
+         int offset;
+         if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF;
+         else if (regno == RA_REGNUM) offset = SIGFRAME_RA_OFF;
+         else if (regno == SP_REGNUM) offset = SIGFRAME_SP_OFF;
+         else return 0;
+         return read_memory_integer(fi->frame + offset, 4);
+      }
+      else if (regno == SP_REGNUM) return fi->frame;
+      else if (fi->saved_regs->regs[regno])
+       return read_memory_integer(fi->saved_regs->regs[regno], 4);
+  return read_register(regno);
+}
+
+int
+mips_frame_saved_pc(frame)
+     FRAME frame;
+{
+  mips_extra_func_info_t proc_desc = (mips_extra_func_info_t)frame->proc_desc;
+  int pcreg = proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM;
+  if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+      return read_memory_integer(frame->frame - 4, 4);
+#if 0
+  /* If in the procedure prologue, RA_REGNUM might not have been saved yet.
+   * Assume non-leaf functions start with:
+   *   addiu $sp,$sp,-frame_size
+   *   sw $ra,ra_offset($sp)
+   * This if the pc is pointing at either of these instructions,
+   * then $ra hasn't been trashed.
+   * If the pc has advanced beyond these two instructions,
+   * then $ra has been saved.
+   * critical, and much more complex. Handling $ra is enough to get
+   * a stack trace, but some register values with be wrong.
+   */
+  if (frame->proc_desc && frame->pc < PROC_LOW_ADDR(proc_desc) + 8)
+      return read_register(pcreg);
+#endif
+  return read_next_frame_reg(frame, pcreg);
+}
+
+static struct mips_extra_func_info temp_proc_desc;
+static struct frame_saved_regs temp_saved_regs;
+
+CORE_ADDR heuristic_proc_start(pc)
+    CORE_ADDR pc;
+{
+
+    CORE_ADDR start_pc = pc;
+    CORE_ADDR fence = start_pc - 10000;
+    if (fence < VM_MIN_ADDRESS) fence = VM_MIN_ADDRESS;
+    /* search back for previous return */
+    for (start_pc -= 4; ; start_pc -= 4)
+       if (start_pc < fence) return 0; 
+       else if (ABOUT_TO_RETURN(start_pc))
+           break;
+
+    start_pc += 8; /* skip return, and its delay slot */
+#if 0
+    /* skip nops (usually 1) 0 - is this */
+    while (start_pc < pc && read_memory_integer (start_pc, 4) == 0)
+       start_pc += 4;
+#endif
+    return start_pc;
+}
+
+mips_extra_func_info_t
+heuristic_proc_desc(start_pc, limit_pc, next_frame)
+    CORE_ADDR start_pc, limit_pc;
+    FRAME next_frame;
+{
+    CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
+    CORE_ADDR cur_pc;
+    int frame_size;
+    int has_frame_reg = 0;
+    int reg30; /* Value of $r30. Used by gcc for frame-pointer */
+    unsigned long reg_mask = 0;
+
+    if (start_pc == 0) return NULL;
+    bzero(&temp_proc_desc, sizeof(temp_proc_desc));
+    bzero(&temp_saved_regs, sizeof(struct frame_saved_regs));
+    if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200;
+  restart:
+    frame_size = 0;
+    for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {
+       unsigned long word;
+       int status;
+
+       status = read_memory_nobpt (cur_pc, &word, 4); 
+       if (status) memory_error (status, cur_pc); 
+       if ((word & 0xFFFF0000) == 0x27bd0000) /* addiu $sp,$sp,-i */
+           frame_size += (-word) & 0xFFFF;
+       else if ((word & 0xFFFF0000) == 0x23bd0000) /* addu $sp,$sp,-i */
+           frame_size += (-word) & 0xFFFF;
+       else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp) */
+           int reg = (word & 0x001F0000) >> 16;
+           reg_mask |= 1 << reg;
+           temp_saved_regs.regs[reg] = sp + (short)word;
+       }
+       else if ((word & 0xFFFF0000) == 0x27be0000) { /* addiu $30,$sp,size */
+           if ((unsigned short)word != frame_size)
+               reg30 = sp + (unsigned short)word;
+           else if (!has_frame_reg) {
+               int alloca_adjust;
+               has_frame_reg = 1;
+               reg30 = read_next_frame_reg(next_frame, 30);
+               alloca_adjust = reg30 - (sp + (unsigned short)word);
+               if (alloca_adjust > 0) {
+                   /* FP > SP + frame_size. This may be because
+                   /* of an alloca or somethings similar.
+                    * Fix sp to "pre-alloca" value, and try again.
+                    */
+                   sp += alloca_adjust;
+                   goto restart;
+               }
+           }
+       }
+       else if ((word & 0xFFE00000) == 0xafc00000) { /* sw reg,offset($30) */
+           int reg = (word & 0x001F0000) >> 16;
+           reg_mask |= 1 << reg;
+           temp_saved_regs.regs[reg] = reg30 + (short)word;
+       }
+    }
+    if (has_frame_reg) {
+       PROC_FRAME_REG(&temp_proc_desc) = 30;
+       PROC_FRAME_OFFSET(&temp_proc_desc) = 0;
+    }
+    else {
+       PROC_FRAME_REG(&temp_proc_desc) = SP_REGNUM;
+       PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;
+    }
+    PROC_REG_MASK(&temp_proc_desc) = reg_mask;
+    PROC_PC_REG(&temp_proc_desc) = RA_REGNUM;
+    return &temp_proc_desc;
+}
+
+mips_extra_func_info_t
+find_proc_desc(pc, next_frame)
+    CORE_ADDR pc;
+    FRAME next_frame;
+{
+  mips_extra_func_info_t proc_desc;
+  extern struct block *block_for_pc();
+  struct block   *b = block_for_pc(pc);
+
+  struct symbol *sym =
+      b ? lookup_symbol(".gdbinfo.", b, LABEL_NAMESPACE, 0, NULL) : NULL;
+  if (sym != NULL)
+    {
+       /* IF this is the topmost frame AND
+        * (this proc does not have debugging information OR
+        * the PC is in the procedure prologue)
+        * THEN create a "hueristic" proc_desc (by analyzing
+        * the actual code) to replace the "official" proc_desc.
+        */
+       proc_desc = (struct mips_extra_func_info *)sym->value.value;
+       if (next_frame == NULL) {
+           struct symtab_and_line val;
+           struct symbol *proc_symbol =
+               PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc);
+           if (proc_symbol) {
+               val = find_pc_line (BLOCK_START
+                                   (SYMBOL_BLOCK_VALUE(proc_symbol)),
+                                   0);
+               val.pc = val.end ? val.end : pc;
+           }
+           if (!proc_symbol || pc < val.pc) {
+               mips_extra_func_info_t found_heuristic =
+                   heuristic_proc_desc(PROC_LOW_ADDR(proc_desc),
+                                       pc, next_frame);
+               if (found_heuristic) proc_desc = found_heuristic;
+           }
+       }
+    }
+  else
+    {
+      register struct linked_proc_info *link;
+      for (link = linked_proc_desc_table; link; link = link->next)
+         if (PROC_LOW_ADDR(&link->info) <= pc
+             && PROC_HIGH_ADDR(&link->info) > pc)
+             return &link->info;
+      proc_desc =
+         heuristic_proc_desc(heuristic_proc_start(pc), pc, next_frame);
+    }
+  return proc_desc;
+}
+
+mips_extra_func_info_t cached_proc_desc;
+
+FRAME_ADDR mips_frame_chain(frame)
+    FRAME frame;
+{
+    extern CORE_ADDR startup_file_start;       /* From blockframe.c */
+    mips_extra_func_info_t proc_desc;
+    CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
+    if (startup_file_start)
+      { /* has at least the __start symbol */
+       if (saved_pc == 0 || !outside_startup_file (saved_pc)) return 0;
+      }
+    else
+      { /* This hack depends on the internals of __start. */
+       /* We also assume the breakpoints are *not* inserted */
+        if (read_memory_integer (saved_pc + 8, 4) & 0xFC00003F == 0xD)
+           return 0;  /* break */
+      }
+    proc_desc = find_proc_desc(saved_pc, frame);
+    if (!proc_desc) return 0;
+    cached_proc_desc = proc_desc;
+    return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
+       + PROC_FRAME_OFFSET(proc_desc);
+}
+
+void
+init_extra_frame_info(fci)
+     struct frame_info *fci;
+{
+  extern struct obstack frame_cache_obstack;
+  /* Use proc_desc calculated in frame_chain */
+  mips_extra_func_info_t proc_desc = fci->next ? cached_proc_desc :
+      find_proc_desc(fci->pc, fci->next);
+  fci->saved_regs = (struct frame_saved_regs*)
+    obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
+  bzero(fci->saved_regs, sizeof(struct frame_saved_regs));
+  fci->proc_desc =
+      proc_desc == &temp_proc_desc ? (char*)NULL : (char*)proc_desc;
+  if (proc_desc)
+    {
+      int ireg;
+      CORE_ADDR reg_position;
+      unsigned long mask;
+      /* r0 bit means kernel trap */
+      int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
+
+      /* Fixup frame-pointer - only needed for top frame */
+      /* This may not be quite right, if procedure has a real frame register */
+      if (fci->pc == PROC_LOW_ADDR(proc_desc))
+         fci->frame = read_register (SP_REGNUM);
+      else
+         fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
+             + PROC_FRAME_OFFSET(proc_desc);
+
+      if (proc_desc == &temp_proc_desc)
+         *fci->saved_regs = temp_saved_regs;
+      else
+      {
+         /* find which general-purpose registers were saved */
+         reg_position = fci->frame + PROC_REG_OFFSET(proc_desc);
+         mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
+         for (ireg= 31; mask; --ireg, mask <<= 1)
+             if (mask & 0x80000000)
+             {
+                 fci->saved_regs->regs[ireg] = reg_position;
+                 reg_position -= 4;
+             }
+         /* find which floating-point registers were saved */
+         reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc);
+         /* The freg_offset points to where the first *double* register is saved.
+          * So skip to the high-order word. */
+         reg_position += 4;
+         mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
+         for (ireg = 31; mask; --ireg, mask <<= 1)
+             if (mask & 0x80000000)
+             {
+                 fci->saved_regs->regs[32+ireg] = reg_position;
+                 reg_position -= 4;
+             }
+      }
+
+      /* hack: if argument regs are saved, guess these contain args */
+      if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
+      else if ((PROC_REG_MASK(proc_desc) & 0x80) == 0) fci->num_args = 4;
+      else if ((PROC_REG_MASK(proc_desc) & 0x40) == 0) fci->num_args = 3;
+      else if ((PROC_REG_MASK(proc_desc) & 0x20) == 0) fci->num_args = 2;
+      else if ((PROC_REG_MASK(proc_desc) & 0x10) == 0) fci->num_args = 1;
+
+      fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];
+    }
+  if (fci->next == 0)
+      supply_register(FP_REGNUM, &fci->frame);
+}
+
+
+CORE_ADDR mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
+  int nargs;
+  value *args;
+  CORE_ADDR sp;
+  int struct_return;
+  CORE_ADDR struct_addr;
+{
+  CORE_ADDR buf;
+  register i;
+  int accumulate_size = struct_return ? 4 : 0;
+  struct mips_arg { char *contents; int len; int offset; };
+  struct mips_arg *mips_args =
+      (struct mips_arg*)alloca(nargs * sizeof(struct mips_arg));
+  register struct mips_arg *m_arg;
+  for (i = 0, m_arg = mips_args; i < nargs; i++, m_arg++) {
+    extern value value_arg_coerce();
+    value arg = value_arg_coerce (args[i]);
+    m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg));
+    /* This entire mips-specific routine is because doubles must be aligned
+     * on 8-byte boundaries. It still isn't quite right, because MIPS decided
+     * to align 'struct {int a, b}' on 4-byte boundaries (even though this
+     * breaks their varargs implementation...). A correct solution
+     * requires an simulation of gcc's 'alignof' (and use of 'alignof'
+     * in stdarg.h/varargs.h).
+     */
+    if (m_arg->len > 4) accumulate_size = (accumulate_size + 7) & -8;
+    m_arg->offset = accumulate_size;
+    accumulate_size = (accumulate_size + m_arg->len + 3) & -4;
+    m_arg->contents = VALUE_CONTENTS(arg);
+  }
+  accumulate_size = (accumulate_size + 7) & (-8);
+  if (accumulate_size < 16) accumulate_size = 16; 
+  sp -= accumulate_size;
+  for (i = nargs; m_arg--, --i >= 0; )
+    write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
+  if (struct_return) {
+    buf = struct_addr;
+    write_memory(sp, &buf, sizeof(CORE_ADDR));
+}
+  return sp;
+}
+
+/* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */
+#define MASK(i,j) ((1 << (j)+1)-1 ^ (1 << (i))-1)
+
+void
+mips_push_dummy_frame()
+{
+  int ireg;
+  struct linked_proc_info *link = (struct linked_proc_info*)
+      xmalloc(sizeof(struct linked_proc_info));
+  mips_extra_func_info_t proc_desc = &link->info;
+  CORE_ADDR sp = read_register (SP_REGNUM);
+  CORE_ADDR save_address;
+  REGISTER_TYPE buffer;
+  link->next = linked_proc_desc_table;
+  linked_proc_desc_table = link;
+#define PUSH_FP_REGNUM 16 /* must be a register preserved across calls */
+#define GEN_REG_SAVE_MASK MASK(1,16)|MASK(24,28)|(1<<31)
+#define GEN_REG_SAVE_COUNT 22
+#define FLOAT_REG_SAVE_MASK MASK(0,19)
+#define FLOAT_REG_SAVE_COUNT 20
+#define SPECIAL_REG_SAVE_COUNT 4
+  /*
+   * The registers we must save are all those not preserved across
+   * procedure calls. Dest_Reg (see tm-mips.h) must also be saved.
+   * In addition, we must save the PC, and PUSH_FP_REGNUM.
+   * (Ideally, we should also save MDLO/-HI and FP Control/Status reg.)
+   *
+   * Dummy frame layout:
+   *  (high memory)
+   *   Saved PC
+   *   Saved MMHI, MMLO, FPC_CSR
+   *   Saved R31
+   *   Saved R28
+   *   ...
+   *   Saved R1
+   *    Saved D18 (i.e. F19, F18)
+   *    ...
+   *    Saved D0 (i.e. F1, F0)
+   *   CALL_DUMMY (subroutine stub; see m-mips.h)
+   *   Parameter build area (not yet implemented)
+   *  (low memory)
+   */
+  PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
+  PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;
+  PROC_REG_OFFSET(proc_desc) = /* offset of (Saved R31) from FP */
+      -sizeof(long) - 4 * SPECIAL_REG_SAVE_COUNT;
+  PROC_FREG_OFFSET(proc_desc) = /* offset of (Saved D18) from FP */
+      -sizeof(double) - 4 * (SPECIAL_REG_SAVE_COUNT + GEN_REG_SAVE_COUNT);
+  /* save general registers */
+  save_address = sp + PROC_REG_OFFSET(proc_desc);
+  for (ireg = 32; --ireg >= 0; )
+    if (PROC_REG_MASK(proc_desc) & (1 << ireg))
+      {
+       buffer = read_register (ireg);
+       write_memory (save_address, &buffer, sizeof(REGISTER_TYPE));
+       save_address -= 4;
+      }
+  /* save floating-points registers */
+  save_address = sp + PROC_FREG_OFFSET(proc_desc);
+  for (ireg = 32; --ireg >= 0; )
+    if (PROC_FREG_MASK(proc_desc) & (1 << ireg))
+      {
+       buffer = read_register (ireg);
+       write_memory (save_address, &buffer, 4);
+       save_address -= 4;
+      }
+  write_register (PUSH_FP_REGNUM, sp);
+  PROC_FRAME_REG(proc_desc) = PUSH_FP_REGNUM;
+  PROC_FRAME_OFFSET(proc_desc) = 0;
+  buffer = read_register (PC_REGNUM);
+  write_memory (sp - 4, &buffer, sizeof(REGISTER_TYPE));
+  buffer = read_register (HI_REGNUM);
+  write_memory (sp - 8, &buffer, sizeof(REGISTER_TYPE));
+  buffer = read_register (LO_REGNUM);
+  write_memory (sp - 12, &buffer, sizeof(REGISTER_TYPE));
+  buffer = read_register (FCRCS_REGNUM);
+  write_memory (sp - 16, &buffer, sizeof(REGISTER_TYPE));
+  sp -= 4 * (GEN_REG_SAVE_COUNT+FLOAT_REG_SAVE_COUNT+SPECIAL_REG_SAVE_COUNT);
+  write_register (SP_REGNUM, sp);
+  PROC_LOW_ADDR(proc_desc) = sp - CALL_DUMMY_SIZE + CALL_DUMMY_START_OFFSET;
+  PROC_HIGH_ADDR(proc_desc) = sp;
+  SET_PROC_DESC_IS_DUMMY(proc_desc);
+  PROC_PC_REG(proc_desc) = RA_REGNUM;
+}
+
+void
+mips_pop_frame()
+{ register int regnum;
+  FRAME frame = get_current_frame ();
+  CORE_ADDR new_sp = frame->frame;
+  mips_extra_func_info_t proc_desc = (mips_extra_func_info_t)frame->proc_desc;
+  if (PROC_DESC_IS_DUMMY(proc_desc))
+    {
+      struct linked_proc_info **ptr = &linked_proc_desc_table;;
+      for (; &ptr[0]->info != proc_desc; ptr = &ptr[0]->next )
+         if (ptr[0] == NULL) abort();
+      *ptr = ptr[0]->next;
+      free (ptr[0]);
+      write_register (HI_REGNUM, read_memory_integer(new_sp - 8, 4));
+      write_register (LO_REGNUM, read_memory_integer(new_sp - 12, 4));
+      write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16, 4));
+    }
+  write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
+  if (frame->proc_desc) {
+    for (regnum = 32; --regnum >= 0; )
+      if (PROC_REG_MASK(proc_desc) & (1 << regnum))
+       write_register (regnum,
+                 read_memory_integer (frame->saved_regs->regs[regnum], 4));
+    for (regnum = 64; --regnum >= 32; )
+      if (PROC_FREG_MASK(proc_desc) & (1 << regnum))
+       write_register (regnum,
+                 read_memory_integer (frame->saved_regs->regs[regnum], 4));
+  }
+  write_register (SP_REGNUM, new_sp);
+  flush_cached_frames ();
+  set_current_frame (create_new_frame (new_sp, read_pc ()));
+}
+
+static mips_print_register(regnum, all)
+     int regnum, all;
+{
+      unsigned char raw_buffer[8];
+      REGISTER_TYPE val;
+
+      read_relative_register_raw_bytes (regnum, raw_buffer);
+
+      if (!(regnum & 1) && regnum >= FP0_REGNUM && regnum < FP0_REGNUM+32) {
+         read_relative_register_raw_bytes (regnum+1, raw_buffer+4);
+         printf_filtered ("(d%d: ", regnum&31);
+         val_print (builtin_type_double, raw_buffer, 0,
+                    stdout, 0, 1, 0, Val_pretty_default);
+         printf_filtered ("); ", regnum&31);
+      }
+      fputs_filtered (reg_names[regnum], stdout);
+#ifndef NUMERIC_REG_NAMES
+      if (regnum < 32)
+         printf_filtered ("(r%d): ", regnum);
+      else
+#endif
+         printf_filtered (": ");
+
+      /* If virtual format is floating, print it that way.  */
+      if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
+         && ! INVALID_FLOAT (raw_buffer, REGISTER_VIRTUAL_SIZE(regnum))) {
+         val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0,
+                    stdout, 0, 1, 0, Val_pretty_default);
+      }
+      /* Else print as integer in hex.  */
+      else
+       {
+         long val;
+
+         bcopy (raw_buffer, &val, sizeof (long));
+         if (val == 0)
+           printf_filtered ("0");
+         else if (all)
+           printf_filtered ("0x%x", val);
+         else
+           printf_filtered ("0x%x=%d", val, val);
+       }
+}
+
+mips_do_registers_info(regnum)
+     int regnum;
+{
+  if (regnum != -1) {
+      mips_print_register (regnum, 0);
+      printf_filtered ("\n");
+  }
+  else {
+      for (regnum = 0; regnum < NUM_REGS; ) {
+         mips_print_register (regnum, 1);
+         regnum++;
+         if ((regnum & 3) == 0 || regnum == NUM_REGS)
+             printf_filtered (";\n");
+         else
+             printf_filtered ("; ");
+      }
+  }
+}
+/* Return number of args passed to a frame. described by FIP.
+   Can return -1, meaning no way to tell.  */
+
+mips_frame_num_args(fip)
+       FRAME fip;
+{
+#if 0
+       struct chain_info_t *p;
+
+       p = mips_find_cached_frame(FRAME_FP(fip));
+       if (p->valid)
+               return p->the_info.numargs;
+#endif
+       return -1;
+}
+
+\f
+/* Bad floats: Returns 0 if P points to a valid IEEE floating point number,
+   1 if P points to a denormalized number or a NaN. LEN says whether this is
+   a single-precision or double-precision float */
+#define SINGLE_EXP_BITS  8
+#define DOUBLE_EXP_BITS 11
+int
+isa_NAN(p, len)
+     int *p, len;
+{
+  int exponent;
+  if (len == 4)
+    {
+      exponent = *p;
+      exponent = exponent << 1 >> (32 - SINGLE_EXP_BITS - 1);
+      return ((exponent == -1) || (! exponent && *p));
+    }
+  else if (len == 8)
+    {
+      exponent = *(p+1);
+      exponent = exponent << 1 >> (32 - DOUBLE_EXP_BITS - 1);
+      return ((exponent == -1) || (! exponent && *p * *(p+1)));
+    }
+  else return 1;
+}
+
+/* To skip prologues, I use this predicate. Returns either PC
+   itself if the code at PC does not look like a function prologue,
+   PC+4 if it does (our caller does not need anything more fancy). */
+
+CORE_ADDR mips_skip_prologue(pc)
+     CORE_ADDR pc;
+{
+    struct symbol *f;
+    struct block *b;
+    unsigned long inst;
+
+    /* For -g modules and most functions anyways the
+       first instruction adjusts the stack. */
+    inst = read_memory_integer(pc, 4);
+    if ((inst & 0xffff0000) == 0x27bd0000)
+       return pc + 4;
+
+    /* Well, it looks like a frameless. Let's make sure.
+       Note that we are not called on the current PC,
+       but on the function`s start PC, and I have definitely
+       seen optimized code that adjusts the SP quite later */
+    b = block_for_pc(pc);
+    if (!b) return pc;
+
+    f = lookup_symbol(".gdbinfo.", b, LABEL_NAMESPACE, 0, NULL);
+    if (!f) return pc;
+    /* Ideally, I would like to use the adjusted info
+       from mips_frame_info(), but for all practical
+       purposes it will not matter (and it would require
+       a different definition of SKIP_PROLOGUE())
+
+       Actually, it would not hurt to skip the storing
+       of arguments on the stack as well. */
+    if (((struct mips_extra_func_info *)f->value.value)->framesize)
+       return pc + 4;
+
+    return pc;
+}
diff --git a/gdb/mips-xdep.c b/gdb/mips-xdep.c
new file mode 100644 (file)
index 0000000..7748f1c
--- /dev/null
@@ -0,0 +1,132 @@
+/* Low level MIPS interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+   Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <mips/inst.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h>  Can we live without this?  */
+
+#include "gdbcore.h"
+
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* Get all registers from the inferior */
+
+void
+fetch_inferior_registers ()
+{
+  register int regno;
+  register unsigned int regaddr;
+  char buf[MAX_REGISTER_RAW_SIZE];
+  register int i;
+
+  registers_fetched ();
+
+  for (regno = 1; regno < NUM_REGS; regno++)
+    {
+      regaddr = register_addr (regno, 1);
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+       {
+         *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
+         regaddr += sizeof (int);
+       }
+      supply_register (regno, buf);
+    }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+
+  if (regno == 0)
+    return;
+
+  if (regno > 0)
+    {
+      regaddr = register_addr (regno, 1);
+      errno = 0;
+      ptrace (6, inferior_pid, regaddr, read_register (regno));
+      if (errno != 0)
+       {
+         sprintf (buf, "writing register number %d", regno);
+         perror_with_name (buf);
+       }
+    }
+  else
+    {
+      for (regno = 1; regno < NUM_REGS; regno++)
+       {
+         if (regno == 32 || regno == 35 || regno == 36 || regno == 71)
+           continue;
+         regaddr = register_addr (regno, 1);
+         errno = 0;
+         ptrace (6, inferior_pid, regaddr, read_register (regno));
+         if (errno != 0)
+           {
+             sprintf (buf, "writing all regs, number %d", regno);
+             perror_with_name (buf);
+           }
+       }
+    }
+}
+
+void
+fetch_core_registers ()
+{
+  register int regno;
+  int val;
+
+  for (regno = 1; regno < NUM_REGS; regno++) {
+    char buf[MAX_REGISTER_RAW_SIZE];
+
+    val = bfd_seek (core_bfd, register_addr (regno, 0));
+    if (val < 0 || (val = bfd_read (core_bfd, buf, sizeof buf)) < 0) {
+      char buffer[50];
+      strcpy (buffer, "Reading register ");
+      strcat (buffer, reg_names[regno]);
+
+      perror_with_name (buffer);
+    }
+    supply_register (regno, buf);
+  }
+}
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
new file mode 100644 (file)
index 0000000..2c7112f
--- /dev/null
@@ -0,0 +1,2879 @@
+/* Read a symbol table in MIPS' format (Third-Eye).
+   Copyright (C) 1986, 1987, 1989-1991 Free Software Foundation, Inc.
+   Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "param.h"
+#include "obstack.h"
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include "defs.h"
+#include "symtab.h"
+#include "gdbcore.h"
+#include "symfile.h"
+#ifdef CMUCS
+#include <mips/syms.h>
+#endif CMUCS
+
+/* Since these things are defined differently on various systems I'll
+   (re)define here what I really need in this module.  I only assume the
+   three standard COFF structure definitions: filehdr, aouthdr, scnhdr */
+#define MIPS           /* Kludge to get MIPS version of coff */
+#include "intel-coff.h"
+
+struct coff_exec {
+       struct filehdr f;
+       struct aouthdr a;
+};
+#undef a_magic
+#undef a_text
+#undef a_data
+#undef a_bss
+#undef a_syms
+#undef a_entry
+#define a_magic        a.magic         /* magic number */
+#define a_text a.tsize         /* size of text segment */
+#define a_data a.dsize         /* size of initialized data */
+#define a_bss  a.bsize         /* size of uninitialized data */
+#define a_syms f.f_nsyms       /* size of symbol table */
+#define a_entry        a.entry         /* entry point */
+
+#undef N_BADMAG
+#define        N_BADMAG(x) \
+    (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
+
+/* Things we import explicitly from other modules */
+
+extern int          info_verbose;
+extern struct block *block_for_pc();
+extern void         sort_symtab_syms();
+
+/* Forward declarations */
+
+static void psymtab_to_symtab_1();
+
+/* Macros and extra defs */
+
+struct complaint unknown_ext_complaint = 
+       {"unknown external symbol %s", 0, 0};
+
+/* Already parsed symbols are marked specially */
+
+#define stParsed stType
+
+/* Puns: hard to find whether -g was used and how */
+
+#define MIN_GLEVEL GLEVEL_0
+#define compare_glevel(a,b)                                    \
+       (((a) == GLEVEL_3) ? ((b) < GLEVEL_3) :                 \
+        ((b) == GLEVEL_3) ? -1 : (int)((b) - (a)))
+
+/* When looking at .o files avoid tripping over bad addresses */
+
+#define SAFE_TEXT_ADDR 0x400000
+#define SAFE_DATA_ADDR 0x10000000
+
+#define UNSAFE_DATA_ADDR(p)    ((unsigned)p < SAFE_DATA_ADDR || (unsigned)p > 2*SAFE_DATA_ADDR)
+
+\f
+/* Things we export to other modules */
+
+
+/* Lists of partial symbols */
+
+struct psymbol_allocation_list global_psymbols, static_psymbols;
+
+/* Address bounds for the signal trampoline in inferior, if any */
+
+CORE_ADDR sigtramp_address, sigtramp_end;
+
+
+/* Functions that we really export */
+
+/* THIS DESCRIPTION IS OBSOLETE POST-BFD; FIXME! */
+/* Basically, this module must provide two functions: symbol_file_command()
+   which loads the symbol table from a file, and add_file_command() which
+   adds more symbols to the symbol table (incrementally).
+
+   These two functions only do the minimum work necessary for letting the
+   user "name" things symbolically, they do not read the entire symtab.
+   Instead, they read in the external symbols and put them in partial
+   symbol tables.  When more extensive information is requested of a
+   file the corresponding partial symbol table is mutated into a full
+   fledged symbol table by going back and reading the relative symbols
+   for real.  mipscoff_psymtab_to_symtab() is the function that does this */
+
+/* The entry point (starting address) of the file, if it is an executable.  */
+
+static CORE_ADDR entry_point;
+
+extern CORE_ADDR startup_file_start;   /* From blockframe.c */
+extern CORE_ADDR startup_file_end;     /* From blockframe.c */
+
+void
+mipscoff_new_init()
+{
+}
+
+void
+mipscoff_symfile_init (sf)
+     struct sym_fns *sf;
+{
+  bfd *abfd = sf->sym_bfd;
+  sf->sym_private = NULL;
+  /* Save startup file's range of PC addresses to help blockframe.c
+     decide where the bottom of the stack is.  */
+  if (bfd_get_file_flags (abfd) & EXEC_P)
+    {
+      /* Executable file -- record its entry point so we'll recognize
+        the startup file because it contains the entry point.  */
+      entry_point = bfd_get_start_address (abfd);
+    }
+  else
+    {
+      /* Examination of non-executable.o files.  Short-circuit this stuff.  */
+      /* ~0 will not be in any file, we hope.  */
+      entry_point = ~0;
+      /* set the startup file to be an empty range.  */
+      startup_file_start = 0;
+      startup_file_end = 0;
+    }
+}
+
+void
+mipscoff_symfile_read(sf, addr, mainline)
+     struct sym_fns *sf;
+     CORE_ADDR addr;
+     int mainline;
+{
+  struct coff_symfile_info *info = (struct coff_symfile_info *)sf->sym_private;
+  bfd *abfd = sf->sym_bfd;
+  char *name = bfd_get_filename (abfd);
+  int desc;
+  register int val;
+  int num_symbols;
+  int symtab_offset;
+  int stringtab_offset;
+
+/* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
+   desc = fileno ((FILE *)(abfd->iostream));   /* Raw file descriptor */
+   num_symbols = bfd_get_symcount (abfd);      /* How many syms */
+/*   symtab_offset = obj_sym_filepos (abfd);   * Symbol table file offset */
+/*   stringtab_offset = symtab_offset + num_symbols * SYMESZ;  * String tab */
+/* End of warning */
+
+#ifdef TDESC
+  debug_info = text_hdr.s_relptr;
+  if (tdesc_handle)
+    {
+       dc_terminate (tdesc_handle);
+       tdesc_handle = 0;
+    }
+#endif
+
+#if 0
+  /* Read the line number table, all at once.  */
+  info->min_lineno_offset = 0;
+  info->max_lineno_offset = 0;
+  bfd_map_over_sections (abfd, find_linenos, info);
+
+  val = init_lineno (desc, info->min_lineno_offset, 
+                    info->max_lineno_offset - info->min_lineno_offset);
+  if (val < 0)
+    error ("\"%s\": error reading line numbers\n", name);
+
+  /* Now read the string table, all at once.  */
+
+  val = init_stringtab (desc, stringtab_offset);
+  if (val < 0)
+    {
+      free_all_symtabs ();             /* FIXME blows whole symtab */
+      printf ("\"%s\": can't get string table", name);
+      fflush (stdout);
+      return;
+    }
+  make_cleanup (free_stringtab, 0);
+#endif
+  /* Position to read the symbol table.  Do not read it all at once. */
+  val = lseek (desc, (long)symtab_offset, 0);
+  if (val < 0)
+    perror_with_name (name);
+
+  init_misc_bunches ();
+  make_cleanup (discard_misc_bunches, 0);
+
+  /* Now that the executable file is positioned at symbol table,
+     process it and define symbols accordingly.  */
+
+  printf("Reading symbol data from %s...", name);
+  fflush(stdout);
+  read_mips_symtab(desc, 0);
+
+/*  patch_opaque_types ();*/
+
+  /* Sort symbols alphabetically within each block.  */
+
+  sort_all_symtab_syms ();
+
+  /* Go over the misc symbol bunches and install them in vector.  */
+
+  condense_misc_bunches (0);
+
+  /* Make a default for file to list.  */
+
+  select_source_symtab (0);    /* FIXME, this might be too slow, see dbxread */
+}  
+  
+void
+mipscoff_symfile_discard()
+{
+}
+  
+  
+#if 0
+/* Exported procedure: Reads symbols from file NAME.
+   Invoked at startup time if executable was given.
+   When invoked cleans up the world */
+
+void
+symbol_file_command(name, from_tty)
+     char *name;
+     int from_tty;
+{
+  int                  desc;
+  struct coff_exec     hdr;
+  register int         val;
+  extern void          close();
+  struct cleanup *old_chain;
+
+  dont_repeat();
+
+  /*
+   * Make sure s/he means it 
+   */
+  if (name == 0) {
+    if ((symtab_list || partial_symtab_list)
+       && from_tty
+       && !query("Discard symbol table? ", 0))
+       error("Not confirmed.");
+    destroy_all_symtabs();
+    return;
+  }
+
+  name = tilde_expand(name);
+  make_cleanup(free, name);
+
+  if (symtab_list &&
+      !query("Load new symbol table from \"%s\"? ", name))
+      error("Not confirmed.");
+
+  /* Open the file */
+  {
+    char *absolute_name;
+    desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
+    if (desc < 0)
+      perror_with_name (name);
+    else
+      name = absolute_name;
+  }
+
+  old_chain = make_cleanup (close, desc);
+  make_cleanup (free_current_contents, &name);
+
+  /*
+   * Check file is indeed executable 
+   */
+  val = myread(desc, &hdr, sizeof hdr);
+  if (val < 0)
+     perror_with_name(name);
+
+  if (N_BADMAG(hdr))
+    error("File \"%s\" not in executable format.", name);
+
+  if (hdr.a.entry < SAFE_TEXT_ADDR && access(name, 1))
+      printf_filtered("Warning: %s is not executable!\n", name);
+
+  if (hdr.a_syms == 0) {
+    printf_filtered("%s does not have a symbol-table.\n", name);
+    fflush(stdout);
+    return;
+  }
+
+  /* Get the modification time.  */
+  {
+    struct stat symstat;
+
+    if (fstat (desc, &symstat) < 0)
+      perror_with_name (name);
+
+    symfile_mtime = symstat.st_mtime;
+  }
+
+  /*
+   * Throw away the old symbol table.  
+   */
+
+  destroy_all_symtabs();
+
+  /* Make a default for file to list.  */
+
+  symfile = savestring (name, strlen (name));
+
+  /* Prepare to remember misc symbol values */
+
+  init_misc_bunches ();
+  make_cleanup (discard_misc_bunches, 0);
+
+  /*
+   * Now read the new symbol table 
+   */
+
+  read_mips_symtab(desc, 0);
+
+  /* Go over the misc symbol bunches and install them in vector.  */
+
+  condense_misc_bunches (0);
+
+  /* Don't allow char * to have a typename (else would get caddr_t.)  */
+
+  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+
+  /* Force reinit of the sigtramp info */
+  sigtramp_address = 0;
+
+  do_cleanups (old_chain);     /* Descriptor closed here */
+
+  if (!partial_symtab_list)
+    printf ("\n(no debugging symbols found)...");
+
+  printf ("done.\n");
+  fflush(stdout);
+}
+#endif
+
+/* C++:
+   This function allows the addition of incrementally linked object files.
+   Since this has a fair amount of code in common with symbol_file_command,
+   it might be worthwhile to consolidate things, as was done with
+   read_dbx_symtab and condense_misc_bunches. */
+
+/* Exported procedure: add more symbols from file NAME. */
+
+void
+add_file_command(arg_string)
+     char* arg_string;
+{
+  int                  desc;
+  struct coff_exec     hdr;
+  register int         val;
+  extern void          close();
+  struct cleanup *old_chain;
+  char *name;
+  unsigned text_addr;
+
+  if (arg_string == 0)
+    error ("add-file takes a file name and an address");
+
+  if (arg_string == 0)
+    error ("add-file takes a file name and an address");
+
+  arg_string = tilde_expand (arg_string);
+  make_cleanup (free, arg_string);
+
+  for( ; *arg_string == ' '; arg_string++ );
+  name = arg_string;
+  for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
+  *arg_string++ = (char) 0;
+
+  if (name[0] == 0)
+    error ("add-file takes a file name and an address");
+
+  text_addr = parse_and_eval_address (arg_string);
+
+  dont_repeat();
+
+  if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n",
+             name, text_addr))
+    error ("Not confirmed.");
+
+  /*
+   * Open the file 
+   */
+  {
+    char           *absolute_name;
+
+    desc = openp(getenv("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
+    if (desc < 0)
+      perror_with_name(name);
+    else
+      name = absolute_name;
+  }
+  old_chain = make_cleanup (close, desc);
+
+
+  /*
+   * Check file is indeed executable 
+   */
+  val = myread(desc, &hdr, sizeof hdr);
+  if (val < 0)
+      perror_with_name(name);
+
+  if (N_BADMAG(hdr))
+      error("File \"%s\" not in executable format.", name);
+
+  if (hdr.a.entry < SAFE_TEXT_ADDR && access(name, 1))
+      printf_filtered("Warning: %s is not executable!\n", name);
+
+  if (hdr.a_syms == 0) {
+      printf_filtered("%s does not have a symbol-table.\n", name);
+      fflush(stdout);
+      return;
+  }
+
+  if (symfile)
+      free(symfile);
+  symfile = 0;
+
+  /*
+   * Now read the new symbol table 
+   */
+
+  symfile = savestring(name, strlen(name));
+
+  init_misc_bunches ();
+  make_cleanup (discard_misc_bunches, 0);
+  read_mips_symtab(desc, 1);
+
+  /* Go over the misc symbol bunches and install them in vector.  */
+
+  condense_misc_bunches (1);
+
+  /* Don't allow char * to have a typename (else would get caddr_t.)  */
+
+  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+
+  do_cleanups (old_chain);
+
+  printf_filtered("done.\n");
+  fflush(stdout);
+}
+
+/* Exported procedure: Allocate zeroed memory */
+
+char *xzalloc(size)
+{
+       char           *p = xmalloc(size);
+
+       bzero(p, size);
+       return p;
+}
+
+/* Exported procedure: Builds a symtab from the PST partial one.
+   Restores the environment in effect when PST was created, delegates
+   most of the work to an ancillary procedure, and sorts
+   and reorders the symtab list at the end */
+
+/* Forward decls */
+static HDRR    *cur_hdr;       /* MIPS symtab header for the current file */
+
+void
+mipscoff_psymtab_to_symtab(pst)
+       struct partial_symtab *pst;
+{
+       struct symtab  *ret;
+       int             i;
+
+       if (!pst)
+               return;
+
+       if (info_verbose) {
+               printf_filtered("Reading in symbols for %s...", pst->filename);
+               fflush(stdout);
+       }
+       /* Restore the header and list of pending typedefs */
+       cur_hdr = (HDRR *) pst->ldsymlen;
+
+       psymtab_to_symtab_1(pst);
+
+       reorder_symtabs();
+
+       /* Finish up the debug error message.  */
+       if (info_verbose)
+               printf_filtered("done.\n");
+}
+
+/* Exported procedure: Is PC in the signal trampoline code */
+
+int in_sigtramp(pc,name)
+       CORE_ADDR pc;
+{
+       if (sigtramp_address == 0)
+               fixup_sigtramp();
+       return (pc >= sigtramp_address && pc < sigtramp_end);
+}
+
+\f
+/* Things that really are local to this module */
+
+/* All allocated symtabs and psymtabs */
+
+static int all_symtabs_count;
+static int all_psymtabs_count;
+
+/* GDB symtable for the current compilation unit */
+
+static struct symtab *cur_stab;
+
+/* Header for executable/object file we read symbols from */
+
+static struct coff_exec filhdr;
+#define END_OF_TEXT_SEGMENT(f) ((f).a.text_start + (f).a.tsize)
+
+/* Pointer to current file decriptor record, and its index */
+
+static FDR     *cur_fdr;
+static int      cur_fd;
+
+/* Index of current symbol */
+
+static int      cur_sdx;
+
+/* Note how much "debuggable" this image is.  We would like
+   to see at least one FDR with full symbols */
+
+static max_gdbinfo;
+static max_glevel;
+
+/* When examining .o files, report on undefined symbols */
+
+static int n_undef_symbols, n_undef_labels, n_undef_vars, n_undef_procs;
+
+/* Extra builtin types */
+
+struct type *builtin_type_complex;
+struct type *builtin_type_double_complex;
+struct type *builtin_type_fixed_dec;
+struct type *builtin_type_float_dec;
+struct type *builtin_type_string;
+
+/* Template types */
+
+static struct type *builtin_type_ptr;
+static struct type *builtin_type_struct;
+static struct type *builtin_type_union;
+static struct type *builtin_type_enum;
+static struct type *builtin_type_range;
+static struct type *builtin_type_set;
+
+
+/* Forward decls */
+
+static struct symbol   *new_symbol();
+static struct type     *new_type();
+static struct field    *new_field();
+static struct block    *new_block();
+static struct symtab   *new_symtab();
+static struct linetable        *new_linetable();
+static struct blockvector *new_bvect();
+
+static struct type     *parse_type();
+static struct type     *make_type();
+static struct symbol   *mylookup_symbol();
+static struct block    *shrink_block();
+
+static int compare_symtabs();
+static int compare_psymtabs();
+static int compare_blocks();
+
+static struct partial_symtab *new_psymtab();
+static struct partial_symbol *new_psymbol();
+static struct partial_symtab *parse_fdr();
+static int compare_psymbols();
+\f
+/* File-level interface functions */
+
+/* Read the symtab information from file FSYM into memory */
+
+static
+read_the_mips_symtab(fsym)
+{
+       int             stsize, st_hdrsize;
+       unsigned        st_filptr;
+       HDRR            st_hdr;
+
+       /* Find and read the symbol table header */
+       st_hdrsize = filhdr.f.f_nsyms;
+       st_filptr = filhdr.f.f_symptr;
+       if (st_filptr == 0)
+               return 0;
+
+       lseek(fsym, st_filptr, L_SET);
+       if (read(fsym, &st_hdr, st_hdrsize) != st_hdrsize)
+               goto readerr;
+
+       /* Find out how large the symbol table is */
+       stsize = (st_hdr.cbExtOffset - (st_filptr + st_hdrsize))
+               + st_hdr.iextMax * cbEXTR;
+
+       /* Allocate space for the symbol table.  Read it in.  */
+       cur_hdr = (HDRR *) xmalloc(stsize + st_hdrsize);
+
+       bcopy(&st_hdr, cur_hdr, st_hdrsize);
+       if (read(fsym, (char *) cur_hdr + st_hdrsize, stsize) != stsize)
+               goto readerr;
+
+       /* Fixup file_pointers in it */
+       fixup_symtab(cur_hdr, (char *) cur_hdr + st_hdrsize,
+                    st_filptr + st_hdrsize);
+
+       return;
+readerr:
+       error("Short read on %s", symfile);
+}
+
+
+/* Turn all file-relative pointers in the symtab described by HDR
+   into memory pointers, given that the symtab itself is located
+   at DATA in memory and F_PTR in the file. */
+
+static
+fixup_symtab( hdr, data, f_ptr)
+       HDRR *hdr;
+       char *data;
+{
+       int             f_idx, s_idx;
+       FDR            *fh;
+       SYMR           *sh;
+       OPTR           *op;
+       PDR            *pr;
+       EXTR           *esh;
+
+       /*
+        * These fields are useless (and empty) by now:
+        *      hdr->cbDnOffset, hdr->cbOptOffset
+        * We use them for other internal purposes.
+        */
+       hdr->cbDnOffset = 0;
+       hdr->cbOptOffset = 0;
+
+#define FIX(off) \
+        if (hdr->off) hdr->off = (unsigned int)data + (hdr->off - f_ptr);
+
+        FIX(cbLineOffset);
+        FIX(cbPdOffset);
+        FIX(cbSymOffset);
+        FIX(cbOptOffset);
+        FIX(cbAuxOffset);
+        FIX(cbSsOffset);
+        FIX(cbSsExtOffset);
+        FIX(cbFdOffset);
+        FIX(cbRfdOffset);
+        FIX(cbExtOffset);
+#undef FIX
+
+
+       /*
+        * Fix all string pointers inside the symtab, and
+        * the FDR records.  Also fix other miscellany.
+        */
+       for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
+               register unsigned code_offset;
+
+               /* Header itself, and strings */
+               fh = (FDR *) (hdr->cbFdOffset) + f_idx;
+               fh->issBase += hdr->cbSsOffset;
+               if (fh->rss != -1)
+                       fh->rss = (long)fh->rss + fh->issBase;
+               for (s_idx = 0; s_idx < fh->csym; s_idx++) {
+                       sh = (SYMR*)(hdr->cbSymOffset) + fh->isymBase + s_idx;
+                       sh->iss = (long) sh->iss + fh->issBase;
+                       sh->reserved = 0;
+               }
+
+               cur_fd = f_idx;
+
+               /* Local symbols */
+               fh->isymBase = (int)((SYMR*)(hdr->cbSymOffset)+fh->isymBase);
+
+               /* cannot fix fh->ipdFirst because it is a short */
+#define IPDFIRST(h,fh) \
+               ((long)h->cbPdOffset + fh->ipdFirst * sizeof(PDR))
+
+               /* Optional symbols (actually used for partial_symtabs) */
+               fh->ioptBase = 0;
+               fh->copt = 0;
+
+               /* Aux symbols */
+               if (fh->caux)
+                       fh->iauxBase = hdr->cbAuxOffset + fh->iauxBase * sizeof(AUXU);
+               /* Relative file descriptor table */
+               fh->rfdBase = hdr->cbRfdOffset + fh->rfdBase * sizeof(RFDT);
+
+               /* Line numbers */
+               if (fh->cbLine)
+                       fh->cbLineOffset += hdr->cbLineOffset;
+
+               /* Procedure symbols.  (XXX This should be done later) */
+               code_offset = fh->adr;
+               for (s_idx = 0; s_idx < fh->cpd; s_idx++) {
+                       unsigned name, only_ext;
+
+                       pr = (PDR*)(IPDFIRST(hdr,fh)) + s_idx;
+
+                       /* Simple rule to find files linked "-x" */
+                       only_ext = fh->rss == -1;
+                       if (only_ext) {
+                               if (pr->isym == -1) {
+                                       /* static function */
+                                       sh = (SYMR*)-1;
+                               } else {
+                                       /* external */
+                                       name = hdr->cbExtOffset + pr->isym * sizeof(EXTR);
+                                       sh = &((EXTR*)name)->asym;
+                               }
+                       } else {
+                               /* Full symbols */
+                               sh = (SYMR*)fh->isymBase + pr->isym;
+                               /* Included code ? */
+                               if (s_idx == 0 && pr->adr != 0)
+                                       code_offset -= pr->adr;
+                       }
+
+                       /* Turn index into a pointer */
+                       pr->isym = (long)sh;
+
+                       /* Fix line numbers */
+                       pr->cbLineOffset += fh->cbLineOffset;
+
+                       /* Relocate address */
+                       if (!only_ext)
+                               pr->adr += code_offset;
+               }               
+       }
+
+       /* External symbols: fix string */
+       for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) {
+               esh = (EXTR*)(hdr->cbExtOffset) + s_idx;
+               esh->asym.iss = esh->asym.iss + hdr->cbSsExtOffset;
+       }
+}
+
+
+/* Find a file descriptor given its index RF relative to a file CF */
+
+static
+FDR *get_rfd( cf, rf)
+{
+       register FDR   *f;
+
+       f = (FDR *) (cur_hdr->cbFdOffset) + cf;
+       /* Object files do not have the RFD table, all refs are absolute */
+       if (f->rfdBase == 0)
+               return (FDR *) (cur_hdr->cbFdOffset) + rf;
+       cf = *((pRFDT) f->rfdBase + rf);
+       return (FDR *) (cur_hdr->cbFdOffset) + cf;
+}
+
+/* Return a safer print NAME for a file descriptor */
+
+static
+char *fdr_name(name)
+       char *name;
+{
+       if (name == (char *) -1)
+               return "<stripped file>";
+       if (UNSAFE_DATA_ADDR(name))
+               return "<NFY>";
+       return name;
+}
+
+
+/* Read in and parse the symtab of the file DESC. INCREMENTAL says
+   whether we are adding to the general symtab or not */
+
+static
+read_mips_symtab( desc, incremental)
+{
+       /*
+        * We get here with DESC pointing to the symtab header. But we need
+        * other info from the initial headers 
+        */
+       lseek(desc, 0L, 0);
+       myread(desc, &filhdr, sizeof filhdr);
+
+       read_the_mips_symtab(desc);
+
+       parse_partial_symbols(cur_hdr, incremental);
+       cur_hdr = 0;
+
+       /*
+        * Check to make sure file was compiled with -g.
+        * If not, warn the user of this limitation.
+        */
+       if (compare_glevel(max_glevel, GLEVEL_2) < 0) {
+               if (max_gdbinfo == 0)
+                       printf("\n%s not compiled with -g, debugging support is limited.", symfile);
+               printf("\nYou should compile with -g2 or -g3 for best debugging support.\n");
+               fflush(stdout);
+       }
+
+       /*
+        * Dont allow char * to have a typename (else would get
+        * caddr_t.)  
+        */
+       TYPE_NAME(lookup_pointer_type(builtin_type_char)) = 0;
+}
+
+\f
+/* Local utilities */
+
+
+/* Map of FDR indexes to partial symtabs */
+
+static struct pst_map {
+       struct partial_symtab *pst;     /* the psymtab proper */
+       int n_globals;                  /* globals it exports */
+} * fdr_to_pst;
+
+
+/* Utility stack, used to nest procedures and blocks properly.
+   It is a doubly linked list, to avoid too many alloc/free.
+   Since we might need it quite a few times it is NOT deallocated
+   after use. */
+
+static struct parse_stack {
+       struct parse_stack      *next, *prev;
+       struct symtab           *cur_st;        /* Current symtab */
+       struct block            *cur_block;     /* Block in it */
+       int                      blocktype;     /* What are we parsing */
+       int                      maxsyms;       /* Max symbols in this block */
+       struct type             *cur_type;      /* Type we parse fields for */
+       int                      procadr;       /* Start addres of this procedure */
+       int                      numargs;       /* Its argument count */
+} *top_stack;  /* Top stack ptr */
+
+
+/* Enter a new lexical context */
+
+static push_parse_stack()
+{
+       struct parse_stack *new;
+
+       /* Reuse frames if possible */
+       if (top_stack && top_stack->prev)
+               new = top_stack->prev;
+       else
+               new = (struct parse_stack *) xzalloc(sizeof(struct parse_stack));
+       /* Initialize new frame with previous content */
+       if (top_stack) {
+               register struct parse_stack *prev = new->prev;
+
+               *new = *top_stack;
+               top_stack->prev = new;
+               new->prev = prev;
+               new->next = top_stack;
+       }
+       top_stack = new;
+}
+
+/* Exit a lexical context */
+
+static pop_parse_stack()
+{
+       if (!top_stack)
+               return;
+       if (top_stack->next)
+               top_stack = top_stack->next;
+}
+
+
+/* Cross-references might be to things we haven't looked at
+   yet, e.g. type references.  To avoid too many type
+   duplications we keep a quick fixup table, an array
+   of lists of references indexed by file descriptor */
+
+static struct pending {
+       struct pending  *next;          /* link */
+       SYMR            *s;             /* the symbol */
+       struct type     *t;             /* its partial type descriptor */
+} **pending_list;
+
+
+/* Check whether we already saw symbol SH in file FH as undefined */
+
+static
+struct pending *is_pending_symbol(fh, sh)
+       FDR *fh;
+       SYMR *sh;
+{
+       int             f_idx = fh - (FDR *) cur_hdr->cbFdOffset;
+       register struct pending *p;
+
+       /* Linear search is ok, list is typically no more than 10 deep */
+       for (p = pending_list[f_idx]; p; p = p->next)
+               if (p->s == sh)
+                       break;
+       return p;
+}
+
+/* Check whether we already saw type T in file FH as undefined */
+
+static
+struct pending *is_pending_type(fh, t)
+       FDR *fh;
+       struct type *t;
+{
+       int             f_idx = fh - (FDR *) cur_hdr->cbFdOffset;
+       register struct pending *p;
+
+       for (p = pending_list[f_idx]; p; p = p->next)
+               if (p->t == t)
+                       break;
+       return p;
+}
+
+/* Add a new undef symbol SH of type T */
+
+static
+add_pending(fh, sh, t)
+       FDR *fh;
+       SYMR *sh;
+       struct type *t;
+{
+       int             f_idx = fh - (FDR *) cur_hdr->cbFdOffset;
+       struct pending *p = is_pending_symbol(fh, sh);
+
+       /* Make sure we do not make duplicates */
+       if (!p) {
+               p = (struct pending *) xmalloc(sizeof(*p));
+               p->s = sh;
+               p->t = t;
+               p->next = pending_list[f_idx];
+               pending_list[f_idx] = p;
+       }
+       sh->reserved = 1;       /* for quick check */
+}
+
+/* Throw away undef entries when done with file index F_IDX */
+
+static
+free_pending(f_idx)
+{
+       register struct pending *p, *q;
+
+       for (p = pending_list[f_idx]; p; p = q) {
+               q = p->next;
+               free(p);
+       }
+       pending_list[f_idx] = 0;
+}
+
+/* The number of args to a procedure is not explicit in the symtab,
+   this is the list of all those we know of.
+   This makes parsing more reasonable and avoids extra passes */
+
+static struct numarg {
+       struct numarg   *next;          /* link */
+       unsigned         adr;           /* procedure's start address */
+       unsigned         num;           /* arg count */
+} *numargs_list;
+
+/* Record that the procedure at ADR takes NUM arguments. */
+
+static
+got_numargs(adr,num)
+{
+       struct numarg  *n = (struct numarg *) xmalloc(sizeof(struct numarg));
+
+       n->adr = adr;
+       n->num = num;
+       n->next = numargs_list;
+       numargs_list = n;
+}
+
+/* See if we know how many arguments the procedure at ADR takes */
+
+static
+lookup_numargs(adr)
+{
+       struct numarg  *n = numargs_list;
+
+       while (n && n->adr != adr)
+               n = n->next;
+       return (n) ? n->num : -1;
+}
+
+/* Release storage when done with this file */
+
+static
+free_numargs()
+{
+       struct numarg  *n = numargs_list, *m;
+
+       while (n) {
+               m = n->next;
+               free(n);
+               n = m;
+       }
+       numargs_list = 0;
+}
+
+\f
+/* Parsing Routines proper. */
+
+/* Parse a single symbol. Mostly just make up a GDB symbol for it.
+   For blocks, procedures and types we open a new lexical context.
+   This is basically just a big switch on the symbol's type */
+
+static
+parse_symbol(sh, ax)
+       SYMR *sh;
+       AUXU *ax;
+{
+       struct symbol  *s;
+       struct block   *b;
+       struct type    *t;
+       struct field   *f;
+       /* When a symbol is cross-referenced from other files/symbols
+          we mark it explicitly */
+       int             pend = (sh->reserved == 1);
+       enum address_class class;
+
+       switch (sh->st) {
+
+           case stNil:
+               break;
+
+           case stGlobal:      /* external symbol, goes into the primary block */
+               class = LOC_STATIC;
+               b = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st), 0);
+               goto data;
+
+           case stStatic:      /* static data, goes into the current block. */
+               class = LOC_STATIC;
+               b = top_stack->cur_block;
+               goto data;
+
+           case stLocal:       /* local variable, goes into the current block */
+               if (sh->sc == scRegister) {
+                       class = LOC_REGISTER;
+                       if (sh->value > 31)
+                               sh->value += 6;
+               } else
+                       class = LOC_LOCAL;
+               b = top_stack->cur_block;
+
+data:          /* Common code for symbols describing data */
+               s = new_symbol(sh->iss);
+               SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+               SYMBOL_CLASS(s) = class;
+               add_symbol(s, b);
+
+               /* Type could be missing in a number of cases */
+               if (sh->sc == scUndefined || sh->sc == scNil ||
+                   sh->index == 0xfffff)
+                       SYMBOL_TYPE(s) = builtin_type_int;      /* undefined? */
+               else
+                       SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
+               /* Value of a data symbol is its memory address */
+               SYMBOL_VALUE(s) = sh->value;
+               break;
+
+           case stParam:       /* argument to procedure, goes into current block */
+               max_gdbinfo++;
+               top_stack->numargs++;
+               s = new_symbol(sh->iss);
+               SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+               if (sh->sc == scRegister) {
+                       SYMBOL_CLASS(s) = LOC_REGPARM;
+                       if (sh->value > 31)
+                               sh->value += 6;
+               } else
+                       SYMBOL_CLASS(s) = LOC_ARG;
+               SYMBOL_VALUE(s) = sh->value;
+               SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
+               add_symbol(s, top_stack->cur_block);
+               break;
+
+           case stLabel:       /* label, we do make a symbol for it */
+               s = new_symbol(sh->iss);
+               SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;    /* so that it can be used */
+               SYMBOL_CLASS(s) = LOC_LABEL;            /* but not misused */
+               SYMBOL_VALUE(s) = sh->value;
+               SYMBOL_TYPE(s) = builtin_type_int;
+               add_symbol(s, top_stack->cur_block);
+               break;
+
+           case stProc:        /* Procedure */
+           case stStaticProc:  /* Static procedure */
+               s = new_symbol(sh->iss);
+               SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+               SYMBOL_CLASS(s) = LOC_BLOCK;
+               /* Type of the return value */
+               if (sh->sc == scUndefined || sh->sc == scNil)
+                       t = builtin_type_int;
+               else
+                       t = parse_type(ax + sh->index, sh, 0);
+               add_symbol(s, top_stack->cur_block);
+
+               /* Make a type for the procedure itself */
+               SYMBOL_TYPE(s) = lookup_function_type (t);
+
+               /* Create and enter a new lexical context */
+               b = new_block(top_stack->maxsyms);
+               SYMBOL_BLOCK_VALUE(s) = b;
+               BLOCK_FUNCTION(b) = s;
+               BLOCK_START(b) = BLOCK_END(b) = sh->value;
+               BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
+               add_block(b, top_stack->cur_st);
+
+               /* Not if we only have partial info */
+               if (sh->sc == scUndefined || sh->sc == scNil)
+                       break;
+
+               push_parse_stack();
+               top_stack->cur_block = b;
+               top_stack->blocktype = sh->st;
+               top_stack->cur_type = SYMBOL_TYPE(s);
+               top_stack->procadr = sh->value;
+               top_stack->numargs = 0;
+
+               sh->value = (long) SYMBOL_TYPE(s);
+               break;
+
+           case stBlock:       /* Either a lexical block, or some type */
+               push_parse_stack();
+               top_stack->blocktype = stBlock;
+               if (sh->sc == scInfo) { /* structure/union/enum def */
+                       s = new_symbol(sh->iss);
+                       SYMBOL_NAMESPACE(s) = STRUCT_NAMESPACE;
+                       SYMBOL_CLASS(s) = LOC_TYPEDEF;
+                       SYMBOL_VALUE(s) = 0;
+                       add_symbol(s, top_stack->cur_block);
+                       /* If this type was expected, use its partial definition */
+                       if (pend) {
+                               t = is_pending_symbol(cur_fdr, sh)->t;
+                       } else {
+                               /* Uhmm, can`t decide yet. Smash later */
+                               t = new_type(sh->iss);
+                               TYPE_CODE(t) = TYPE_CODE_UNDEF;
+                               add_pending(cur_fdr, sh, t);
+                       }
+                       SYMBOL_TYPE(s) = t;
+                       /* make this the current type */
+                       top_stack->cur_type = t;
+                       TYPE_LENGTH(t) = sh->value;
+                       /* Mark that symbol has a type, and say which one */
+                       sh->value = (long) t;
+               } else {
+                       /* beginnning of (code) block. Value of symbol
+                          is the displacement from procedure start */
+                       b = new_block(top_stack->maxsyms);
+                       BLOCK_START(b) = sh->value + top_stack->procadr;
+                       BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
+                       top_stack->cur_block = b;
+                       add_block(b, top_stack->cur_st);
+               }
+               break;
+
+           case stEnd:         /* end (of anything) */
+               if (sh->sc == scInfo) {
+                       /* Finished with type */
+                       top_stack->cur_type = 0;
+               } else if (sh->sc == scText &&
+                          (top_stack->blocktype == stProc ||
+                           top_stack->blocktype == stStaticProc)) {
+                   /* Finished with procedure */
+                   struct blockvector *bv = BLOCKVECTOR(top_stack->cur_st);
+                   struct block *b;
+                   int i;
+
+                   BLOCK_END(top_stack->cur_block) += sh->value; /* size */
+                   got_numargs(top_stack->procadr, top_stack->numargs);
+                   /* Reallocate symbols, saving memory */
+                   b = shrink_block(top_stack->cur_block, top_stack->cur_st);
+
+                   /* f77 emits proc-level with address bounds==[0,0],
+                      So look for such child blocks, and patch them.  */
+                   for (i = 0; i < BLOCKVECTOR_NBLOCKS(bv); i++) {
+                       struct block *b_bad = BLOCKVECTOR_BLOCK(bv,i);
+                       if (BLOCK_SUPERBLOCK(b_bad) == b
+                        && BLOCK_START(b_bad) == top_stack->procadr
+                        && BLOCK_END(b_bad) == top_stack->procadr) {
+                           BLOCK_START(b_bad) = BLOCK_START(b);
+                           BLOCK_END(b_bad) = BLOCK_END(b);
+                       }
+                   }
+               } else if (sh->sc == scText && top_stack->blocktype == stBlock) {
+                       /* End of (code) block. The value of the symbol
+                          is the displacement from the procedure`s start
+                          address of the end of this block. */
+                       BLOCK_END(top_stack->cur_block) = sh->value + top_stack->procadr;
+                       (void) shrink_block(top_stack->cur_block, top_stack->cur_st);
+               }
+               pop_parse_stack();      /* restore previous lexical context */
+               break;
+
+           case stMember:      /* member of struct/union/enum.. */
+               f = new_field(top_stack->cur_type, sh->iss);
+               f->bitpos = sh->value;
+               f->type = parse_type(ax + sh->index, sh, &f->bitsize);
+               break;
+
+           case stTypedef:     /* type definition */
+               s = new_symbol(sh->iss);
+               SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+               SYMBOL_CLASS(s) = LOC_TYPEDEF;
+               SYMBOL_BLOCK_VALUE(s) = top_stack->cur_block;
+               add_symbol(s, top_stack->cur_block);                    
+               SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
+               sh->value = (long) SYMBOL_TYPE(s);
+               break;
+
+           case stFile:        /* file name */
+               push_parse_stack();
+               top_stack->blocktype = sh->st;
+               break;
+
+               /* I`ve never seen these for C */
+           case stRegReloc:
+               break;          /* register relocation */
+           case stForward:
+               break;          /* forwarding address */
+           case stConstant:
+               break;          /* constant */
+           default:
+               error("Unknown symbol type %x.", sh->st);
+       }
+       sh->st = stParsed;
+}
+
+/* Parse the type information provided in the AX entries for
+   the symbol SH. Return the bitfield size in BS, in case. */
+
+static struct type *parse_type(ax, sh, bs)
+       AUXU    *ax;
+       SYMR    *sh;
+       int     *bs;
+{
+       /* Null entries in this map are treated specially */
+       static struct type **map_bt[] =
+       {
+                &builtin_type_void,            /* btNil */
+                0,                             /* btAdr */
+                &builtin_type_char,            /* btChar */
+                &builtin_type_unsigned_char,   /* btUChar */
+                &builtin_type_short,           /* btShort */
+                &builtin_type_unsigned_short,  /* btUShort */
+                &builtin_type_int,             /* btInt */
+                &builtin_type_unsigned_int,    /* btUInt */
+                &builtin_type_long,            /* btLong */
+                &builtin_type_unsigned_long,   /* btULong */
+                &builtin_type_float,           /* btFloat */
+                &builtin_type_double,          /* btDouble */
+                0,                             /* btStruct */
+                0,                             /* btUnion */
+                0,                             /* btEnum */
+                0,                             /* btTypedef */
+                0,                             /* btRange */
+                0,                             /* btSet */
+                &builtin_type_complex,         /* btComplex */
+                &builtin_type_double_complex,  /* btDComplex */
+                0,                             /* btIndirect */
+                &builtin_type_fixed_dec,       /* btFixedDec */
+                &builtin_type_float_dec,       /* btFloatDec */
+                &builtin_type_string,          /* btString */
+                0,                             /* btBit */
+                0,                             /* btPicture */
+                &builtin_type_void,            /* btVoid */
+       };
+
+       TIR            *t;
+       struct type    *tp = 0, *tp1;
+       char           *fmt = "%s";
+
+       /* Procedures start off by one */
+       if (sh->st == stProc || sh->st == stStaticProc)
+               ax++;
+
+       /* Undefined ? Should not happen */
+       if (ax->rndx.rfd == 0xfff) {
+               return builtin_type_void;
+       }
+
+       /* Use aux as a type information record, map its basic type */
+       t = &ax->ti;
+       if (t->bt > 26 || t->bt == btPicture) {
+               printf_filtered("Internal: cannot map MIPS basic type x%x\n", t->bt);
+               return builtin_type_int;
+       }
+       if (map_bt[t->bt])
+               tp = *map_bt[t->bt];
+       else {
+               /* Cannot use builtin types, use templates */
+               tp = make_type(TYPE_CODE_VOID, 0, 0, 0);
+               switch (t->bt) {
+                   case btAdr:
+                       *tp = *builtin_type_ptr;
+                       break;
+                   case btStruct:
+                       *tp = *builtin_type_struct;
+                       fmt = "struct %s";
+                       break;
+                   case btUnion:
+                       *tp = *builtin_type_union;
+                       fmt = "union %s";
+                       break;
+                   case btEnum:
+                       *tp = *builtin_type_enum;
+                       fmt = "enum %s";
+                       break;
+                   case btRange:
+                       *tp = *builtin_type_range;
+                       break;
+                   case btSet:
+                       *tp = *builtin_type_set;
+                       fmt = "set %s";
+                       break;
+               }
+       }
+
+       /* Move on to next aux */
+       ax++;
+       if (t->continued) {
+               /* This is the way it would work if the compiler worked */
+               register TIR *t1 = t;
+               while (t1->continued)
+                       ax++;
+       }
+
+       /* For bitfields all we need is the width */
+       if (t->fBitfield) {
+               *bs = ax->width;
+               return tp;
+       }
+
+       /* All these types really point to some (common) MIPS type
+          definition, and only the type-qualifiers fully identify
+          them.  We`ll make the same effort at sharing */
+       if (t->bt == btIndirect ||
+           t->bt == btStruct ||
+           t->bt == btUnion ||
+           t->bt == btEnum ||
+           t->bt == btTypedef ||
+           t->bt == btRange ||
+           t->bt == btSet) {
+               char            name[256], *pn;
+
+               /* Try to cross reference this type */
+               tp1 = tp;
+               ax += cross_ref(ax, &tp1, &pn);
+               /* SOMEONE OUGHT TO FIX DBXREAD TO DROP "STRUCT" */
+               sprintf(name, fmt, pn);
+
+               /* reading .o file ? */
+               if (UNSAFE_DATA_ADDR(tp1))
+                       tp1 = tp;
+               if (TYPE_CODE(tp1) == TYPE_CODE_UNDEF) {
+                       /*
+                        * Type was incompletely defined, now we know.
+                        */
+                       TYPE_CODE(tp1) = TYPE_CODE(tp);
+                       TYPE_NAME(tp1) = obsavestring(name, strlen(name));
+                       if (TYPE_CODE(tp1) == TYPE_CODE_ENUM) {
+                               int             i;
+
+                               for (i = 0; i < TYPE_NFIELDS(tp1); i++)
+                                       make_enum_constant(&TYPE_FIELD(tp1,i), tp1);
+                       }
+               }
+               if (tp1 != tp) {
+                       /* found as cross ref, rid of our template */
+                       if ((TYPE_FLAGS(tp) & TYPE_FLAG_PERM) == 0)
+                               free(tp);
+                       tp = tp1;
+                       /* stupid idea of prepending "struct" to type names */
+                       if (t->bt == btStruct && !index(TYPE_NAME(tp), ' ')) {
+                               sprintf(name, fmt, TYPE_NAME(tp));
+                               TYPE_NAME(tp) = obsavestring(name, strlen(name));
+                       }
+               } else
+                       TYPE_NAME(tp) = savestring(name, strlen(name));
+       }
+
+       /* Deal with range types */
+       if (t->bt == btRange) {
+               struct field   *f;
+
+               f = new_field(tp, "Low");
+               f->bitpos = ax->dnLow;
+               ax++;
+               f = new_field(tp, "High");
+               f->bitpos = ax->dnHigh;
+               ax++;
+       }
+
+       /* Parse all the type qualifiers now. If there are more
+          than 6 the game will continue in the next aux */
+
+#define PARSE_TQ(tq) \
+       if (t->tq != tqNil) ax += upgrade_type(&tp, t->tq, ax, sh);
+
+again: PARSE_TQ(tq0);
+       PARSE_TQ(tq1);
+       PARSE_TQ(tq2);
+       PARSE_TQ(tq3);
+       PARSE_TQ(tq4);
+       PARSE_TQ(tq5);
+#undef PARSE_TQ
+
+       if (t->continued) {
+               t++;
+               goto again;
+       }
+       return tp;
+}
+
+/* Make up a complex type from a basic one.  Type is passed by
+   reference in TPP and side-effected as necessary. The type
+   qualifier TQ says how to handle the aux symbols at AX for
+   the symbol SX we are currently analyzing.
+   Returns the number of aux symbols we parsed. */
+
+static
+upgrade_type(tpp, tq, ax, sh)
+       struct type   **tpp;
+       AUXU           *ax;
+       SYMR           *sh;
+{
+       int             off = 0;
+       int             ret = 0;
+       struct type    *t;
+
+       if (tq == tqPtr) {
+               t = lookup_pointer_type (*tpp);
+       } else if (tq == tqProc) {
+               t = lookup_function_type (*tpp);
+       } else if (tq == tqArray) {
+               int             rf, id;
+               FDR            *fh;
+               struct field   *f;
+               SYMR            ss;
+
+               t = make_type(TYPE_CODE_ARRAY, 0, 0, 0);
+               TYPE_TARGET_TYPE(t) = *tpp;
+
+               /* Pointer to domain type (type of index) */
+               id = ax->rndx.index;
+               if ((rf = ax->rndx.rfd) == 0xfff)
+                       rf = (++ax)->isym, off++;
+
+               fh = get_rfd(cur_fd, rf);
+               f = new_field(t, 0);
+               bzero(&ss, sizeof ss);
+/* XXX */      f->type = parse_type(fh->iauxBase + id * sizeof(AUXU),
+                                    &ss, &f->bitsize);
+
+               /*
+                * This seems to be a pointer to the end of the Block defining
+                * the type.  Why it is here is magic for me, and I have no
+                * good use for it anyways.
+                */
+               if (off == 0) {
+                       off++;
+                       id = (++ax)->rndx.index;
+                       if ((rf = ax->rndx.rfd) == 0xfff)
+                               rf = (++ax)->isym, off++;
+               }
+               f->bitpos = (++ax)->dnLow;      /* ?? */
+               f->bitsize = (++ax)->dnHigh;    /* ?? */
+               rf = (++ax)->width - 1; /* bit alignment */
+               id = TYPE_LENGTH(TYPE_TARGET_TYPE(t)) << 3; /* bitsize */
+
+               if (id == 0) {
+                       /* Most likely an undefined type */
+                       id = rf + 1;
+                       TYPE_LENGTH(TYPE_TARGET_TYPE(t)) = id >> 3;
+               }
+               TYPE_LENGTH(t) = (f->bitsize < 0) ? 0 :
+                       (f->bitsize - f->bitpos + 1) * (id >> 3);
+               ret = 4 + off;
+       } else {
+               if (tq != tqVol)
+                       printf_filtered("Internal: unknown type qualifier %x\n", tq);
+               return ret;
+       }
+
+       *tpp = t;
+       return ret;
+}
+
+
+/* Parse a procedure descriptor record PR.  Note that the procedure
+   is parsed _after_ the local symbols, now we just make up the
+   extra information we need into a special symbol that we insert
+   in the procedure's main block.  Note also that images that
+   have been partially stripped (ld -x) have been deprived
+   of local symbols, and we have to cope with them here.
+   The procedure's code ends at BOUND */
+
+static
+parse_procedure(pr, bound)
+       PDR *pr;
+{
+       struct symbol *s, *i;
+       SYMR *sh = (SYMR*)pr->isym;
+       struct block *b;
+       struct mips_extra_func_info *e;
+       char name[100];
+       char *sh_name;
+
+       /* Reuse the MIPS record */
+       e = (struct mips_extra_func_info *) pr;
+       e->numargs = lookup_numargs(pr->adr);
+
+       /* Make up our special symbol */
+       i = new_symbol(".gdbinfo.");
+       SYMBOL_VALUE(i) = (int)e;
+       SYMBOL_NAMESPACE(i) = LABEL_NAMESPACE;
+       SYMBOL_CLASS(i) = LOC_CONST;
+       SYMBOL_TYPE(i) = builtin_type_void;
+
+       /* Make up a name for static procedures. Sigh. */
+       if (sh == (SYMR*)-1) {
+           sprintf(name,".static_procedure@%x",pr->adr);
+           sh_name = savestring(name, strlen(name));
+           s = NULL;
+       }
+       else {
+           sh_name = (char*)sh->iss;
+           s = mylookup_symbol(sh_name, top_stack->cur_block,
+                               VAR_NAMESPACE, LOC_BLOCK);
+       }
+       if (s != 0) {
+               b = SYMBOL_BLOCK_VALUE(s);
+       } else {
+               s = new_symbol(sh_name);
+               SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+               SYMBOL_CLASS(s) = LOC_BLOCK;
+               /* Donno its type, hope int is ok */
+               SYMBOL_TYPE(s) = lookup_function_type (builtin_type_int);
+               add_symbol(s, top_stack->cur_block);
+               /* Wont have symbols for this one */
+               b = new_block(2);
+               SYMBOL_BLOCK_VALUE(s) = b;
+               BLOCK_FUNCTION(b) = s;
+               BLOCK_START(b) = pr->adr;
+               BLOCK_END(b) = bound;
+               BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
+               add_block(b, top_stack->cur_st);
+       }
+       e->isym = (long)s;
+       add_symbol(i,b);
+}
+
+/* Parse the external symbol ES. Just call parse_symbol() after
+   making sure we know where the aux are for it. For procedures,
+   parsing of the PDRs has already provided all the needed
+   information, we only parse them if SKIP_PROCEDURES is false,
+   and only if this causes no symbol duplication */
+
+static
+parse_external(es, skip_procedures)
+       EXTR *es;
+{
+       AUXU *ax;
+
+       if (es->ifd != ifdNil) {
+               cur_fd = es->ifd;
+               cur_fdr = (FDR*)(cur_hdr->cbFdOffset) + cur_fd;
+               ax = (AUXU*)cur_fdr->iauxBase;
+       } else {
+               cur_fdr = (FDR*)(cur_hdr->cbFdOffset);
+               ax = 0;
+       }
+       top_stack->cur_st = cur_stab;
+       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st),0);
+
+       /* Reading .o files */
+       if (es->asym.sc == scUndefined || es->asym.sc == scNil) {
+               char *what;
+               switch (es->asym.st) {
+               case stStaticProc:
+               case stProc:    what = "Procedure"; n_undef_procs++;  break;
+               case stGlobal:  what = "Variable";  n_undef_vars++;   break;
+               case stLabel:   what = "Label";     n_undef_labels++; break;
+               default :       what = "Symbol";                      break;
+               }
+               n_undef_symbols++;
+               if (info_verbose)
+                       printf_filtered("Warning: %s %s is undefined (in %s)\n", what,
+                               es->asym.iss, fdr_name(cur_fdr->rss));
+               return;
+       }
+
+       switch (es->asym.st) {
+       case stProc:
+               /* If we have full symbols we do not need more */
+               if (skip_procedures)
+                       return;
+               if (mylookup_symbol (es->asym.iss, top_stack->cur_block,
+                                       VAR_NAMESPACE, LOC_BLOCK))
+                       break;
+               /* fall through */
+       case stGlobal:
+       case stLabel:
+               /*
+                * Note that the case of a symbol with indexNil
+                * must be handled anyways by parse_symbol().
+                */
+               parse_symbol(&es->asym, ax);
+               break;
+       default:
+               break;
+       }
+}
+
+/* Parse the line number info for file descriptor FH into
+   GDB's linetable LT.  MIPS' encoding requires a little bit
+   of magic to get things out.  Note also that MIPS' line
+   numbers can go back and forth, apparently we can live
+   with that and do not need to reorder our linetables */
+
+static
+parse_lines(fh, lt)
+       FDR *fh;
+       struct linetable *lt;
+{
+       char *base = (char*)fh->cbLineOffset;
+       int i, j, k;
+       int delta, count, lineno = 0;
+       PDR *pr;
+
+       if (base == 0)
+               return;
+
+       /* Scan by procedure descriptors */
+       i = 0; j = 0, k = 0;
+       for (pr = (PDR*)IPDFIRST(cur_hdr,fh); j < fh->cpd; j++, pr++) {
+               int l, halt;
+
+               /* No code for this one */
+               if (pr->iline == ilineNil ||
+                   pr->lnLow == -1 || pr->lnHigh == -1)
+                       continue;
+               /*
+                *      Aurgh! To know where to stop expanding we
+                *      must look-ahead.
+                */
+               for (l = 1; l < (fh->cpd - j); l++)
+                       if (pr[l].iline != -1)
+                               break;
+               if (l == (fh->cpd - j))
+                       halt = fh->cline;
+               else
+                       halt = pr[l].iline;
+               /*
+                * When procedures are moved around the linenumbers
+                * are attributed to the next procedure up
+                */
+               if (pr->iline >= halt) continue;
+
+               base = (char*)pr->cbLineOffset;
+               l = pr->adr >> 2;       /* in words */
+               halt += (pr->adr >> 2) - pr->iline;
+               for (lineno = pr->lnLow; l < halt;) {
+                       count = *base & 0x0f;
+                       delta = *base++ >> 4;
+                       if (delta == -8) {
+                               delta = (base[0] << 8) | (base[1] & 0xff);
+                               base += 2;
+                       }
+                       lineno += delta;/* first delta is 0 */
+                       k = add_line(lt, lineno, l, k);
+                       l += count + 1;
+               }
+       }
+}
+
+
+/* Parse the symbols of the file described by FH, whose index is F_IDX.
+   BOUND is the highest core address of this file's procedures */
+
+static
+parse_one_file(fh, f_idx, bound)
+       FDR *fh;
+{
+       register int s_idx;
+       SYMR *sh;
+       PDR *pr;
+
+       /* Parse local symbols first */
+
+       for (s_idx = 0; s_idx < fh->csym; s_idx++) {
+               sh = (SYMR *) (fh->isymBase) + s_idx;
+               cur_sdx = s_idx;
+               parse_symbol(sh, fh->iauxBase);
+       }
+
+       /* Procedures next, note we need to look-ahead to
+          find out where the procedure's code ends */
+
+       for (s_idx = 0; s_idx < fh->cpd-1; s_idx++) {
+               pr = (PDR *) (IPDFIRST(cur_hdr, fh)) + s_idx;
+               parse_procedure(pr, pr[1].adr); /* next proc up */
+       }
+       if (fh->cpd) {
+               pr = (PDR *) (IPDFIRST(cur_hdr, fh)) + s_idx;
+               parse_procedure(pr, bound);     /* next file up */
+       }
+
+       /* Linenumbers. At the end, check if we can save memory */
+       parse_lines(fh, LINETABLE(cur_stab));
+       if (LINETABLE(cur_stab)->nitems < fh->cline)
+               shrink_linetable(cur_stab);
+}
+
+
+/* Master parsing procedure. Parses the symtab described by the
+   symbolic header HDR.  If INCREMENTAL is true we are called
+   by add-file and must preserve the old symtabs */
+static
+parse_partial_symbols(hdr, incremental)
+       HDRR *hdr;
+{
+       int             f_idx, s_idx, h_max;
+       CORE_ADDR       dummy, *prevhigh;
+       /* Running pointers */
+       FDR            *fh;
+       RFDT           *rh;
+       register EXTR           *esh;
+
+       /*
+        * Big plan: 
+        *
+        * Only parse the External symbols, and the Relative FDR.
+        * Fixup enough of the loader symtab to be able to use it.
+        * Allocate space only for the file`s portions we need to
+        * look at. (XXX)
+        */
+
+       cur_hdr = hdr;
+       max_gdbinfo = 0;
+       max_glevel = MIN_GLEVEL;
+
+       /* Allocate the map FDR -> PST.
+          Minor hack: -O3 images might claim some global data belongs
+          to FDR -1. We`ll go along with that */
+       fdr_to_pst = (struct pst_map *)xzalloc((hdr->ifdMax+1) * sizeof *fdr_to_pst);
+       fdr_to_pst++;
+       {
+               struct partial_symtab * pst = new_psymtab("");
+               fdr_to_pst[-1].pst = pst;
+               pst->ldsymoff = -1;
+       }
+
+       /* Now scan the FDRs, mostly for dependencies */
+       for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
+               (void) parse_fdr(f_idx, 1);
+
+       /* Take a good guess at how many symbols we might ever need */
+       h_max = hdr->iextMax;
+
+       /* Parse externals: two passes because they can be ordered
+          in any way */
+
+       /* Pass 1: Presize and partition the list */
+       for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) {
+               esh = (EXTR *) (hdr->cbExtOffset) + s_idx;
+               fdr_to_pst[esh->ifd].n_globals++;
+       }
+
+       if (global_psymbols.list) {
+               global_psymbols.list = (struct partial_symbol *)
+                       xrealloc( global_psymbols.list, (h_max +
+                               global_psymbols.size) * sizeof(struct partial_symbol));
+               global_psymbols.next = global_psymbols.list + global_psymbols.size;
+               global_psymbols.size += h_max;
+       } else {
+               global_psymbols.list = (struct partial_symbol *)
+                               xmalloc( h_max * sizeof(struct partial_symbol));
+               global_psymbols.size = h_max;
+               global_psymbols.next = global_psymbols.list;
+       }
+
+       s_idx = global_psymbols.next - global_psymbols.list;
+       for (f_idx = -1; f_idx < hdr->ifdMax; f_idx++) {
+               fdr_to_pst[f_idx].pst->globals_offset = s_idx;
+               s_idx += fdr_to_pst[f_idx].n_globals;
+       }
+
+       /* Pass 2: fill in symbols */
+       for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) {
+               register struct partial_symbol *p;
+               enum misc_function_type misc_type = mf_text;
+               esh = (EXTR *) (hdr->cbExtOffset) + s_idx;
+
+               if (esh->asym.sc == scUndefined || esh->asym.sc == scNil)
+                       continue;
+               p = new_psymbol(&global_psymbols, esh->asym.iss, esh->ifd);
+               SYMBOL_VALUE(p) = esh->asym.value;
+               SYMBOL_NAMESPACE(p) = VAR_NAMESPACE;
+
+               switch (esh->asym.st) {
+               case stProc:
+                       SYMBOL_CLASS(p) = LOC_BLOCK;
+                       break;
+               case stGlobal:
+                       SYMBOL_CLASS(p) = LOC_STATIC;
+                       misc_type = mf_data;
+                       break;
+               case stLabel:
+                       SYMBOL_CLASS(p) = LOC_LABEL;
+                       break;
+               default:
+                       misc_type = mf_unknown;
+                       complain (&unknown_ext_complaint, SYMBOL_NAME(p));
+               }
+               prim_record_misc_function (SYMBOL_NAME(p),
+                                          SYMBOL_VALUE(p),
+                                          misc_type);
+       }
+
+
+       /* The array (of lists) of globals must be sorted.
+          Take care, since we are at it, of pst->texthigh.
+
+          NOTE: The way we handle textlow/high is incorrect, but good
+          enough for a first approximation. The case we fail is on a
+          file "foo.c" that looks like
+               proc1() {...}
+               #include "bar.c"        -- this contains proc2()
+               proc3() {...}
+          where proc3() is attributed to bar.c.  But since this is a
+          dependent file it will cause loading of foo.c as well, so
+          everything will be fine at the end.  */
+
+       prevhigh = &dummy;
+       for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
+               struct partial_symtab *pst = fdr_to_pst[f_idx].pst;
+               if (pst->n_global_syms > 1)
+                       qsort (global_psymbols.list + pst->globals_offset,
+                               pst->n_global_syms, sizeof (struct partial_symbol),
+                               compare_psymbols);
+               if (pst->textlow) {
+                       *prevhigh = pst->textlow;
+                       prevhigh = &pst->texthigh;
+               }
+       }
+
+       /* Mark the last code address, and remember it for later */
+       *prevhigh = END_OF_TEXT_SEGMENT(filhdr);
+       hdr->cbDnOffset = END_OF_TEXT_SEGMENT(filhdr);
+
+       reorder_psymtabs();
+       free(&fdr_to_pst[-1]);
+       fdr_to_pst = 0;
+}
+
+
+/* Do the initial analisys of the F_IDX-th file descriptor.
+   Allocates a partial symtab for it, and builds the list
+   of dependent files by recursion. LEV says at which level
+   of recursion we are called (to pretty up debug traces) */
+
+static struct partial_symtab *
+parse_fdr(f_idx, lev)
+       int f_idx;
+{
+       register FDR *fh;
+       register struct partial_symtab *pst;
+       int s_idx, s_id0;
+
+       fh = (FDR *) (cur_hdr->cbFdOffset) + f_idx;
+
+       /* Use this to indicate into which symtab this file was parsed */
+       if (fh->ioptBase)
+               return (struct partial_symtab *) fh->ioptBase;
+
+       /* Debuggability level */
+       if (compare_glevel(max_glevel, fh->glevel) < 0)
+               max_glevel = fh->glevel;
+
+       /* Make a new partial_symtab */
+       pst = new_psymtab(fh->rss);
+       if (fh->cpd == 0){
+               pst->textlow = 0;
+               pst->texthigh = 0;
+       } else {
+               pst->textlow = fh->adr;
+               pst->texthigh = fh->cpd;        /* To be fixed later */
+       }
+       /* Reverse mapping PST -> FDR */
+       pst->ldsymoff = f_idx;
+
+       fdr_to_pst[f_idx].pst = pst;
+       fh->ioptBase = (int)pst;
+
+       /* Analyze its dependencies */
+       if (fh->crfd <= 1)
+               return pst;
+
+       s_id0 = 0;
+       if (fh->cpd == 0) {  /* If there are no functions defined here ... */
+               /* ...then presumably a .h file: drop reverse depends .h->.c */
+               for (; s_id0 < fh->crfd; s_id0++) {
+                       RFDT *rh = (RFDT *) (fh->rfdBase) + s_id0;
+                       if (*rh == f_idx) {
+                               s_id0++;        /* Skip self-dependency */
+                               break;
+                       }
+               }
+       }
+       pst->number_of_dependencies = fh->crfd - s_id0;
+       pst->dependencies = (struct partial_symtab **)
+               obstack_alloc (psymbol_obstack,
+                              pst->number_of_dependencies * sizeof(char*));
+       for (s_idx = s_id0; s_idx < fh->crfd; s_idx++) {
+               RFDT *rh = (RFDT *) (fh->rfdBase) + s_idx;
+
+               pst->dependencies[s_idx-s_id0] = parse_fdr(*rh, lev+1);
+
+       }
+
+       return pst;
+}
+
+
+/* Ancillary function to psymtab_to_symtab().  Does all the work
+   for turning the partial symtab PST into a symtab, recurring
+   first on all dependent psymtabs */
+
+static void psymtab_to_symtab_1(pst)
+       struct partial_symtab *pst;
+{
+       int             i, f_max;
+       struct symtab  *st;
+       FDR *fh;
+
+       if (pst->readin)
+               return;
+       pst->readin = 1;
+
+       pending_list = (struct pending **) cur_hdr->cbOptOffset;
+       if (pending_list == 0) {
+               pending_list = (struct pending **)
+                       xzalloc(cur_hdr->ifdMax * sizeof(struct pending *));
+               cur_hdr->cbOptOffset = (int)pending_list;
+       }
+
+       /* How many symbols will we need */
+       f_max = pst->n_global_syms + pst->n_static_syms;
+       if (pst->ldsymoff == -1) {
+               fh = 0;
+               st = new_symtab( "unknown", f_max, 0);
+       } else {
+               fh = (FDR *) (cur_hdr->cbFdOffset) + pst->ldsymoff;
+               f_max += fh->csym + fh->cpd;
+               st = new_symtab(pst->filename, 2 * f_max, 2 * fh->cline);
+       }
+
+       /*
+        * Read in all partial symbtabs on which this one is dependent.
+        * NOTE that we do have circular dependencies, sigh. 
+        */
+       for (i = 0; i < pst->number_of_dependencies; i++)
+               if (!pst->dependencies[i]->readin) {
+                       /*
+                        * DO NOT inform about additional files that need to
+                        * be read in, it would only annoy the user.
+                        */
+                       psymtab_to_symtab_1(pst->dependencies[i]);
+               }
+
+       /* Now read the symbols for this symtab */
+
+       cur_fd = pst->ldsymoff;
+       cur_fdr = fh;
+       cur_stab = st;
+
+       /* Get a new lexical context */
+
+       push_parse_stack();
+       top_stack->cur_st = cur_stab;
+       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(cur_stab), 0);
+       BLOCK_START(top_stack->cur_block) = fh ? fh->adr : 0;
+       BLOCK_END(top_stack->cur_block) = 0;
+       top_stack->blocktype = stFile;
+       top_stack->maxsyms = f_max;
+       top_stack->cur_type = 0;
+       top_stack->procadr = 0;
+       top_stack->numargs = 0;
+
+       /* Parse locals and procedures */
+       if (fh)
+               parse_one_file(fh, cur_fd, (cur_fd == (cur_hdr->ifdMax - 1)) ?
+                               cur_hdr->cbDnOffset : fh[1].adr);
+
+       /* .. and our share of externals.
+          XXX use the global list to speed up things here. how ? */
+       top_stack->blocktype = stFile;
+       top_stack->maxsyms = cur_hdr->isymMax + cur_hdr->ipdMax + cur_hdr->iextMax;
+       for (i = 0; i < cur_hdr->iextMax; i++) {
+               register EXTR *esh = (EXTR *) (cur_hdr->cbExtOffset) + i;
+               if (esh->ifd == cur_fd)
+                       parse_external(esh, 1);
+       }
+
+       /* If there are undefined, tell the user */
+       if (n_undef_symbols) {
+               printf_filtered("File %s contains %d unresolved references:",
+                               st->filename, n_undef_symbols);
+               printf_filtered("\n\t%4d variables\n\t%4d procedures\n\t%4d labels\n",
+                               n_undef_vars, n_undef_procs, n_undef_labels);
+               n_undef_symbols = n_undef_labels = n_undef_vars = n_undef_procs = 0;
+       }
+
+       pop_parse_stack();
+
+       /*
+        * Sort the symbol table now, we are done adding symbols to it.
+        */
+       sort_symtab_syms(st);
+}
+
+
+
+\f
+/* Ancillary parsing procedures. */
+
+/* Lookup the type at relative index RN.  Return it in TPP
+   if found and in any event come up with its name PNAME.
+   Return value says how many aux symbols we ate */
+
+static
+cross_ref(rn, tpp, pname)
+       RNDXR *rn;
+       struct type **tpp;
+       char **pname;
+{
+       unsigned        rf;
+
+       /* Escape index means 'the next one' */
+       if (rn->rfd == 0xfff)
+               rf = *(unsigned *) (rn + 1);
+       else
+               rf = rn->rfd;
+
+       if (rf == -1) {
+               /* Ooops */
+               *pname = "<undefined>";
+       } else {
+               /*
+                * Find the relative file descriptor and the symbol in it 
+                */
+               FDR            *fh = get_rfd(cur_fd, rf);
+               SYMR           *sh;
+               struct type    *t;
+
+               /*
+                * If we have processed this symbol then we left a forwarding
+                * pointer to the corresponding GDB symbol.  If not, we`ll put
+                * it in a list of pending symbols, to be processed later when
+                * the file f will be.  In any event, we collect the name for
+                * the type here. Which is why we made a first pass at
+                * strings. 
+                */
+               sh = (SYMR *) (fh->isymBase) + rn->index;
+
+               /* Careful, we might be looking at .o files */
+               *pname = (UNSAFE_DATA_ADDR(sh->iss)) ? "<undefined>" :
+                       (char *) sh->iss;
+
+               /* Have we parsed it ? */
+               if ((!UNSAFE_DATA_ADDR(sh->value)) && (sh->st == stParsed)) {
+                       t = (struct type *) sh->value;
+                       *tpp = t;
+               } else {
+                       struct pending *p;
+
+                       /* Avoid duplicates */
+                       p = is_pending_symbol(fh, sh);
+
+                       if (p)
+                               *tpp = p->t;
+                       else
+                               add_pending(fh, sh, *tpp);
+               }
+       }
+       return (rn->rfd == 0xfff);
+}
+
+
+/* Quick&dirty lookup procedure, to avoid the MI ones that require
+   keeping the symtab sorted */
+
+static struct symbol *
+mylookup_symbol (name, block, namespace, class)
+     char *name;
+     register struct block *block;
+     enum namespace namespace;
+     enum address_class class;
+{
+       register int    bot, top, inc;
+       register struct symbol *sym;
+
+       bot = 0;
+       top = BLOCK_NSYMS(block);
+       inc = name[0];
+       while (bot < top) {
+               sym = BLOCK_SYM(block, bot);
+               if (SYMBOL_NAME(sym)[0] == inc
+                   && SYMBOL_NAMESPACE(sym) == namespace
+                   && SYMBOL_CLASS(sym) == class
+                   && !strcmp(SYMBOL_NAME(sym), name))
+                       return sym;
+               bot++;
+       }
+       if (block = BLOCK_SUPERBLOCK (block))
+               return mylookup_symbol (name, block, namespace, class);
+       return 0;
+}
+
+
+/* Add a new symbol S to a block B */
+
+static
+add_symbol(s,b)
+       struct symbol *s;
+       struct block *b;
+{
+       BLOCK_SYM(b,BLOCK_NSYMS(b)++) = s;
+       if (b == top_stack->cur_block &&
+           BLOCK_NSYMS(b) > top_stack->maxsyms)
+               printf_filtered("Internal: block at @%x overfilled (by %d)\n",
+                       b, BLOCK_NSYMS(b) - top_stack->maxsyms);
+}
+
+/* Add a new block B to a symtab S */
+
+static
+add_block(b,s)
+       struct block *b;
+       struct symtab *s;
+{
+       struct blockvector *bv = BLOCKVECTOR(s);
+
+       bv = (struct blockvector *)xrealloc(bv, sizeof(struct blockvector) +
+                                           BLOCKVECTOR_NBLOCKS(bv) * sizeof(bv->block));
+       if (bv != BLOCKVECTOR(s))
+               BLOCKVECTOR(s) = bv;
+
+       BLOCKVECTOR_BLOCK(bv, BLOCKVECTOR_NBLOCKS(bv)++) = b;
+}
+
+/* Add a new linenumber entry (LINENO,ADR) to a linevector LT.
+   MIPS' linenumber encoding might need more than one byte
+   to describe it, LAST is used to detect these continuation lines */
+
+static 
+add_line(lt, lineno, adr, last)
+       struct linetable *lt;
+       CORE_ADDR adr;
+{
+       if (last == 0)
+               last = -2;      /* make sure we record first line */
+
+       if (last == lineno)     /* skip continuation lines */
+               return lineno;
+
+       lt->item[lt->nitems].line = lineno;
+       lt->item[lt->nitems++].pc = adr << 2;
+       return lineno;
+}
+
+
+\f
+/* Comparison functions, used when sorting things */
+
+/*  Symtabs must be ordered viz the code segments they cover */
+
+static int
+compare_symtabs( s1, s2)
+       struct symtab **s1, **s2;
+{
+       /* "most specific" first */
+
+       register struct block *b1, *b2;
+       b1 = BLOCKVECTOR_BLOCK(BLOCKVECTOR(*s1),0);
+       b2 = BLOCKVECTOR_BLOCK(BLOCKVECTOR(*s2),0);
+       if (BLOCK_END(b1) == BLOCK_END(b2))
+               return BLOCK_START(b1) - BLOCK_START(b2);
+       return BLOCK_END(b1) - BLOCK_END(b2);
+}
+
+
+/*  Partial Symtabs, same */
+
+static int
+compare_psymtabs( s1, s2)
+       struct partial_symtab **s1, **s2;
+{
+       /* Perf twist: put the ones with no code at the end */
+
+       register int a = (*s1)->textlow;
+       register int b = (*s2)->textlow;
+       if (a == 0)
+               return b;
+       if (b == 0)
+               return -a;
+       return a - b;
+}
+
+
+/* Partial symbols are compared lexicog by their print names */
+
+static int
+compare_psymbols (s1, s2)
+       register struct partial_symbol *s1, *s2;
+{
+       register char
+                      *st1 = SYMBOL_NAME(s1),
+                      *st2 = SYMBOL_NAME(s2);
+
+       return (st1[0] - st2[0] ? st1[0] - st2[0] :
+               strcmp(st1 + 1, st2 + 1));
+}
+
+/* Blocks with a smaller low bound should come first */
+
+static int compare_blocks(b1,b2)
+       struct block **b1, **b2;
+{
+       register int addr_diff;
+
+       addr_diff = (BLOCK_START((*b1))) - (BLOCK_START((*b2)));
+       if (addr_diff == 0)
+               return (BLOCK_END((*b1))) - (BLOCK_END((*b2)));
+       return addr_diff;
+}
+
+\f
+/* Sorting and reordering procedures */
+
+/* Sort the blocks of a symtab S.
+   Reorder the blocks in the blockvector by code-address,
+   as required by some MI search routines */
+
+static
+sort_blocks(s)
+       struct symtab *s;
+{
+       struct blockvector *bv = BLOCKVECTOR(s);
+
+       if (BLOCKVECTOR_NBLOCKS(bv) <= 2) {
+               /* Cosmetic */
+               if (BLOCK_END(BLOCKVECTOR_BLOCK(bv,0)) == 0)
+                       BLOCK_START(BLOCKVECTOR_BLOCK(bv,0)) = 0;
+               return;
+       }
+       /*
+        * This is very unfortunate: normally all functions are compiled in
+        * the order they are found, but if the file is compiled -O3 things
+        * are very different.  It would be nice to find a reliable test
+        * to detect -O3 images in advance.
+        */
+       if (BLOCKVECTOR_NBLOCKS(bv) > 3)
+               qsort(&BLOCKVECTOR_BLOCK(bv,2),
+                     BLOCKVECTOR_NBLOCKS(bv) - 2,
+                     sizeof(struct block *),
+                     compare_blocks);
+
+       {
+               register CORE_ADDR high = 0;
+               register int    i, j = BLOCKVECTOR_NBLOCKS(bv);
+
+               for (i = 2; i < j; i++)
+                       if (high < BLOCK_END(BLOCKVECTOR_BLOCK(bv,i)))
+                               high = BLOCK_END(BLOCKVECTOR_BLOCK(bv,i));
+               BLOCK_END(BLOCKVECTOR_BLOCK(bv,0)) = high;
+       }
+
+       BLOCK_START(BLOCKVECTOR_BLOCK(bv,0)) = BLOCK_START(BLOCKVECTOR_BLOCK(bv,2));
+
+       BLOCK_START(BLOCKVECTOR_BLOCK(bv,1)) = BLOCK_START(BLOCKVECTOR_BLOCK(bv,0));
+       BLOCK_END  (BLOCKVECTOR_BLOCK(bv,1)) = BLOCK_END  (BLOCKVECTOR_BLOCK(bv,0));
+}
+
+/* Sort the symtab list, as required by some search procedures.
+   We want files ordered to make them look right to users, and for
+   searching (see block_for_pc).  */
+
+static
+reorder_symtabs()
+{
+       register int i;
+       struct symtab *stab;
+       struct symtab **all_symtabs = (struct symtab **)
+               obstack_alloc (psymbol_obstack,
+                               all_symtabs_count * sizeof (struct symtab *));
+
+       /* Create an array of pointers to all the symtabs.  */
+       for (i = 0, stab = symtab_list;
+            i < all_symtabs_count;
+            i++, stab = stab->next) {
+               all_symtabs[i] = stab;
+               /* FIXME: Only do this for new symtabs ??? */
+               sort_blocks(all_symtabs[i]);
+       }
+
+       qsort(all_symtabs, all_symtabs_count,
+               sizeof(struct symtab *), compare_symtabs);
+
+       /* Re-construct the symtab list, but now it is sorted.  */
+       for (i = 0; i < all_symtabs_count-1; i++)
+               all_symtabs[i]->next = all_symtabs[i+1];
+       all_symtabs[i]->next = 0;
+       symtab_list = all_symtabs[0];
+       obstack_free (psymbol_obstack, all_symtabs);
+}
+
+/* Sort the partial symtab list, as required by some search procedures */
+
+static reorder_psymtabs()
+{
+       register int i;
+       struct partial_symtab *pstab;
+
+       /*
+        * PC lookups stop at the first psymtab such that
+        *      textlow <= PC < texthigh 
+        */
+       /* Create an array of pointers to all the partial_symtabs.  */
+       struct partial_symtab **all_psymtabs = (struct partial_symtab **)
+         obstack_alloc (psymbol_obstack,
+                        all_psymtabs_count*sizeof(struct partial_symtab*));
+       for (i = 0, pstab = partial_symtab_list;
+            i < all_psymtabs_count;
+            i++, pstab = pstab->next)
+         all_psymtabs[i] = pstab;
+
+       qsort(all_psymtabs, all_psymtabs_count,
+               sizeof(struct partial_symtab *), compare_psymtabs);
+
+       /* Re-construct the partial_symtab_list, but now it is sorted.  */
+
+       for (i = 0; i < all_psymtabs_count-1; i++)
+               all_psymtabs[i]->next = all_psymtabs[i+1];
+       all_psymtabs[i]->next = 0;
+       partial_symtab_list = all_psymtabs[0];
+
+       obstack_free (psymbol_obstack, all_psymtabs);
+}
+
+
+\f
+/* Constructor/restructor/destructor procedures */
+
+/* Allocate a new symtab for NAME.  Needs an estimate of how many symbols
+   MAXSYMS and linenumbers MAXLINES we'll put in it */
+
+static
+struct symtab *
+new_symtab(name, maxsyms, maxlines)
+       char *name;
+{
+       struct symtab *s = (struct symtab *) xzalloc(sizeof(struct symtab));
+       int i;
+
+       LINETABLE(s) = new_linetable(maxlines);
+
+       s->filename = name;
+
+       /* All symtabs must have at least two blocks */
+       BLOCKVECTOR(s) = new_bvect(2);
+       BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), 0) = new_block(maxsyms);
+       BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), 1) = new_block(maxsyms);
+       BLOCK_SUPERBLOCK( BLOCKVECTOR_BLOCK(BLOCKVECTOR(s),1)) =
+               BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), 0);
+
+       s->free_code = free_linetable;
+
+       /* Link the new symtab into the list of such.  */
+       s->next = symtab_list;
+       symtab_list = s;
+
+       all_symtabs_count++;
+
+       return s;
+}
+
+/* Cleanup before loading a fresh image */
+
+static destroy_all_symtabs()
+{
+  if (symfile)
+    free(symfile);
+  symfile = 0;
+
+  free_all_symtabs();
+  all_symtabs_count = 0;
+  current_source_symtab = 0;
+  /* psymtabs! */
+}
+
+/* Allocate a new partial_symtab NAME */
+
+static struct partial_symtab *
+new_psymtab(name)
+       char *name;
+{
+       struct partial_symtab *pst;
+
+       pst = (struct partial_symtab *)
+             obstack_alloc (psymbol_obstack, sizeof (*pst));
+       bzero (pst, sizeof (*pst));
+
+       if (name == (char*)-1)          /* FIXME -- why not null here? */
+               pst->filename = "<no name>";
+       else
+               pst->filename = name;
+
+       pst->next = partial_symtab_list;
+       partial_symtab_list = pst;
+       all_psymtabs_count++;
+
+       /* Keep a backpointer to the file`s symbols */
+       pst->ldsymlen = (int)cur_hdr;
+
+       /* The way to turn this into a symtab is to call... */
+       pst->read_symtab = mipscoff_psymtab_to_symtab;
+
+       return pst;
+}
+
+
+/* Allocate a new NAME psymbol from LIST, extending it if necessary.
+   The psymbol belongs to the psymtab at index PST_IDX */
+
+static struct partial_symbol *
+new_psymbol(list, name, pst_idx)
+       struct psymbol_allocation_list *list;
+       char *name;
+{
+       struct partial_symbol *p;
+       struct partial_symtab *pst = fdr_to_pst[pst_idx].pst;
+
+       /* Lists are pre-sized, we won`t overflow */
+
+       p = list->list + pst->globals_offset + pst->n_global_syms++;
+       SYMBOL_NAME(p) = name;
+       return p;
+}
+
+
+/* Allocate a linetable array of the given SIZE */
+
+static
+struct linetable *new_linetable(size)
+{
+       struct linetable *l;
+
+       size = size * sizeof(l->item) + sizeof(struct linetable);
+       l = (struct linetable *)xmalloc(size);
+       l->nitems = 0;
+       return l;
+}
+
+/* Oops, too big. Shrink it.  This was important with the 2.4 linetables,
+   I am not so sure about the 3.4 ones */
+
+static shrink_linetable(s)
+       struct symtab *s;
+{
+       struct linetable *l = new_linetable(LINETABLE(s)->nitems);
+
+       bcopy(LINETABLE(s), l,
+             LINETABLE(s)->nitems * sizeof(l->item) + sizeof(struct linetable));
+       free (LINETABLE(s));
+       LINETABLE(s) = l;
+}
+
+/* Allocate and zero a new blockvector of NBLOCKS blocks. */
+
+static
+struct blockvector *new_bvect(nblocks)
+{
+       struct blockvector *bv;
+       int size;
+
+       size = sizeof(struct blockvector) + nblocks * sizeof(struct block*);
+       bv = (struct blockvector *) xzalloc(size);
+
+       BLOCKVECTOR_NBLOCKS(bv) = nblocks;
+
+       return bv;
+}
+
+/* Allocate and zero a new block of MAXSYMS symbols */
+
+static
+struct block *new_block(maxsyms)
+{
+       int size = sizeof(struct block) + (maxsyms-1) * sizeof(struct symbol *);
+       struct block *b = (struct block *)xzalloc(size);
+
+       return b;
+}
+
+/* Ooops, too big. Shrink block B in symtab S to its minimal size */
+
+static struct block *
+shrink_block(b, s)
+       struct block *b;
+       struct symtab *s;
+{
+       struct block *new;
+       struct blockvector *bv = BLOCKVECTOR(s);
+       int i;
+
+       /* Just get a new one, copy, and fix references to the old one */
+
+       new = (struct block *)xmalloc(sizeof(struct block) +
+               (BLOCK_NSYMS(b)-1) * sizeof(struct symbol *));
+
+       bcopy(b, new, sizeof(*new) + (BLOCK_NSYMS(b) - 1) * sizeof(struct symbol*));
+
+       /* Should chase pointers to old one.  Fortunately, that`s just
+          the block`s function and inferior blocks */
+       if (BLOCK_FUNCTION(b) && SYMBOL_BLOCK_VALUE(BLOCK_FUNCTION(b)) == b)
+               SYMBOL_BLOCK_VALUE(BLOCK_FUNCTION(b)) = new;
+       for (i = 0; i < BLOCKVECTOR_NBLOCKS(bv); i++)
+               if (BLOCKVECTOR_BLOCK(bv,i) == b)
+                       BLOCKVECTOR_BLOCK(bv,i) = new;
+               else if (BLOCK_SUPERBLOCK(BLOCKVECTOR_BLOCK(bv,i)) == b)
+                       BLOCK_SUPERBLOCK(BLOCKVECTOR_BLOCK(bv,i)) = new;
+       free(b);
+       return new;
+}
+
+/* Create a new symbol with printname NAME */
+
+static
+struct symbol *
+new_symbol(name)
+       char *name;
+{
+       struct symbol *s = (struct symbol *) 
+               obstack_alloc (symbol_obstack, sizeof (struct symbol));
+
+       bzero (s, sizeof (*s));
+       SYMBOL_NAME(s) = name;
+       return s;
+}
+
+/* Create a new type with printname NAME */
+
+static
+struct type *
+new_type(name)
+       char *name;
+{
+       struct type *t = (struct type *)
+               obstack_alloc (symbol_obstack, sizeof (struct type));
+
+       bzero (t, sizeof (*t));
+       TYPE_NAME(t) = name;
+       return t;
+}
+
+/* Create and initialize a new type with printname NAME.
+   CODE and LENGTH are the initial info we put in,
+   UNS says whether the type is unsigned or not.  */
+
+static
+struct type *
+make_type(code, length, uns, name)
+     enum type_code code;
+     int length, uns;
+     char *name;
+{
+       register struct type *type;
+
+       type = (struct type *) xzalloc(sizeof(struct type));
+       TYPE_CODE(type) = code;
+       TYPE_LENGTH(type) = length;
+       TYPE_FLAGS(type) = uns ? TYPE_FLAG_UNSIGNED : 0;
+       TYPE_NAME(type) = name;
+
+       return type;
+}
+
+/* Allocate a new field named NAME to the type TYPE */
+
+static
+struct field *new_field(type,name)
+       struct type *type;
+       char *name;
+{
+       struct field *f;
+
+       /* Fields are kept in an array */
+       if (TYPE_NFIELDS(type))
+               TYPE_FIELDS(type) = (struct field*)xrealloc(TYPE_FIELDS(type),
+                       (TYPE_NFIELDS(type)+1) * sizeof(struct field));
+       else
+               TYPE_FIELDS(type) = (struct field*)xzalloc(2*sizeof(struct field));
+       f = &(TYPE_FIELD(type,TYPE_NFIELDS(type)++));
+       bzero(f, sizeof(struct field));
+       if (name)
+               f->name = name;
+       return f;
+}
+
+/* Make an enum constant for a member F of an enumerated type T */
+
+static
+make_enum_constant(f,t)
+       struct field *f;
+       struct type *t;
+{
+       struct symbol *s;
+       /*
+        * This is awful, but that`s the way it is supposed to be
+        * (BTW, no need to free the real 'type', it's a builtin)
+        */
+       f->type = (struct type *) f->bitpos;
+
+       s = new_symbol(f->name);
+       SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+       SYMBOL_CLASS(s) = LOC_CONST;
+       SYMBOL_TYPE(s) = t;
+       SYMBOL_VALUE(s) = f->bitpos;
+       add_symbol(s, top_stack->cur_block);
+}
+
+
+\f
+/* Things used for calling functions in the inferior.
+   These functions are exported to our companion
+   mips-dep.c file and are here because they play
+   with the symbol-table explicitly. */
+
+#if 0
+/* Need to make a new symbol on the fly for the dummy
+   frame we put on the stack.  Which goes in the.. */
+
+static struct symtab *dummy_symtab;
+
+/* Make up a dummy symbol for the code we put at END_PC,
+   of size SIZE, invoking a function with NARGS arguments
+   and using a frame of FRAMESIZE bytes */
+
+mips_create_dummy_symbol(end_pc, size, nargs, framesize)
+{
+       struct block   *bl;
+       struct symbol  *g;
+       struct mips_extra_func_info *gdbinfo;
+
+       /* Allocate symtab if not done already */
+       if (dummy_symtab == 0)
+               dummy_symtab = new_symtab(".dummy_symtab.", 100, 0);
+
+       /* Make a new block. Only needs one symbol */
+       bl = new_block(1);
+       BLOCK_START(bl) = end_pc - size;
+       BLOCK_END(bl) = end_pc;
+
+       BLOCK_SUPERBLOCK(bl) = BLOCKVECTOR_BLOCK(BLOCKVECTOR(dummy_symtab),0);
+       add_block(bl, dummy_symtab);
+       sort_blocks(dummy_symtab);
+
+       BLOCK_FUNCTION(bl) = new_symbol("??");
+       SYMBOL_BLOCK_VALUE(BLOCK_FUNCTION(bl)) = bl;
+       g = new_symbol(".gdbinfo.");
+       BLOCK_SYM(bl,BLOCK_NSYMS(bl)++) = g;
+
+       SYMBOL_NAMESPACE(g) = LABEL_NAMESPACE;
+       SYMBOL_CLASS(g) = LOC_CONST;
+       SYMBOL_TYPE(g) = builtin_type_void;
+       gdbinfo = (struct mips_extra_func_info *)
+               xzalloc(sizeof(struct mips_extra_func_info));
+
+       SYMBOL_VALUE(g) = (long) gdbinfo;
+
+       gdbinfo->numargs = nargs;
+       gdbinfo->framesize = framesize;
+       gdbinfo->framereg = 29;
+       gdbinfo->pcreg = 31;
+       gdbinfo->regmask = -2;
+       gdbinfo->regoffset = -4;
+       gdbinfo->fregmask = 0;  /* XXX */
+       gdbinfo->fregoffset = 0;        /* XXX */
+}
+
+/* We just returned from the dummy code at END_PC, drop its symbol */
+
+mips_destroy_dummy_symbol(end_pc)
+{
+       struct block *bl;
+       struct blockvector *bv = BLOCKVECTOR(dummy_symtab);
+       int i;
+
+       bl = block_for_pc(end_pc);
+       free(BLOCK_FUNCTION(bl));
+       free(SYMBOL_VALUE(BLOCK_SYM(bl,0)));
+       free(BLOCK_SYM(bl,0));
+
+       for (i = 2; i < BLOCKVECTOR_NBLOCKS(bv); i++)
+               if (BLOCKVECTOR_BLOCK(bv,i) == bl)
+                       break;
+       for (; i < BLOCKVECTOR_NBLOCKS(bv) - 1; i++)
+               BLOCKVECTOR_BLOCK(bv,i) = BLOCKVECTOR_BLOCK(bv,i+1);
+       BLOCKVECTOR_NBLOCKS(bv)--;
+       sort_blocks(dummy_symtab);
+       free(bl);
+}
+#endif
+
+/* Sigtramp: make sure we have all the necessary information
+   about the signal trampoline code. Since the official code
+   from MIPS does not do so, we make up that information ourselves.
+   If they fix the library (unlikely) this code will neutralize itself. */
+
+static
+fixup_sigtramp()
+{
+       struct symbol  *s;
+       struct symtab  *st;
+       struct block   *b, *b0;
+
+       sigtramp_address = -1;
+
+       /* We know it is sold as sigvec */
+       s = lookup_symbol("sigvec", 0, VAR_NAMESPACE, 0, NULL);
+
+       /* Most programs do not play with signals */
+       if (s == 0)
+               return;
+
+       b0 = SYMBOL_BLOCK_VALUE(s);
+
+       /* A label of sigvec, to be more precise */
+       s = lookup_symbol("sigtramp", b0, VAR_NAMESPACE, 0, NULL);
+
+       /* But maybe this program uses its own version of sigvec */
+       if (s == 0)
+               return;
+
+       sigtramp_address = SYMBOL_VALUE(s);
+       sigtramp_end = sigtramp_address + 0x88; /* black magic */
+
+       /* Did we or MIPSco fix the library ? */
+       if (SYMBOL_CLASS(s) == LOC_BLOCK)
+               return;
+
+       /* But what symtab does it live in ? */
+       st = find_pc_symtab(SYMBOL_VALUE(s));
+
+       /*
+        * Ok, there goes the fix: turn it into a procedure, with all the
+        * needed info.  Note we make it a nested procedure of sigvec,
+        * which is the way the (assembly) code is actually written.
+        */
+       SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+       SYMBOL_CLASS(s) = LOC_BLOCK;
+       SYMBOL_TYPE(s) = make_type(TYPE_CODE_FUNC, 4, 0, 0);
+       TYPE_TARGET_TYPE(SYMBOL_TYPE(s)) = builtin_type_void;
+
+       /* Need a block to allocate .gdbinfo. in */
+       b = new_block(1);
+       SYMBOL_BLOCK_VALUE(s) = b;
+       BLOCK_START(b) = sigtramp_address;
+       BLOCK_END(b) = sigtramp_end;
+       BLOCK_FUNCTION(b) = s;
+       BLOCK_SUPERBLOCK(b) = BLOCK_SUPERBLOCK(b0);
+       add_block(b, st);
+       sort_blocks(st);
+
+       /* Make a .gdbinfo. for it */
+       {
+               struct mips_extra_func_info *e =
+                       (struct mips_extra_func_info *)
+                       xzalloc(sizeof(struct mips_extra_func_info));
+
+               e->numargs = 0; /* the kernel thinks otherwise */
+               /* align_longword(sigcontext + SIGFRAME) */
+               e->framesize = 0x150;
+               e->framereg = SP_REGNUM;
+               e->pcreg = 31;
+               e->regmask = -2;
+               e->regoffset = -(41 * sizeof(int));
+               e->fregmask = -1;
+               e->fregoffset = -(37 * sizeof(int));
+               e->isym = (long)s;
+
+               s = new_symbol(".gdbinfo.");
+               SYMBOL_VALUE(s) = (int) e;
+               SYMBOL_NAMESPACE(s) = LABEL_NAMESPACE;
+               SYMBOL_CLASS(s) = LOC_CONST;
+               SYMBOL_TYPE(s) = builtin_type_void;
+       }
+
+       BLOCK_SYM(b,BLOCK_NSYMS(b)++) = s;
+}
+
+\f
+/* Initialization */
+
+static struct sym_fns ecoff_sym_fns = {"ecoff", 5,
+               mipscoff_new_init, mipscoff_symfile_init,
+               mipscoff_symfile_read, mipscoff_symfile_discard};
+
+_initialize_mipsread ()
+{
+       add_symtab_fns (&ecoff_sym_fns);
+
+       bzero (&global_psymbols, sizeof (global_psymbols));
+       bzero (&static_psymbols, sizeof (static_psymbols));
+
+       add_com("add-file", class_files, add_file_command,
+               "Add a new symbol table (in mips format) from file FILE.");
+
+       /* Missing basic types */
+       builtin_type_string = make_type(TYPE_CODE_PASCAL_ARRAY,
+                                       1, 0, "string");
+       builtin_type_complex = make_type(TYPE_CODE_FLT,
+                                        2 * sizeof(float), 0, "complex");
+       builtin_type_double_complex = make_type(TYPE_CODE_FLT,
+                                   2 * sizeof(double), 0, "double_complex");
+       builtin_type_fixed_dec = make_type(TYPE_CODE_INT, sizeof(int),
+                                          0, "fixed_decimal");
+       builtin_type_float_dec = make_type(TYPE_CODE_FLT, sizeof(double),
+                                          0, "floating_decimal");
+
+       /* Templates types */
+       builtin_type_ptr = lookup_pointer_type (builtin_type_void);
+       builtin_type_struct = make_type(TYPE_CODE_STRUCT, 0, 0, 0);
+       builtin_type_union = make_type(TYPE_CODE_UNION, 0, 0, 0);
+       builtin_type_enum = make_type(TYPE_CODE_ENUM, 0, 0, 0);
+       builtin_type_range = make_type(TYPE_CODE_RANGE, 0, 0, 0);
+       builtin_type_set = make_type(TYPE_CODE_SET, 0, 0, 0);
+}
diff --git a/gdb/munch b/gdb/munch
new file mode 100755 (executable)
index 0000000..8b59ed0
--- /dev/null
+++ b/gdb/munch
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# create an initialization procedure from a list of .o files
+
+echo '/* Do not modify this file.  It is created automatically by "munch". */'
+echo 'void initialize_all_files () {'
+
+# make it easy to use a different nm, e.g. for cross-developing
+MUNCH_NM=${MUNCH_NM-nm}
+if test "`$MUNCH_NM main.o | egrep 'T _?main$'`" = "" ; then
+    # System V style nm
+    shift;
+    $MUNCH_NM $* | egrep '^(.*[^a-zA-Z_]_|_)_?initialize_.*\.text' | \
+       sed -e 's/^.*\(_initialize_[a-zA-Z0-9_]*\)[^a-zA-Z0-9_].*$/   {extern void \1 (); \1 ();}/'
+else
+    # BSD style nm
+    $MUNCH_NM -p $* | egrep 'T *_?_initialize_' | \
+       sed -e 's/^.*T *_*\(.*\)/    {extern void _\1 (); _\1 ();}/'
+fi
+
+echo '}'
diff --git a/gdb/news-xdep.c b/gdb/news-xdep.c
new file mode 100644 (file)
index 0000000..58a9191
--- /dev/null
@@ -0,0 +1,65 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifdef __GNUC__
+/* Bad implement execle(3). It's depend for "/bin/cc".
+
+   main()
+   {
+     printf("execle:\n");
+     execle(FILE, ARGS, envp);
+     exit(1);
+   }
+
+   GCC:
+   link a6,#0
+   pea LC5     ; call printf
+   jbsr _printf
+   ;           ; (not popd stack)
+   pea _envp   ; call execle
+   clrl sp@-
+   pea LC4
+   pea LC4
+   pea LC4
+   pea LC3
+   pea LC6
+   jbsr _execle
+   addw #32,sp ; delayed pop !!
+
+   /bin/cc:
+   link.l      fp,#L23
+   movem.l     #L24,(sp)
+   pea L26             ; call printf
+   jbsr        _printf
+   addq.l      #4,sp   ; <--- popd stack !!
+   pea _envp           ; call execle
+   clr.l       -(sp)
+   pea L32
+   
+   */
+
+execle(name, args)
+     char *name, *args;
+{
+  register char        **env = &args;
+  while (*env++)
+    ;
+  execve(name, (char **)&args, (char **)*env);
+}
+#endif
diff --git a/gdb/nindy-tdep.c b/gdb/nindy-tdep.c
new file mode 100644 (file)
index 0000000..b609fd7
--- /dev/null
@@ -0,0 +1,77 @@
+/* Target-machine dependent code for the NINDY monitor running on the Intel 960
+   Copyright (C) 1991 Free Software Foundation, Inc.
+   Contributed by Intel Corporation.
+
+This file is part of GDB.
+
+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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Miscellaneous NINDY-dependent routines.
+   Some replace macros normally defined in "tm.h".  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+/* 'start_frame' is a variable in the NINDY runtime startup routine
+   that contains the frame pointer of the 'start' routine (the routine
+   that calls 'main').  By reading its contents out of remote memory,
+   we can tell where the frame chain ends:  backtraces should halt before
+   they display this frame.  */
+
+int
+nindy_frame_chain_valid (chain, curframe)
+    unsigned int chain;
+    FRAME curframe;
+{
+       struct symbol *sym;
+       int i;
+
+       /* crtnindy.o is an assembler module that is assumed to be linked
+        * first in an i80960 executable.  It contains the true entry point;
+        * it performs startup up initialization and then calls 'main'.
+        *
+        * 'sf' is the name of a variable in crtnindy.o that is set
+        *      during startup to the address of the first frame.
+        *
+        * 'a' is the address of that variable in 80960 memory.
+        */
+       static char sf[] = "start_frame";
+       CORE_ADDR a;
+
+
+       chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
+                          contain return status info in them.  */
+       if ( chain == 0 ){
+               return 0;
+       }
+
+       sym = lookup_symbol(sf, 0, VAR_NAMESPACE, (int *)NULL, 
+                                 (struct symtab **)NULL);
+       if ( sym != 0 ){
+               a = sym->value.value;
+       } else {
+               for ( i = 0; strcmp(misc_function_vector[i].name,sf); i++ ){
+                       if ( i >= misc_function_count ){
+                               return 0;
+                       }
+               }
+               a = misc_function_vector[i].address;
+       }
+
+       return ( chain != read_memory_integer(a,4) );
+}
diff --git a/gdb/np1-opcode.h b/gdb/np1-opcode.h
new file mode 100755 (executable)
index 0000000..6546825
--- /dev/null
@@ -0,0 +1,422 @@
+/* Print GOULD NPL instructions for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+struct gld_opcode
+{
+  char *name;
+  unsigned long opcode;
+  unsigned long mask;
+  char *args;
+  int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+   is the most any of them need.  The actual length of an instruction
+   is always at least 2 bytes, and at most four.  The length of the
+   instruction is based on the opcode.
+
+   The mask component is a mask saying which bits must match
+   particular opcode in order for an instruction to be an instance
+   of that opcode.
+
+   The args component is a string containing characters
+   that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+   r  Register in first field
+   R  Register in second field
+   b  Base register in first field
+   B  Base register in second field
+   v  Vector register in first field
+   V  Vector register in first field
+   A  Optional address register (base register)
+   X  Optional index register
+   I  Immediate data (16bits signed)
+   O  Offset field (16bits signed)
+   h  Offset field (15bits signed)
+   d  Offset field (14bits signed)
+   S  Shift count field
+
+   any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+   all instances of the same mnemonic must be consecutive.
+   All instances of the same mnemonic with the same number of operands
+   must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "lb",                0xb4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lnb",       0xb8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lbs",       0xec080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lh",                0xb4000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "lnh",       0xb8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "lw",                0xb4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lnw",       0xb8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "ld",                0xb4000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "lnd",       0xb8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "li",                0xf8000000,     0xfc7f0000,     "r,I",          4 },
+{ "lpa",       0x50080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "la",                0x50000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "labr",      0x58080000,     0xfc080000,     "b,xOA,X",      4 },
+{ "lbp",       0x90080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lhp",       0x90000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "lwp",       0x90000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "ldp",       0x90000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "suabr",     0x58000000,     0xfc080000,     "b,xOA,X",      4 },
+{ "lf",                0xbc000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lfbr",      0xbc080000,     0xfc080000,     "b,xOA,X",      4 },
+{ "lwbr",      0x5c000000,     0xfc080000,     "b,xOA,X",      4 },
+{ "stb",       0xd4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "sth",       0xd4000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "stw",       0xd4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "std",       0xd4000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "stf",       0xdc000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "stfbr",     0xdc080000,     0xfc080000,     "b,xOA,X",      4 },
+{ "stwbr",     0x54000000,     0xfc080000,     "b,xOA,X",      4 },
+{ "zmb",       0xd8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "zmh",       0xd8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "zmw",       0xd8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "zmd",       0xd8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "stbp",      0x94080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "sthp",      0x94000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "stwp",      0x94000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "stdp",      0x94000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "lil",       0xf80b0000,     0xfc7f0000,     "r,D",          4 },
+{ "lwsl1",     0xec000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lwsl2",     0xfc000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lwsl3",     0xfc080000,     0xfc080000,     "r,xOA,X",      4 },
+
+{ "lvb",       0xb0080000,     0xfc080000,     "v,xOA,X",      4 },
+{ "lvh",       0xb0000001,     0xfc080001,     "v,xOA,X",      4 },
+{ "lvw",       0xb0000000,     0xfc080000,     "v,xOA,X",      4 },
+{ "lvd",       0xb0000002,     0xfc080002,     "v,xOA,X",      4 },
+{ "liv",       0x3c040000,     0xfc0f0000,     "v,R",          2 },
+{ "livf",      0x3c080000,     0xfc0f0000,     "v,R",          2 },
+{ "stvb",      0xd0080000,     0xfc080000,     "v,xOA,X",      4 },
+{ "stvh",      0xd0000001,     0xfc080001,     "v,xOA,X",      4 },
+{ "stvw",      0xd0000000,     0xfc080000,     "v,xOA,X",      4 },
+{ "stvd",      0xd0000002,     0xfc080002,     "v,xOA,X",      4 },
+
+{ "trr",       0x2c000000,     0xfc0f0000,     "r,R",          2 },
+{ "trn",       0x2c040000,     0xfc0f0000,     "r,R",          2 },
+{ "trnd",      0x2c0c0000,     0xfc0f0000,     "r,R",          2 },
+{ "trabs",     0x2c010000,     0xfc0f0000,     "r,R",          2 },
+{ "trabsd",    0x2c090000,     0xfc0f0000,     "r,R",          2 },
+{ "trc",       0x2c030000,     0xfc0f0000,     "r,R",          2 },
+{ "xcr",       0x28040000,     0xfc0f0000,     "r,R",          2 },
+{ "cxcr",      0x2c060000,     0xfc0f0000,     "r,R",          2 },
+{ "cxcrd",     0x2c0e0000,     0xfc0f0000,     "r,R",          2 },
+{ "tbrr",      0x2c020000,     0xfc0f0000,     "r,B",          2 },
+{ "trbr",      0x28030000,     0xfc0f0000,     "b,R",          2 },
+{ "xcbr",      0x28020000,     0xfc0f0000,     "b,B",          2 },
+{ "tbrbr",     0x28010000,     0xfc0f0000,     "b,B",          2 },
+
+{ "trvv",      0x28050000,     0xfc0f0000,     "v,V",          2 },
+{ "trvvn",     0x2c050000,     0xfc0f0000,     "v,V",          2 },
+{ "trvvnd",    0x2c0d0000,     0xfc0f0000,     "v,V",          2 },
+{ "trvab",     0x2c070000,     0xfc0f0000,     "v,V",          2 },
+{ "trvabd",    0x2c0f0000,     0xfc0f0000,     "v,V",          2 },
+{ "cmpv",      0x14060000,     0xfc0f0000,     "v,V",          2 },
+{ "expv",      0x14070000,     0xfc0f0000,     "v,V",          2 },
+{ "mrvvlt",    0x10030000,     0xfc0f0000,     "v,V",          2 },
+{ "mrvvle",    0x10040000,     0xfc0f0000,     "v,V",          2 },
+{ "mrvvgt",    0x14030000,     0xfc0f0000,     "v,V",          2 },
+{ "mrvvge",    0x14040000,     0xfc0f0000,     "v,V",          2 },
+{ "mrvveq",    0x10050000,     0xfc0f0000,     "v,V",          2 },
+{ "mrvvne",    0x10050000,     0xfc0f0000,     "v,V",          2 },
+{ "mrvrlt",    0x100d0000,     0xfc0f0000,     "v,R",          2 },
+{ "mrvrle",    0x100e0000,     0xfc0f0000,     "v,R",          2 },
+{ "mrvrgt",    0x140d0000,     0xfc0f0000,     "v,R",          2 },
+{ "mrvrge",    0x140e0000,     0xfc0f0000,     "v,R",          2 },
+{ "mrvreq",    0x100f0000,     0xfc0f0000,     "v,R",          2 },
+{ "mrvrne",    0x140f0000,     0xfc0f0000,     "v,R",          2 },
+{ "trvr",      0x140b0000,     0xfc0f0000,     "r,V",          2 },
+{ "trrv",      0x140c0000,     0xfc0f0000,     "v,R",          2 },
+
+{ "bu",                0x40000000,     0xff880000,     "xOA,X",        4 },
+{ "bns",       0x70080000,     0xff880000,     "xOA,X",        4 },
+{ "bnco",      0x70880000,     0xff880000,     "xOA,X",        4 },
+{ "bge",       0x71080000,     0xff880000,     "xOA,X",        4 },
+{ "bne",       0x71880000,     0xff880000,     "xOA,X",        4 },
+{ "bunge",     0x72080000,     0xff880000,     "xOA,X",        4 },
+{ "bunle",     0x72880000,     0xff880000,     "xOA,X",        4 },
+{ "bgt",       0x73080000,     0xff880000,     "xOA,X",        4 },
+{ "bnany",     0x73880000,     0xff880000,     "xOA,X",        4 },
+{ "bs" ,       0x70000000,     0xff880000,     "xOA,X",        4 },
+{ "bco",       0x70800000,     0xff880000,     "xOA,X",        4 },
+{ "blt",       0x71000000,     0xff880000,     "xOA,X",        4 },
+{ "beq",       0x71800000,     0xff880000,     "xOA,X",        4 },
+{ "buge",      0x72000000,     0xff880000,     "xOA,X",        4 },
+{ "bult",      0x72800000,     0xff880000,     "xOA,X",        4 },
+{ "ble",       0x73000000,     0xff880000,     "xOA,X",        4 },
+{ "bany",      0x73800000,     0xff880000,     "xOA,X",        4 },
+{ "brlnk",     0x44000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bib",       0x48000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bih",       0x48080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "biw",       0x4c000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bid",       0x4c080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bivb",      0x60000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bivh",      0x60080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bivw",      0x64000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bivd",      0x64080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bvsb",      0x68000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bvsh",      0x68080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bvsw",      0x6c000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bvsd",      0x6c080000,     0xfc080000,     "r,xOA,X",      4 },
+
+{ "camb",      0x80080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "camh",      0x80000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "camw",      0x80000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "camd",      0x80000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "car",       0x10000000,     0xfc0f0000,     "r,R",          2 },
+{ "card",      0x14000000,     0xfc0f0000,     "r,R",          2 },
+{ "ci",                0xf8050000,     0xfc7f0000,     "r,I",          4 },
+{ "chkbnd",    0x5c080000,     0xfc080000,     "r,xOA,X",      4 },
+
+{ "cavv",      0x10010000,     0xfc0f0000,     "v,V",          2 },
+{ "cavr",      0x10020000,     0xfc0f0000,     "v,R",          2 },
+{ "cavvd",     0x10090000,     0xfc0f0000,     "v,V",          2 },
+{ "cavrd",     0x100b0000,     0xfc0f0000,     "v,R",          2 },
+
+{ "anmb",      0x84080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "anmh",      0x84000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "anmw",      0x84000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "anmd",      0x84000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "anr",       0x04000000,     0xfc0f0000,     "r,R",          2 },
+{ "ani",       0xf8080000,     0xfc7f0000,     "r,I",          4 },
+{ "ormb",      0xb8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "ormh",      0xb8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "ormw",      0xb8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "ormd",      0xb8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "orr",       0x08000000,     0xfc0f0000,     "r,R",          2 },
+{ "oi",                0xf8090000,     0xfc7f0000,     "r,I",          4 },
+{ "eomb",      0x8c080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "eomh",      0x8c000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "eomw",      0x8c000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "eomd",      0x8c000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "eor",       0x0c000000,     0xfc0f0000,     "r,R",          2 },
+{ "eoi",       0xf80a0000,     0xfc7f0000,     "r,I",          4 },
+
+{ "anvv",      0x04010000,     0xfc0f0000,     "v,V",          2 },
+{ "anvr",      0x04020000,     0xfc0f0000,     "v,R",          2 },
+{ "orvv",      0x08010000,     0xfc0f0000,     "v,V",          2 },
+{ "orvr",      0x08020000,     0xfc0f0000,     "v,R",          2 },
+{ "eovv",      0x0c010000,     0xfc0f0000,     "v,V",          2 },
+{ "eovr",      0x0c020000,     0xfc0f0000,     "v,R",          2 },
+
+{ "sacz",      0x100c0000,     0xfc0f0000,     "r,R",          2 },
+{ "sla",       0x1c400000,     0xfc600000,     "r,S",          2 },
+{ "sll",       0x1c600000,     0xfc600000,     "r,S",          2 },
+{ "slc",       0x24400000,     0xfc600000,     "r,S",          2 },
+{ "slad",      0x20400000,     0xfc600000,     "r,S",          2 },
+{ "slld",      0x20600000,     0xfc600000,     "r,S",          2 },
+{ "sra",       0x1c000000,     0xfc600000,     "r,S",          2 },
+{ "srl",       0x1c200000,     0xfc600000,     "r,S",          2 },
+{ "src",       0x24000000,     0xfc600000,     "r,S",          2 },
+{ "srad",      0x20000000,     0xfc600000,     "r,S",          2 },
+{ "srld",      0x20200000,     0xfc600000,     "r,S",          2 },
+{ "sda",       0x3c030000,     0xfc0f0000,     "r,R",          2 },
+{ "sdl",       0x3c020000,     0xfc0f0000,     "r,R",          2 },
+{ "sdc",       0x3c010000,     0xfc0f0000,     "r,R",          2 },
+{ "sdad",      0x3c0b0000,     0xfc0f0000,     "r,R",          2 },
+{ "sdld",      0x3c0a0000,     0xfc0f0000,     "r,R",          2 },
+
+{ "svda",      0x3c070000,     0xfc0f0000,     "v,R",          2 },
+{ "svdl",      0x3c060000,     0xfc0f0000,     "v,R",          2 },
+{ "svdc",      0x3c050000,     0xfc0f0000,     "v,R",          2 },
+{ "svdad",     0x3c0e0000,     0xfc0f0000,     "v,R",          2 },
+{ "svdld",     0x3c0d0000,     0xfc0f0000,     "v,R",          2 },
+
+{ "sbm",       0xac080000,     0xfc080000,     "f,xOA,X",      4 },
+{ "zbm",       0xac000000,     0xfc080000,     "f,xOA,X",      4 },
+{ "tbm",       0xa8080000,     0xfc080000,     "f,xOA,X",      4 },
+{ "incmb",     0xa0000000,     0xfc080000,     "xOA,X",        4 },
+{ "incmh",     0xa0080000,     0xfc080000,     "xOA,X",        4 },
+{ "incmw",     0xa4000000,     0xfc080000,     "xOA,X",        4 },
+{ "incmd",     0xa4080000,     0xfc080000,     "xOA,X",        4 },
+{ "sbmd",      0x7c080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "zbmd",      0x7c000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "tbmd",      0x78080000,     0xfc080000,     "r,xOA,X",      4 },
+
+{ "ssm",       0x9c080000,     0xfc080000,     "f,xOA,X",      4 },
+{ "zsm",       0x9c000000,     0xfc080000,     "f,xOA,X",      4 },
+{ "tsm",       0x98080000,     0xfc080000,     "f,xOA,X",      4 },
+
+{ "admb",      0xc8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "admh",      0xc8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "admw",      0xc8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "admd",      0xc8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "adr",       0x38000000,     0xfc0f0000,     "r,R",          2 },
+{ "armb",      0xe8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "armh",      0xe8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "armw",      0xe8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "armd",      0xe8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "adi",       0xf8010000,     0xfc0f0000,     "r,I",          4 },
+{ "sumb",      0xcc080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "sumh",      0xcc000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "sumw",      0xcc000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "sumd",      0xcc000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "sur",       0x3c000000,     0xfc0f0000,     "r,R",          2 },
+{ "sui",       0xf8020000,     0xfc0f0000,     "r,I",          4 },
+{ "mpmb",      0xc0080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "mpmh",      0xc0000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "mpmw",      0xc0000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "mpr",       0x38020000,     0xfc0f0000,     "r,R",          2 },
+{ "mprd",      0x3c0f0000,     0xfc0f0000,     "r,R",          2 },
+{ "mpi",       0xf8030000,     0xfc0f0000,     "r,I",          4 },
+{ "dvmb",      0xc4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "dvmh",      0xc4000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "dvmw",      0xc4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "dvr",       0x380a0000,     0xfc0f0000,     "r,R",          2 },
+{ "dvi",       0xf8040000,     0xfc0f0000,     "r,I",          4 },
+{ "exs",       0x38080000,     0xfc0f0000,     "r,R",          2 },
+
+{ "advv",      0x30000000,     0xfc0f0000,     "v,V",          2 },
+{ "advvd",     0x30080000,     0xfc0f0000,     "v,V",          2 },
+{ "adrv",      0x34000000,     0xfc0f0000,     "v,R",          2 },
+{ "adrvd",     0x34080000,     0xfc0f0000,     "v,R",          2 },
+{ "suvv",      0x30010000,     0xfc0f0000,     "v,V",          2 },
+{ "suvvd",     0x30090000,     0xfc0f0000,     "v,V",          2 },
+{ "surv",      0x34010000,     0xfc0f0000,     "v,R",          2 },
+{ "survd",     0x34090000,     0xfc0f0000,     "v,R",          2 },
+{ "mpvv",      0x30020000,     0xfc0f0000,     "v,V",          2 },
+{ "mprv",      0x34020000,     0xfc0f0000,     "v,R",          2 },
+
+{ "adfw",      0xe0080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "adfd",      0xe0080002,     0xfc080002,     "r,xOA,X",      4 },
+{ "adrfw",     0x38010000,     0xfc0f0000,     "r,R",          2 },
+{ "adrfd",     0x38090000,     0xfc0f0000,     "r,R",          2 },
+{ "surfw",     0xe0000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "surfd",     0xe0000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "surfw",     0x38030000,     0xfc0f0000,     "r,R",          2 },
+{ "surfd",     0x380b0000,     0xfc0f0000,     "r,R",          2 },
+{ "mpfw",      0xe4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "mpfd",      0xe4080002,     0xfc080002,     "r,xOA,X",      4 },
+{ "mprfw",     0x38060000,     0xfc0f0000,     "r,R",          2 },
+{ "mprfd",     0x380e0000,     0xfc0f0000,     "r,R",          2 },
+{ "rfw",       0xe4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "rfd",       0xe4000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "rrfw",      0x0c0e0000,     0xfc0f0000,     "r",            2 },
+{ "rrfd",      0x0c0f0000,     0xfc0f0000,     "r",            2 },
+
+{ "advvfw",    0x30040000,     0xfc0f0000,     "v,V",          2 },
+{ "advvfd",    0x300c0000,     0xfc0f0000,     "v,V",          2 },
+{ "adrvfw",    0x34040000,     0xfc0f0000,     "v,R",          2 },
+{ "adrvfd",    0x340c0000,     0xfc0f0000,     "v,R",          2 },
+{ "suvvfw",    0x30050000,     0xfc0f0000,     "v,V",          2 },
+{ "suvvfd",    0x300d0000,     0xfc0f0000,     "v,V",          2 },
+{ "survfw",    0x34050000,     0xfc0f0000,     "v,R",          2 },
+{ "survfd",    0x340d0000,     0xfc0f0000,     "v,R",          2 },
+{ "mpvvfw",    0x30060000,     0xfc0f0000,     "v,V",          2 },
+{ "mpvvfd",    0x300e0000,     0xfc0f0000,     "v,V",          2 },
+{ "mprvfw",    0x34060000,     0xfc0f0000,     "v,R",          2 },
+{ "mprvfd",    0x340e0000,     0xfc0f0000,     "v,R",          2 },
+{ "rvfw",      0x30070000,     0xfc0f0000,     "v",            2 },
+{ "rvfd",      0x300f0000,     0xfc0f0000,     "v",            2 },
+
+{ "fltw",      0x38070000,     0xfc0f0000,     "r,R",          2 },
+{ "fltd",      0x380f0000,     0xfc0f0000,     "r,R",          2 },
+{ "fixw",      0x38050000,     0xfc0f0000,     "r,R",          2 },
+{ "fixd",      0x380d0000,     0xfc0f0000,     "r,R",          2 },
+{ "cfpds",     0x3c090000,     0xfc0f0000,     "r,R",          2 },
+
+{ "fltvw",     0x080d0000,     0xfc0f0000,     "v,V",          2 },
+{ "fltvd",     0x080f0000,     0xfc0f0000,     "v,V",          2 },
+{ "fixvw",     0x080c0000,     0xfc0f0000,     "v,V",          2 },
+{ "fixvd",     0x080e0000,     0xfc0f0000,     "v,V",          2 },
+{ "cfpvds",    0x0c0d0000,     0xfc0f0000,     "v,V",          2 },
+
+{ "orvrn",     0x000a0000,     0xfc0f0000,     "r,V",          2 },
+{ "andvrn",    0x00080000,     0xfc0f0000,     "r,V",          2 },
+{ "frsteq",    0x04090000,     0xfc0f0000,     "r,V",          2 },
+{ "sigma",     0x0c080000,     0xfc0f0000,     "r,V",          2 },
+{ "sigmad",    0x0c0a0000,     0xfc0f0000,     "r,V",          2 },
+{ "sigmf",     0x08080000,     0xfc0f0000,     "r,V",          2 },
+{ "sigmfd",    0x080a0000,     0xfc0f0000,     "r,V",          2 },
+{ "prodf",     0x04080000,     0xfc0f0000,     "r,V",          2 },
+{ "prodfd",    0x040a0000,     0xfc0f0000,     "r,V",          2 },
+{ "maxv",      0x10080000,     0xfc0f0000,     "r,V",          2 },
+{ "maxvd",     0x100a0000,     0xfc0f0000,     "r,V",          2 },
+{ "minv",      0x14080000,     0xfc0f0000,     "r,V",          2 },
+{ "minvd",     0x140a0000,     0xfc0f0000,     "r,V",          2 },
+
+{ "lpsd",      0xf0000000,     0xfc080000,     "xOA,X",        4 },
+{ "ldc",       0xf0080000,     0xfc080000,     "xOA,X",        4 },
+{ "spm",       0x040c0000,     0xfc0f0000,     "r",            2 },
+{ "rpm",       0x040d0000,     0xfc0f0000,     "r",            2 },
+{ "tritr",     0x00070000,     0xfc0f0000,     "r",            2 },
+{ "trrit",     0x00060000,     0xfc0f0000,     "r",            2 },
+{ "rpswt",     0x04080000,     0xfc0f0000,     "r",            2 },
+{ "exr",       0xf8070000,     0xfc0f0000,     "",             4 },
+{ "halt",      0x00000000,     0xfc0f0000,     "",             2 },
+{ "wait",      0x00010000,     0xfc0f0000,     "",             2 },
+{ "nop",       0x00020000,     0xfc0f0000,     "",             2 },
+{ "eiae",      0x00030000,     0xfc0f0000,     "",             2 },
+{ "efae",      0x000d0000,     0xfc0f0000,     "",             2 },
+{ "diae",      0x000e0000,     0xfc0f0000,     "",             2 },
+{ "dfae",      0x000f0000,     0xfc0f0000,     "",             2 },
+{ "spvc",      0xf8060000,     0xfc0f0000,     "r,T,N",        4 },
+{ "rdsts",     0x00090000,     0xfc0f0000,     "r",            2 },
+{ "setcpu",    0x000c0000,     0xfc0f0000,     "r",            2 },
+{ "cmc",       0x000b0000,     0xfc0f0000,     "r",            2 },
+{ "trrcu",     0x00040000,     0xfc0f0000,     "r",            2 },
+{ "attnio",    0x00050000,     0xfc0f0000,     "",             2 },
+{ "fudit",     0x28080000,     0xfc0f0000,     "",             2 },
+{ "break",     0x28090000,     0xfc0f0000,     "",             2 },
+{ "frzss",     0x280a0000,     0xfc0f0000,     "",             2 },
+{ "ripi",      0x04040000,     0xfc0f0000,     "r,R",          2 },
+{ "xcp",       0x04050000,     0xfc0f0000,     "r",            2 },
+{ "block",     0x04060000,     0xfc0f0000,     "",             2 },
+{ "unblock",   0x04070000,     0xfc0f0000,     "",             2 },
+{ "trsc",      0x08060000,     0xfc0f0000,     "r,R",          2 },
+{ "tscr",      0x08070000,     0xfc0f0000,     "r,R",          2 },
+{ "fq",                0x04080000,     0xfc0f0000,     "r",            2 },
+{ "flupte",    0x2c080000,     0xfc0f0000,     "r",            2 },
+{ "rviu",      0x040f0000,     0xfc0f0000,     "",             2 },
+{ "ldel",      0x280c0000,     0xfc0f0000,     "r,R",          2 },
+{ "ldu",       0x280d0000,     0xfc0f0000,     "r,R",          2 },
+{ "stdecc",    0x280b0000,     0xfc0f0000,     "r,R",          2 },
+{ "trpc",      0x08040000,     0xfc0f0000,     "r",            2 },
+{ "tpcr",      0x08050000,     0xfc0f0000,     "r",            2 },
+{ "ghalt",     0x0c050000,     0xfc0f0000,     "r",            2 },
+{ "grun",      0x0c040000,     0xfc0f0000,     "",             2 },
+{ "tmpr",      0x2c0a0000,     0xfc0f0000,     "r,R",          2 },
+{ "trmp",      0x2c0b0000,     0xfc0f0000,     "r,R",          2 },
+
+{ "trrve",     0x28060000,     0xfc0f0000,     "r",            2 },
+{ "trver",     0x28070000,     0xfc0f0000,     "r",            2 },
+{ "trvlr",     0x280f0000,     0xfc0f0000,     "r",            2 },
+
+{ "linkfl",    0x18000000,     0xfc0f0000,     "r,R",          2 },
+{ "linkbl",    0x18020000,     0xfc0f0000,     "r,R",          2 },
+{ "linkfp",    0x18010000,     0xfc0f0000,     "r,R",          2 },
+{ "linkbp",    0x18030000,     0xfc0f0000,     "r,R",          2 },
+{ "linkpl",    0x18040000,     0xfc0f0000,     "r,R",          2 },
+{ "ulinkl",    0x18080000,     0xfc0f0000,     "r,R",          2 },
+{ "ulinkp",    0x18090000,     0xfc0f0000,     "r,R",          2 },
+{ "ulinktl",   0x180a0000,     0xfc0f0000,     "r,R",          2 },
+{ "ulinktp",   0x180b0000,     0xfc0f0000,     "r,R",          2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+                               sizeof(gld_opcodes[0]);
diff --git a/gdb/ns32k-opcode.h b/gdb/ns32k-opcode.h
new file mode 100644 (file)
index 0000000..5f336e9
--- /dev/null
@@ -0,0 +1,328 @@
+/* ns32k-opcode.h */
+
+#ifndef ns32k_opcodeT
+#define ns32k_opcodeT int
+#endif /* no ns32k_opcodeT */
+
+struct not_wot                 /* ns32k opcode table: wot to do with this */
+                               /* particular opcode */
+{
+  int obits;           /* number of opcode bits */
+  int ibits;           /* number of instruction bits */
+  ns32k_opcodeT        code;   /* op-code (may be > 8 bits!) */
+  char *args;          /* how to compile said opcode */
+};
+
+struct not                     /* ns32k opcode text */
+{
+  char *            name;      /* opcode name: lowercase string  [key]  */
+  struct not_wot    detail;    /* rest of opcode table          [datum] */
+};
+
+/* Instructions look like this:
+    
+   basic instruction--1, 2, or 3 bytes
+   index byte for operand A, if operand A is indexed--1 byte
+   index byte for operand B, if operand B is indexed--1 byte
+   addressing extension for operand A
+   addressing extension for operand B
+   implied operands
+
+   Operand A is the operand listed first in the following opcode table.
+   Operand B is the operand listed second in the following opcode table.
+   All instructions have at most 2 general operands, so this is enough.
+   The implied operands are associated with operands other than A and B.
+
+   Each operand has a digit and a letter.
+   
+   The digit gives the position in the assembly language.  The letter,
+   one of the following, tells us what kind of operand it is.  */
+
+/* F : 32 bit float
+ * L : 64 bit float
+ * B : byte
+ * W : word
+ * D : double-word
+ * Q : quad-word
+ * d : displacement
+ * q : quick
+ * i : immediate (8 bits)
+ * r : register number (3 bits)
+ * p : displacement - pc relative addressing
+*/
+static struct not
+notstrs[] =
+{
+  { "absf",    14,24,  0x35be, "1F2F" },
+  { "absl",    14,24,  0x34be, "1L2L" },
+  { "absb",    14,24,  0x304e, "1B2B" },
+  { "absw",    14,24,  0x314e, "1W2W" },
+  { "absd",    14,24,  0x334e, "1D2D" },
+  { "acbb",     7,16,  0x4c,   "2B1q3p" },
+  { "acbw",      7,16,  0x4d,   "2W1q3p" },
+  { "acbd",      7,16,  0x4f,   "2D1q3p" },
+  { "addf",    14,24,  0x01be, "1F2F" },
+  { "addl",    14,24,  0x00be, "1L2L" },
+  { "addb",     6,16,  0x00,   "1B2B" },
+  { "addw",     6,16,  0x01,   "1W2W" },
+  { "addd",     6,16,  0x03,   "1D2D" },
+  { "addcb",    6,16,  0x10,   "1B2B" },
+  { "addcw",    6,16,  0x11,   "1W2W" },
+  { "addcd",    6,16,  0x13,   "1D2D" },
+  { "addpb",   14,24,  0x3c4e, "1B2B" },
+  { "addpw",   14,24,  0x3d4e, "1W2W" },
+  { "addpd",   14,24,  0x3f4e, "1D2D" },
+  { "addqb",    7,16,  0x0c,   "2B1q" },
+  { "addqw",    7,16,  0x0d,   "2W1q" },
+  { "addqd",    7,16,  0x0f,   "2D1q" },
+  { "addr",     6,16,  0x27,   "1D2D" },
+  { "adjspb",  11,16,  0x057c, "1B" },
+  { "adjspw",  11,16,  0x057d, "1W" },
+  { "adjspd",  11,16,  0x057f, "1D" },
+  { "andb",     6,16,  0x28,   "1B2B" },
+  { "andw",     6,16,  0x29,   "1W2W" },
+  { "andd",     6,16,  0x2b,   "1D2D" },
+  { "ashb",    14,24,  0x044e, "1B2B" },
+  { "ashw",    14,24,  0x054e, "1B2W" },
+  { "ashd",    14,24,  0x074e, "1B2D" },
+  { "beq",      8,8,   0x0a,   "1p" },
+  { "bne",      8,8,   0x1a,   "1p" },
+  { "bcs",      8,8,   0x2a,   "1p" },
+  { "bcc",      8,8,   0x3a,   "1p" },
+  { "bhi",      8,8,   0x4a,   "1p" },
+  { "bls",      8,8,   0x5a,   "1p" },
+  { "bgt",      8,8,   0x6a,   "1p" },
+  { "ble",      8,8,   0x7a,   "1p" },
+  { "bfs",      8,8,   0x8a,   "1p" },
+  { "bfc",      8,8,   0x9a,   "1p" },
+  { "blo",      8,8,   0xaa,   "1p" },
+  { "bhs",      8,8,   0xba,   "1p" },
+  { "blt",      8,8,   0xca,   "1p" },
+  { "bge",      8,8,   0xda,   "1p" },
+  { "bicb",     6,16,  0x08,   "1B2B" },
+  { "bicw",     6,16,  0x09,   "1W2W" },
+  { "bicd",     6,16,  0x0b,   "1D2D" },
+  { "bicpsrb", 11,16,  0x17c,  "1B" },
+  { "bicpsrw", 11,16,  0x17d,  "1W" },
+  { "bispsrb", 11,16,  0x37c,  "1B" },
+  { "bispsrw", 11,16,  0x37d,  "1W" },
+  { "bpt",      8,8,   0xf2,   "" },
+  { "br",       8,8,   0xea,   "1p" },
+  { "bsr",      8,8,   0x02,   "1p" },
+  { "caseb",   11,16,  0x77c,  "1B" },
+  { "casew",   11,16,  0x77d,  "1W" },
+  { "cased",   11,16,  0x77f,  "1D" },
+  { "cbitb",   14,24,  0x084e, "1B2D" },
+  { "cbitw",   14,24,  0x094e, "1W2D" },
+  { "cbitd",   14,24,  0x0b4e, "1D2D" },
+  { "cbitib",  14,24,  0x0c4e, "1B2D" },
+  { "cbitiw",  14,24,  0x0d4e, "1W2D" },
+  { "cbitid",  14,24,  0x0f4e, "1D2D" },
+  { "checkb",  11,24,  0x0ee,  "2A3B1r" },
+  { "checkw",  11,24,  0x1ee,  "2A3B1r" },
+  { "checkd",  11,24,  0x3ee,  "2A3D1r" },
+  { "cmpf",    14,24,  0x09be, "1F2F" },
+  { "cmpl",    14,24,  0x08be, "1L2L" },
+  { "cmpb",     6,16,  0x04,   "1B2B" },
+  { "cmpw",     6,16,  0x05,   "1W2W" },
+  { "cmpd",     6,16,  0x07,   "1D2D" },
+  { "cmpmb",   14,24,  0x04ce, "1D2D3d" },
+  { "cmpmw",   14,24,  0x05ce, "1D2D3d" },
+  { "cmpmd",   14,24,  0x07ce, "1D2D3d" },
+  { "cmpqb",    7,16,  0x1c,   "2B1q" },
+  { "cmpqw",    7,16,  0x1d,   "2W1q" },
+  { "cmpqd",    7,16,  0x1f,   "2D1q" },
+  { "cmpsb",   16,16,  0x040e, "1i" },
+  { "cmpsw",   16,16,  0x050e, "1i" },
+  { "cmpsd",   16,16,  0x070e, "1i" },
+  { "cmpst",   16,16,  0x840e, "1i" },
+  { "comb",    14,24,  0x344e, "1B2B" },
+  { "comw",    14,24,  0x354e, "1W2W" },
+  { "comd",    14,24,  0x374e, "1D2D" },
+  { "cvtp",    11,24,  0x036e, "2D3D1r" },
+  { "cxp",      8,8,   0x22,   "1p" },
+  { "cxpd",    11,16,  0x07f,  "1D" },
+  { "deib",    14,24,  0x2cce, "1B2W" },
+  { "deiw",    14,24,  0x2dce, "1W2D" },
+  { "deid",    14,24,  0x2fce, "1D2Q" },
+  { "dia",      8,8,   0xc2,   "" },
+  { "divf",    14,24,  0x21be, "1F2F" },
+  { "divl",    14,24,  0x20be, "1L2L" },
+  { "divb",    14,24,  0x3cce, "1B2B" },
+  { "divw",    14,24,  0x3dce, "1W2W" },
+  { "divd",    14,24,  0x3fce, "1D2D" },
+  { "enter",    8,8,   0x82,   "1i2d" },
+  { "exit",     8,8,   0x92,   "1i" },
+  { "extb",    11,24,  0x02e,  "2D3B1r4d" },
+  { "extw",    11,24,  0x12e,  "2D3W1r4d" },
+  { "extd",    11,24,  0x32e,  "2D3D1r4d" },
+  { "extsb",   14,24,  0x0cce, "1D2B3i" },
+  { "extsw",   14,24,  0x0dce, "1D2W3i" },
+  { "extsd",   14,24,  0x0fce, "1D2D3i" },
+  { "ffsb",    14,24,  0x046e, "1B2B" },
+  { "ffsw",    14,24,  0x056e, "1W2B" },
+  { "ffsd",    14,24,  0x076e, "1D2B" },
+  { "flag",     8,8,   0xd2,   "" },
+  { "floorfb", 14,24,  0x3c3e, "1F2B" },
+  { "floorfw", 14,24,  0x3d3e, "1F2W" },
+  { "floorfd", 14,24,  0x3f3e, "1F2D" },
+  { "floorlb", 14,24,  0x383e, "1L2B" },
+  { "floorlw", 14,24,  0x393e, "1L2W" },
+  { "floorld", 14,24,  0x3b3e, "1L2D" },
+  { "ibitb",   14,24,  0x384e, "1B2D" },
+  { "ibitw",   14,24,  0x394e, "1W2D" },
+  { "ibitd",   14,24,  0x3b4e, "1D2D" },
+  { "indexb",  11,24,  0x42e,  "2B3B1r" },
+  { "indexw",  11,24,  0x52e,  "2W3W1r" },
+  { "indexd",  11,24,  0x72e,  "2D3D1r" },
+  { "insb",    11,24,  0x0ae,  "2B3B1r4d" },
+  { "insw",    11,24,  0x1ae,  "2W3W1r4d" },
+  { "insd",    11,24,  0x3ae,  "2D3D1r4d" },
+  { "inssb",   14,24,  0x08ce, "1B2D3i" },
+  { "inssw",   14,24,  0x09ce, "1W2D3i" },
+  { "inssd",   14,24,  0x0bce, "1D2D3i" },
+  { "jsr",     11,16,  0x67f,  "1A" },
+  { "jump",    11,16,  0x27f,  "1A" },
+  { "lfsr",    19,24,  0x00f3e,"1D" },
+  { "lmr",     15,24,  0x0b1e, "2D1q" },
+  { "lprb",     7,16,  0x6c,   "2B1q" },
+  { "lprw",     7,16,  0x6d,   "2W1q" },
+  { "lprd",     7,16,  0x6f,   "2D1q" },
+  { "lshb",    14,24,  0x144e, "1B2B" },
+  { "lshw",    14,24,  0x154e, "1B2W" },
+  { "lshd",    14,24,  0x174e, "1B2D" },
+  { "meib",    14,24,  0x24ce, "1B2W" },
+  { "meiw",    14,24,  0x25ce, "1W2D" },
+  { "meid",    14,24,  0x27ce, "1D2Q" },
+  { "modb",    14,24,  0x38ce, "1B2B" },
+  { "modw",    14,24,  0x39ce, "1W2W" },
+  { "modd",    14,24,  0x3bce, "1D2D" },
+  { "movf",    14,24,  0x05be, "1F2F" },
+  { "movl",    14,24,  0x04be, "1L2L" },
+  { "movb",     6,16,  0x14,   "1B2B" },
+  { "movw",     6,16,  0x15,   "1W2W" },
+  { "movd",     6,16,  0x17,   "1D2D" },
+  { "movbf",   14,24,  0x043e, "1B2F" },
+  { "movwf",   14,24,  0x053e, "1W2F" },
+  { "movdf",   14,24,  0x073e, "1D2F" },
+  { "movbl",   14,24,  0x003e, "1B2L" },
+  { "movwl",   14,24,  0x013e, "1W2L" },
+  { "movdl",   14,24,  0x033e, "1D2L" },
+  { "movfl",   14,24,  0x1b3e, "1F2L" },
+  { "movlf",   14,24,  0x163e, "1L2F" },
+  { "movmb",   14,24,  0x00ce, "1D2D3d" },
+  { "movmw",   14,24,  0x00de, "1D2D3d" },
+  { "movmd",   14,24,  0x00fe, "1D2D3d" },
+  { "movqb",    7,16,  0x5c,   "2B1q" },
+  { "movqw",    7,16,  0x5d,   "2B1q" },
+  { "movqd",    7,16,  0x5f,   "2B1q" },
+  { "movsb",   16,16,  0x000e, "1i" },
+  { "movsw",   16,16,  0x010e, "1i" },
+  { "movsd",   16,16,  0x030e, "1i" },
+  { "movst",   16,16,  0x800e, "1i" },
+  { "movsub",  14,24,  0x0cae, "1A1A" },
+  { "movsuw",  14,24,  0x0dae, "1A1A" },
+  { "movsud",  14,24,  0x0fae, "1A1A" },
+  { "movusb",  14,24,  0x1cae, "1A1A" },
+  { "movusw",  14,24,  0x1dae, "1A1A" },
+  { "movusd",  14,24,  0x1fae, "1A1A" },
+  { "movxbd",  14,24,  0x1cce, "1B2D" },
+  { "movxwd",  14,24,  0x1dce, "1W2D" },
+  { "movxbw",  14,24,  0x10ce, "1B2W" },
+  { "movzbd",  14,24,  0x18ce, "1B2D" },
+  { "movzwd",  14,24,  0x19ce, "1W2D" },
+  { "movzbw",  14,24,  0x14ce, "1B2W" },
+  { "mulf",    14,24,  0x31be, "1F2F" },
+  { "mull",    14,24,  0x30be, "1L2L" },
+  { "mulb",    14,24,  0x20ce, "1B2B" },
+  { "mulw",    14,24,  0x21ce, "1W2W" },
+  { "muld",    14,24,  0x23ce, "1D2D" },
+  { "negf",    14,24,  0x15be, "1F2F" },
+  { "negl",    14,24,  0x14be, "1L2L" },
+  { "negb",    14,24,  0x204e, "1B2B" },
+  { "negw",    14,24,  0x214e, "1W2W" },
+  { "negd",    14,24,  0x234e, "1D2D" },
+  { "nop",      8,8,   0xa2,   "" },
+  { "notb",    14,24,  0x244e, "1B2B" },
+  { "notw",    14,24,  0x254e, "1W2W" },
+  { "notd",    14,24,  0x274e, "1D2D" },
+  { "orb",      6,16,  0x18,   "1B1B" },
+  { "orw",      6,16,  0x19,   "1W1W" },
+  { "ord",      6,16,  0x1b,   "1D2D" },
+  { "quob",    14,24,  0x30ce, "1B2B" },
+  { "quow",    14,24,  0x31ce, "1W2W" },
+  { "quod",    14,24,  0x33ce, "1D2D" },
+  { "rdval",   19,24,  0x0031e,"1A" },
+  { "remb",    14,24,  0x34ce, "1B2B" },
+  { "remw",    14,24,  0x35ce, "1W2W" },
+  { "remd",    14,24,  0x37ce, "1D2D" },
+  { "restore",  8,8,   0x72,   "1i" },
+  { "ret",      8,8,   0x12,   "1d" },
+  { "reti",     8,8,   0x52,   "" },
+  { "rett",     8,8,   0x42,   "" },
+  { "rotb",    14,24,  0x004e, "1B2B" },
+  { "rotw",    14,24,  0x014e, "1B2W" },
+  { "rotd",    14,24,  0x034e, "1B2D" },
+  { "roundfb", 14,24,  0x243e, "1F2B" },
+  { "roundfw", 14,24,  0x253e, "1F2W" },
+  { "roundfd", 14,24,  0x273e, "1F2D" },
+  { "roundlb", 14,24,  0x203e, "1L2B" },
+  { "roundlw", 14,24,  0x213e, "1L2W" },
+  { "roundld", 14,24,  0x233e, "1L2D" },
+  { "rxp",      8,8,   0x32,   "1d" },
+  { "sCONDb",   7,16,  0x3c,   "2B1q" },
+  { "sCONDw",   7,16,  0x3d,   "2D1q" },
+  { "sCONDd",   7,16,  0x3f,   "2D1q" },
+  { "save",     8,8,   0x62,   "1i" },
+  { "sbitb",   14,24,  0x184e, "1B2A" },
+  { "sbitw",   14,24,  0x194e, "1W2A" },
+  { "sbitd",   14,24,  0x1b4e, "1D2A" },
+  { "sbitib",  14,24,  0x1c4e, "1B2A" },
+  { "sbitiw",  14,24,  0x1d4e, "1W2A" },
+  { "sbitid",  14,24,  0x1f4e, "1D2A" },
+  { "setcfg",  15,24,  0x0b0e, "5D1q" },
+  { "sfsr",    14,24,  0x673e, "5D1D" },
+  { "skpsb",   16,16,  0x0c0e, "1i" },
+  { "skpsw",   16,16,  0x0d0e, "1i" },
+  { "skpsd",   16,16,  0x0f0e, "1i" },
+  { "skpst",   16,16,  0x8c0e, "1i" },
+  { "smr",     15,24,  0x0f1e, "2D1q" },
+  { "sprb",     7,16,  0x2c,   "2B1q" },
+  { "sprw",     7,16,  0x2d,   "2W1q" },
+  { "sprd",     7,16,  0x2f,   "2D1q" },
+  { "subf",    14,24,  0x11be, "1F2F" },
+  { "subl",    14,24,  0x10be, "1L2L" },
+  { "subb",     6,16,  0x20,   "1B2B" },
+  { "subw",     6,16,  0x21,   "1W2W" },
+  { "subd",     6,16,  0x23,   "1D2D" },
+  { "subcb",    6,16,  0x30,   "1B2B" },
+  { "subcw",    6,16,  0x31,   "1W2W" },
+  { "subcd",    6,16,  0x33,   "1D2D" },
+  { "subpb",   14,24,  0x2c4e, "1B2B" },
+  { "subpw",   14,24,  0x2d4e, "1W2W" },
+  { "subpd",   14,24,  0x2f4e, "1D2D" },
+#ifndef NS32K_SVC_IMMED_OPERANDS
+  { "svc",      8,8,   0xe2,   "2i1i" }, /* not really, but unix uses it */
+#else
+  { "svc",      8,8,   0xe2,   "" }, /* not really, but unix uses it */
+#endif
+  { "tbitb",    6,16,  0x34,   "1B2A" },
+  { "tbitw",    6,16,  0x35,   "1W2A" },
+  { "tbitd",    6,16,  0x37,   "1D2A" },
+  { "truncfb", 14,24,  0x2c3e, "1F2B" },
+  { "truncfw", 14,24,  0x2d3e, "1F2W" },
+  { "truncfd", 14,24,  0x2f3e, "1F2D" },
+  { "trunclb", 14,24,  0x283e, "1L2B" },
+  { "trunclw", 14,24,  0x293e, "1L2W" },
+  { "truncld", 14,24,  0x2b3e, "1L2D" },
+  { "wait",     8,8,   0xb2,   "" },
+  { "wrval",   19,24,  0x0071e,"1A" },
+  { "xorb",     6,16,  0x38,   "1B2B" },
+  { "xorw",     6,16,  0x39,   "1W2W" },
+  { "xord",     6,16,  0x3b,   "1D2D" },
+};                             /* notstrs */
+
+/* end: ns32k.opcode.h */
+
+#define MAX_ARGS 4
+#define ARG_LEN 50
diff --git a/gdb/ns32k-pinsn.c b/gdb/ns32k-pinsn.c
new file mode 100644 (file)
index 0000000..1c558e9
--- /dev/null
@@ -0,0 +1,523 @@
+/* Print 32000 instructions for GDB, the GNU debugger.
+   Copyright (C) 1986,1988 Free Software Foundation, Inc.
+
+GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY.  No author or distributor accepts responsibility to anyone
+for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.
+Refer to the GDB General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute GDB,
+but only under the conditions described in the GDB General Public
+License.  A copy of this license is supposed to have been given to you
+along with GDB so you can know your rights and responsibilities.  It
+should be in a file named COPYING.  Among other things, the copyright
+notice and this notice must be preserved on all copies.
+
+In other words, go ahead and share GDB, but don't try to stop
+anyone else from sharing it farther.  Help stamp out software hoarding!
+*/
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "ns32k-opcode.h"
+#include "gdbcore.h"
+
+/* 32000 instructions are never longer than this.  */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof notstrs / sizeof notstrs[0])
+
+extern char *reg_names[];
+
+#define NEXT_IS_ADDR   '|'
+
+/*
+ * extract "count" bits starting "offset" bits
+ * into buffer
+ */
+
+int
+bit_extract (buffer, offset, count)
+     char *buffer;
+     int offset;
+     int count;
+{
+  int result;
+  int mask;
+  int bit;
+
+  buffer += offset >> 3;
+  offset &= 7;
+  bit = 1;
+  result = 0;
+  while (count--) 
+    {
+      if ((*buffer & (1 << offset)))
+       result |= bit;
+      if (++offset == 8)
+       {
+         offset = 0;
+         buffer++;
+       }
+      bit <<= 1;
+    }
+  return result;
+}
+
+float
+fbit_extract (buffer, offset, count)
+{
+  union {
+    int ival;
+    float fval;
+  } foo;
+
+  foo.ival = bit_extract (buffer, offset, 32);
+  return foo.fval;
+}
+
+double
+dbit_extract (buffer, offset, count)
+{
+  union {
+    struct {int low, high; } ival;
+    double dval;
+  } foo;
+
+  foo.ival.low = bit_extract (buffer, offset, 32);
+  foo.ival.high = bit_extract (buffer, offset+32, 32);
+  return foo.dval;
+}
+
+sign_extend (value, bits)
+{
+  value = value & ((1 << bits) - 1);
+  return (value & (1 << (bits-1))
+         ? value | (~((1 << bits) - 1))
+         : value);
+}
+
+flip_bytes (ptr, count)
+     char *ptr;
+     int count;
+{
+  char tmp;
+
+  while (count > 0)
+    {
+      tmp = *ptr;
+      ptr[0] = ptr[count-1];
+      ptr[count-1] = tmp;
+      ptr++;
+      count -= 2;
+    }
+}
+\f
+/* Given a character C, does it represent a general addressing mode?  */
+#define Is_gen(c) \
+  ((c) == 'F' || (c) == 'L' || (c) == 'B' \
+   || (c) == 'W' || (c) == 'D' || (c) == 'A')
+
+/* Adressing modes.  */
+#define Adrmod_index_byte 0x1c
+#define Adrmod_index_word 0x1d
+#define Adrmod_index_doubleword 0x1e
+#define Adrmod_index_quadword 0x1f
+
+/* Is MODE an indexed addressing mode?  */
+#define Adrmod_is_index(mode) \
+  (mode == Adrmod_index_byte \
+   || mode == Adrmod_index_word \
+   || mode == Adrmod_index_doubleword \
+   || mode == Adrmod_index_quadword)
+
+\f
+/* Print the 32000 instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  unsigned char buffer[MAXLEN];
+  register int i;
+  register unsigned char *p;
+  register char *d;
+  unsigned short first_word;
+  int gen, disp;
+  int ioffset;         /* bits into instruction */
+  int aoffset;         /* bits into arguments */
+  char arg_bufs[MAX_ARGS+1][ARG_LEN];
+  int argnum;
+  int maxarg;
+
+  read_memory (memaddr, buffer, MAXLEN);
+
+  first_word = *(unsigned short *) buffer;
+  for (i = 0; i < NOPCODES; i++)
+    if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
+       == notstrs[i].detail.code)
+      break;
+
+  /* Handle undefined instructions.  */
+  if (i == NOPCODES)
+    {
+      fprintf (stream, "0%o", buffer[0]);
+      return 1;
+    }
+
+  fprintf (stream, "%s", notstrs[i].name);
+
+  ioffset = notstrs[i].detail.ibits;
+  aoffset = notstrs[i].detail.ibits;
+  d = notstrs[i].detail.args;
+
+  if (*d)
+    {
+      /* Offset in bits of the first thing beyond each index byte.
+        Element 0 is for operand A and element 1 is for operand B.
+        The rest are irrelevant, but we put them here so we don't
+        index outside the array.  */
+      int index_offset[MAX_ARGS];
+
+      /* 0 for operand A, 1 for operand B, greater for other args.  */
+      int whicharg = 0;
+      
+      fputc ('\t', stream);
+
+      maxarg = 0;
+
+      /* First we have to find and keep track of the index bytes,
+        if we are using scaled indexed addressing mode, since the index
+        bytes occur right after the basic instruction, not as part
+        of the addressing extension.  */
+      if (Is_gen(d[1]))
+       {
+         int addr_mode = bit_extract (buffer, ioffset - 5, 5);
+
+         if (Adrmod_is_index (addr_mode))
+           {
+             aoffset += 8;
+             index_offset[0] = aoffset;
+           }
+       }
+      if (d[2] && Is_gen(d[3]))
+       {
+         int addr_mode = bit_extract (buffer, ioffset - 10, 5);
+
+         if (Adrmod_is_index (addr_mode))
+           {
+             aoffset += 8;
+             index_offset[1] = aoffset;
+           }
+       }
+
+      while (*d)
+       {
+         argnum = *d - '1';
+         d++;
+         if (argnum > maxarg && argnum < MAX_ARGS)
+           maxarg = argnum;
+         ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
+                                   memaddr, arg_bufs[argnum],
+                                   index_offset[whicharg]);
+         d++;
+         whicharg++;
+       }
+      for (argnum = 0; argnum <= maxarg; argnum++)
+       {
+         CORE_ADDR addr;
+         char *ch, *index ();
+         for (ch = arg_bufs[argnum]; *ch;)
+           {
+             if (*ch == NEXT_IS_ADDR)
+               {
+                 ++ch;
+                 addr = atoi (ch);
+                 print_address (addr, stream);
+                 while (*ch && *ch != NEXT_IS_ADDR)
+                   ++ch;
+                 if (*ch)
+                   ++ch;
+               }
+             else
+               putc (*ch++, stream);
+           }
+         if (argnum < maxarg)
+           fprintf (stream, ", ");
+       }
+    }
+  return aoffset / 8;
+}
+
+/* Print an instruction operand of category given by d.  IOFFSET is
+   the bit position below which small (<1 byte) parts of the operand can
+   be found (usually in the basic instruction, but for indexed
+   addressing it can be in the index byte).  AOFFSETP is a pointer to the
+   bit position of the addressing extension.  BUFFER contains the
+   instruction.  ADDR is where BUFFER was read from.  Put the disassembled
+   version of the operand in RESULT.  INDEX_OFFSET is the bit position
+   of the index byte (it contains garbage if this operand is not a
+   general operand using scaled indexed addressing mode).  */
+
+print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
+     char d;
+     int ioffset, *aoffsetp;
+     char *buffer;
+     CORE_ADDR addr;
+     char *result;
+     int index_offset;
+{
+  int addr_mode;
+  float Fvalue;
+  double Lvalue;
+  int Ivalue;
+  int disp1, disp2;
+  int index;
+
+  switch (d)
+    {
+    case 'F':
+    case 'L':
+    case 'B':
+    case 'W':
+    case 'D':
+    case 'A':
+      addr_mode = bit_extract (buffer, ioffset-5, 5);
+      ioffset -= 5;
+      switch (addr_mode)
+       {
+       case 0x0: case 0x1: case 0x2: case 0x3:
+       case 0x4: case 0x5: case 0x6: case 0x7:
+         switch (d)
+           {
+           case 'F':
+           case 'L':
+             sprintf (result, "f%d", addr_mode);
+             break;
+           default:
+             sprintf (result, "r%d", addr_mode);
+           }
+         break;
+       case 0x8: case 0x9: case 0xa: case 0xb:
+       case 0xc: case 0xd: case 0xe: case 0xf:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
+         break;
+       case 0x10:
+       case 0x11:
+       case 0x12:
+         disp1 = get_displacement (buffer, aoffsetp);
+         disp2 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(%d(%s))", disp2, disp1,
+                  addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
+         break;
+       case 0x13:
+         sprintf (result, "reserved");
+         break;
+       case 0x14:
+         switch (d)
+           {
+           case 'B':
+             Ivalue = bit_extract (buffer, *aoffsetp, 8);
+             Ivalue = sign_extend (Ivalue, 8);
+             *aoffsetp += 8;
+             sprintf (result, "$%d", Ivalue);
+             break;
+           case 'W':
+             Ivalue = bit_extract (buffer, *aoffsetp, 16);
+             flip_bytes (&Ivalue, 2);
+             *aoffsetp += 16;
+             Ivalue = sign_extend (Ivalue, 16);
+             sprintf (result, "$%d", Ivalue);
+             break;
+           case 'D':
+             Ivalue = bit_extract (buffer, *aoffsetp, 32);
+             flip_bytes (&Ivalue, 4);
+             *aoffsetp += 32;
+             sprintf (result, "$%d", Ivalue);
+             break;
+           case 'A':
+             Ivalue = bit_extract (buffer, *aoffsetp, 32);
+             flip_bytes (&Ivalue, 4);
+             *aoffsetp += 32;
+             sprintf (result, "$|%d|", Ivalue);
+             break;
+           case 'F':
+             Fvalue = fbit_extract (buffer, *aoffsetp, 32);
+             flip_bytes (&Fvalue, 4);
+             *aoffsetp += 32;
+             sprintf (result, "$%g", Fvalue);
+             break;
+           case 'L':
+             Lvalue = dbit_extract (buffer, *aoffsetp, 64);
+             flip_bytes (&Lvalue, 8);
+             *aoffsetp += 64;
+             sprintf (result, "$%g", Lvalue);
+             break;
+           }
+         break;
+       case 0x15:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "@|%d|", disp1);
+         break;
+       case 0x16:
+         disp1 = get_displacement (buffer, aoffsetp);
+         disp2 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "EXT(%d) + %d", disp1, disp2);
+         break;
+       case 0x17:
+         sprintf (result, "tos");
+         break;
+       case 0x18:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(fp)", disp1);
+         break;
+       case 0x19:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(sp)", disp1);
+         break;
+       case 0x1a:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "%d(sb)", disp1);
+         break;
+       case 0x1b:
+         disp1 = get_displacement (buffer, aoffsetp);
+         sprintf (result, "|%d|", addr + disp1);
+         break;
+       case 0x1c:
+       case 0x1d:
+       case 0x1e:
+       case 0x1f:
+         index = bit_extract (buffer, index_offset - 8, 3);
+         print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
+                         result, 0);
+         {
+           static char *ind[] = {"b", "w", "d", "q"};
+           char *off;
+
+           off = result + strlen (result);
+           sprintf (off, "[r%d:%s]", index,
+                    ind[addr_mode & 3]);
+         }
+         break;
+       }
+      break;
+    case 'q':
+      Ivalue = bit_extract (buffer, ioffset-4, 4);
+      Ivalue = sign_extend (Ivalue, 4);
+      sprintf (result, "%d", Ivalue);
+      ioffset -= 4;
+      break;
+    case 'r':
+      Ivalue = bit_extract (buffer, ioffset-3, 3);
+      sprintf (result, "r%d", Ivalue&7);
+      ioffset -= 3;
+      break;
+    case 'd':
+      sprintf (result, "%d", get_displacement (buffer, aoffsetp));
+      break;
+    case 'p':
+      sprintf (result, "%c%d%c", NEXT_IS_ADDR,
+              addr + get_displacement (buffer, aoffsetp),
+              NEXT_IS_ADDR);
+      break;
+    case 'i':
+      Ivalue = bit_extract (buffer, *aoffsetp, 8);
+      *aoffsetp += 8;
+      sprintf (result, "0x%x", Ivalue);
+      break;
+    }
+  return ioffset;
+}
+
+get_displacement (buffer, aoffsetp)
+     char *buffer;
+     int *aoffsetp;
+{
+  int Ivalue;
+
+  Ivalue = bit_extract (buffer, *aoffsetp, 8);
+  switch (Ivalue & 0xc0)
+    {
+    case 0x00:
+    case 0x40:
+      Ivalue = sign_extend (Ivalue, 7);
+      *aoffsetp += 8;
+      break;
+    case 0x80:
+      Ivalue = bit_extract (buffer, *aoffsetp, 16);
+      flip_bytes (&Ivalue, 2);
+      Ivalue = sign_extend (Ivalue, 14);
+      *aoffsetp += 16;
+      break;
+    case 0xc0:
+      Ivalue = bit_extract (buffer, *aoffsetp, 32);
+      flip_bytes (&Ivalue, 4);
+      Ivalue = sign_extend (Ivalue, 30);
+      *aoffsetp += 32;
+      break;
+    }
+  return Ivalue;
+}
+\f
+/* Return the number of locals in the current frame given a pc
+   pointing to the enter instruction.  This is used in the macro
+   FRAME_FIND_SAVED_REGS.  */
+
+ns32k_localcount (enter_pc)
+     CORE_ADDR enter_pc;
+{
+  unsigned char localtype;
+  int localcount;
+
+  localtype = read_memory_integer (enter_pc+2, 1);
+  if ((localtype & 0x80) == 0)
+    localcount = localtype;
+  else if ((localtype & 0xc0) == 0x80)
+    localcount = (((localtype & 0x3f) << 8)
+                 | (read_memory_integer (enter_pc+3, 1) & 0xff));
+  else
+    localcount = (((localtype & 0x3f) << 24)
+                 | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
+                 | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
+                 | (read_memory_integer (enter_pc+5, 1) & 0xff));
+  return localcount;
+}
+
+/*
+ * Get the address of the enter opcode for the function
+ * containing PC, if there is an enter for the function,
+ * and if the pc is between the enter and exit.
+ * Returns positive address if pc is between enter/exit,
+ * 1 if pc before enter or after exit, 0 otherwise.
+ */
+
+CORE_ADDR
+ns32k_get_enter_addr (pc)
+     CORE_ADDR pc;
+{
+  CORE_ADDR enter_addr;
+  unsigned char op;
+
+  if (ABOUT_TO_RETURN (pc))
+    return 1;          /* after exit */
+
+  enter_addr = get_pc_function_start (pc);
+
+  if (pc == enter_addr) 
+    return 1;          /* before enter */
+
+  op = read_memory_integer (enter_addr, 1);
+
+  if (op != 0x82)
+    return 0;          /* function has no enter/exit */
+
+  return enter_addr;   /* pc is between enter and exit */
+}
diff --git a/gdb/obstack.c b/gdb/obstack.c
new file mode 100755 (executable)
index 0000000..590fcaa
--- /dev/null
@@ -0,0 +1,333 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+   Copyright (C) 1988 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "obstack.h"
+
+#ifdef __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment.  */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+   But in fact it might be less smart and round addresses to as much as
+   DEFAULT_ROUNDING.  So we prepare for it to do that.  */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+   On some machines, copying successive ints does not work;
+   in such a case, redefine COPYING_UNIT to `long' (if that works)
+   or `char' as a last resort.  */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+/* The non-GNU-C macros copy the obstack into this global variable
+   to avoid multiple evaluation.  */
+
+struct obstack *_obstack;
+\f
+/* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
+   Objects start on multiples of ALIGNMENT (0 means use default).
+   CHUNKFUN is the function to use to allocate chunks,
+   and FREEFUN the function to free them.  */
+
+void
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+     struct obstack *h;
+     int size;
+     int alignment;
+     POINTER (*chunkfun) ();
+     void (*freefun) ();
+{
+  register struct _obstack_chunk* chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+        Use the values for range checking, because if range checking is off,
+        the extra bytes won't be missed terribly, but if range checking is on
+        and we used a larger request, a whole extra 4096 bytes would be
+        allocated.
+
+        These number are irrelevant to the new GNU malloc.  I suspect it is
+        less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+                   + 4 + DEFAULT_ROUNDING - 1)
+                  & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+  h->chunkfun = chunkfun;
+  h->freefun = freefun;
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+
+  chunk        = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (h->chunk_size);
+  h->next_free = h->object_base = chunk->contents;
+  h->chunk_limit = chunk->limit
+   = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+}
+
+/* Allocate a new current chunk for the obstack *H
+   on the assumption that LENGTH bytes need to be added
+   to the current object, or a new object of length LENGTH allocated.
+   Copies any partial object from the end of the old chunk
+   to the beginning of the new one.  
+
+   The function must be "int" so it can be used in non-ANSI C
+   compilers in a : expression.  */
+
+int
+_obstack_newchunk (h, length)
+     struct obstack *h;
+     int length;
+{
+  register struct _obstack_chunk*      old_chunk = h->chunk;
+  register struct _obstack_chunk*      new_chunk;
+  register long        new_size;
+  register int obj_size = h->next_free - h->object_base;
+  register int i;
+  int already;
+
+  /* Compute size for new chunk.  */
+  new_size = (obj_size + length) + (obj_size >> 3) + 100;
+  if (new_size < h->chunk_size)
+    new_size = h->chunk_size;
+
+  /* Allocate and initialize the new chunk.  */
+  new_chunk = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (new_size);
+  new_chunk->prev = old_chunk;
+  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+  /* Move the existing object to the new chunk.
+     Word at a time is fast and is safe if the object
+     is sufficiently aligned.  */
+  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+    {
+      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+          i >= 0; i--)
+       ((COPYING_UNIT *)new_chunk->contents)[i]
+         = ((COPYING_UNIT *)h->object_base)[i];
+      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+        but that can cross a page boundary on a machine
+        which does not do strict alignment for COPYING_UNITS.  */
+      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+    }
+  else
+    already = 0;
+  /* Copy remaining bytes one by one.  */
+  for (i = already; i < obj_size; i++)
+    new_chunk->contents[i] = h->object_base[i];
+
+  h->object_base = new_chunk->contents;
+  h->next_free = h->object_base + obj_size;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+   This is here for debugging.
+   If you use it in a program, you are probably losing.  */
+
+int
+_obstack_allocated_p (h, obj)
+     struct obstack *h;
+     POINTER obj;
+{
+  register struct _obstack_chunk*  lp; /* below addr of any objects in this chunk */
+  register struct _obstack_chunk*  plp;        /* point to previous chunk if any */
+
+  lp = (h)->chunk;
+  while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
+    {
+      plp = lp -> prev;
+      lp = plp;
+    }
+  return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+   more recently than OBJ.  If OBJ is zero, free everything in H.  */
+
+#ifdef __STDC__
+#undef obstack_free
+void
+obstack_free (struct obstack *h, POINTER obj)
+#else
+int
+_obstack_free (h, obj)
+     struct obstack *h;
+     POINTER obj;
+#endif
+{
+  register struct _obstack_chunk*  lp; /* below addr of any objects in this chunk */
+  register struct _obstack_chunk*  plp;        /* point to previous chunk if any */
+
+  lp = (h)->chunk;
+  /* We use >= because there cannot be an object at the beginning of a chunk.
+     But there can be an empty object at that address
+     at the end of another chunk.  */
+  while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+    {
+      plp = lp -> prev;
+      (*h->freefun) ((POINTER) lp);
+      lp = plp;
+    }
+  if (lp)
+    {
+      (h)->object_base = (h)->next_free = (char *)(obj);
+      (h)->chunk_limit = lp->limit;
+      (h)->chunk = lp;
+    }
+  else if (obj != 0)
+    /* obj is not in any of the chunks! */
+    abort ();
+}
+
+/* Let same .o link with output of gcc and other compilers.  */
+
+#ifdef __STDC__
+int
+_obstack_free (h, obj)
+     struct obstack *h;
+     POINTER obj;
+{
+  obstack_free (h, obj);
+}
+#endif
+\f
+/* #if 0 */
+/* These are now turned off because the applications do not use it
+   and it uses bcopy via obstack_grow, which causes trouble on sysV.  */
+
+/* Now define the functional versions of the obstack macros.
+   Define them to simply use the corresponding macros to do the job.  */
+
+#ifdef __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+   they won't pass through the macro names in parentheses.  */
+
+/* The function names appear in parentheses in order to prevent
+   the macro-definitions of the names from being expanded there.  */
+
+POINTER (obstack_base) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_room (obstack);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+     struct obstack *obstack;
+     int character;
+{
+  obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+     struct obstack *obstack;
+     int character;
+{
+  obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+/* #endif 0 */
diff --git a/gdb/obstack.h b/gdb/obstack.h
new file mode 100755 (executable)
index 0000000..2e80c9c
--- /dev/null
@@ -0,0 +1,416 @@
+/* obstack.h - object stack macros
+   Copyright (C) 1988 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects.  Each object starts life
+small, and may grow to maturity.  (Consider building a word syllable
+by syllable.)  An object can move while it is growing.  Once it has
+been "finished" it never changes address again.  So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'.  On occasion, they free chunks,
+by calling `obstack_chunk_free'.  You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables.  Unless you are "fascist pig with a read-only mind"
+[Gosper's immortal quote from HAKMEM item 154, out of context] you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols.  At the time you are reading a symbol you don't know
+how long it is.  One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer.  This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently.  Use one obstack for all symbol
+names.  As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it.  Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses.  When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk.  When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies.  No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk.  We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object.  This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+       We allocate large chunks.
+       We carve out one object at a time from the current chunk.
+       Once carved, an object never moves.
+       We are free to append data of any size to the currently
+         growing object.
+       Exactly one object is growing in an obstack at any one time.
+       You can run one obstack per control block.
+       You may have as many control blocks as you dare.
+       Because of the way we do it, you can `unwind' a obstack
+         back to a previous state. (You may remove objects much
+         as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once.  */
+
+#ifndef __OBSTACKS__
+#define __OBSTACKS__
+\f
+/* We use subtraction of (char *)0 instead of casting to int
+   because on word-addressable machines a simple cast to int
+   may ignore the byte-within-word field of the pointer.  */
+
+#ifndef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((P) - (char *)0)
+#endif
+
+#ifndef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((P) + (char *)0)
+#endif
+
+struct _obstack_chunk          /* Lives at front of each chunk. */
+{
+  char  *limit;                        /* 1 past end of this chunk */
+  struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+  char contents[4];            /* objects begin here */
+};
+
+struct obstack         /* control current object in current chunk */
+{
+  long chunk_size;             /* preferred size to allocate chunks in */
+  struct _obstack_chunk* chunk;        /* address of current struct obstack_chunk */
+  char *object_base;           /* address of object we are building */
+  char *next_free;             /* where to add next char to current object */
+  char *chunk_limit;           /* address of char after current chunk */
+  int  temp;                   /* Temporary for some macros.  */
+  int   alignment_mask;                /* Mask of alignment for each object. */
+#ifdef __STDC__
+  void  *(*chunkfun) ();       /* User's fcn to allocate a chunk.  */
+#else
+  char  *(*chunkfun) ();       /* User's fcn to allocate a chunk.  */
+#endif
+  void (*freefun) ();          /* User's function to free a chunk.  */
+};
+\f
+#ifdef __STDC__
+
+/* Do the function-declarations after the structs
+   but before defining the macros.  */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, void *data, int size);
+void obstack_grow0 (struct obstack *obstack, void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+   so we do not declare them.  */
+\f
+/* Pointer to beginning of object being allocated or to be allocated next.
+   Note that this might not be the final address of the object
+   because a new chunk might be needed to hold the final size.  */
+
+#define obstack_base(h) ((h)->object_base)
+
+/* Size for allocating ordinary chunks.  */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk.  */
+
+#define obstack_next_free(h)   ((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object.  */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+#define obstack_init(h) \
+  _obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+  _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+\f
+#if defined (__GNUC__) && defined (__STDC__)
+
+/* For GNU C, if not -traditional,
+   we can define these macros to compute all args only once
+   without using a global variable.
+   Also, we can avoid using the `temp' slot, to make faster code.  */
+
+#define obstack_object_size(OBSTACK)                                   \
+  ({ struct obstack *__o = (OBSTACK);                                  \
+     (unsigned) (__o->next_free - __o->object_base); })
+
+#define obstack_room(OBSTACK)                                          \
+  ({ struct obstack *__o = (OBSTACK);                                  \
+     (unsigned) (__o->chunk_limit - __o->next_free); })
+
+#define obstack_grow(OBSTACK,where,length)                             \
+({ struct obstack *__o = (OBSTACK);                                    \
+   int __len = (length);                                               \
+   ((__o->next_free + __len > __o->chunk_limit)                                \
+    ? _obstack_newchunk (__o, __len) : 0);                             \
+   bcopy (where, __o->next_free, __len);                               \
+   __o->next_free += __len;                                            \
+   (void) 0; })
+
+#define obstack_grow0(OBSTACK,where,length)                            \
+({ struct obstack *__o = (OBSTACK);                                    \
+   int __len = (length);                                               \
+   ((__o->next_free + __len + 1 > __o->chunk_limit)                    \
+    ? _obstack_newchunk (__o, __len + 1) : 0),                         \
+   bcopy (where, __o->next_free, __len),                               \
+   __o->next_free += __len,                                            \
+   *(__o->next_free)++ = 0;                                            \
+   (void) 0; })
+
+#define obstack_1grow(OBSTACK,datum)                                   \
+({ struct obstack *__o = (OBSTACK);                                    \
+   ((__o->next_free + 1 > __o->chunk_limit)                            \
+    ? _obstack_newchunk (__o, 1) : 0),                                 \
+   *(__o->next_free)++ = (datum);                                      \
+   (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers or ints,
+   and that the data added so far to the current object
+   shares that much alignment.  */
+   
+#define obstack_ptr_grow(OBSTACK,datum)                                        \
+({ struct obstack *__o = (OBSTACK);                                    \
+   ((__o->next_free + sizeof (void *) > __o->chunk_limit)              \
+    ? _obstack_newchunk (__o, sizeof (void *)) : 0),                   \
+   *(*(void ***)&__o->next_free)++ = ((void *)datum);                  \
+   (void) 0; })
+
+#define obstack_int_grow(OBSTACK,datum)                                        \
+({ struct obstack *__o = (OBSTACK);                                    \
+   ((__o->next_free + sizeof (int) > __o->chunk_limit)                 \
+    ? _obstack_newchunk (__o, sizeof (int)) : 0),                      \
+   *(*(int **)&__o->next_free)++ = ((int)datum);                               \
+   (void) 0; })
+
+#define obstack_ptr_grow_fast(h,aptr) (*(*(void ***)&(h)->next_free)++ = (void *)aptr)
+#define obstack_int_grow_fast(h,aint) (*(*(int **)&(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(OBSTACK,length)                                  \
+({ struct obstack *__o = (OBSTACK);                                    \
+   int __len = (length);                                               \
+   ((__o->chunk_limit - __o->next_free < __len)                                \
+    ? _obstack_newchunk (__o, __len) : 0);                             \
+   __o->next_free += __len;                                            \
+   (void) 0; })
+
+#define obstack_alloc(OBSTACK,length)                                  \
+({ struct obstack *__h = (OBSTACK);                                    \
+   obstack_blank (__h, (length));                                      \
+   obstack_finish (__h); })
+
+#define obstack_copy(OBSTACK,where,length)                             \
+({ struct obstack *__h = (OBSTACK);                                    \
+   obstack_grow (__h, (where), (length));                              \
+   obstack_finish (__h); })
+
+#define obstack_copy0(OBSTACK,where,length)                            \
+({ struct obstack *__h = (OBSTACK);                                    \
+   obstack_grow0 (__h, (where), (length));                             \
+   obstack_finish (__h); })
+
+#define obstack_finish(OBSTACK)                                        \
+({ struct obstack *__o = (OBSTACK);                                    \
+   void *value = (void *) __o->object_base;                            \
+   __o->next_free                                                      \
+     = __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
+                    & ~ (__o->alignment_mask));                        \
+   ((__o->next_free - (char *)__o->chunk                               \
+     > __o->chunk_limit - (char *)__o->chunk)                          \
+    ? (__o->next_free = __o->chunk_limit) : 0);                                \
+   __o->object_base = __o->next_free;                                  \
+   value; })
+
+#define obstack_free(OBSTACK, OBJ)                                     \
+({ struct obstack *__o = (OBSTACK);                                    \
+   void *__obj = (OBJ);                                                        \
+   if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit)  \
+     __o->next_free = __o->object_base = __obj;                                \
+   else (obstack_free) (__o, __obj); })
+\f
+#else /* not __GNUC__ or not __STDC__ */
+
+#define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+#define obstack_room(h)                \
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+#define obstack_grow(h,where,length)                                   \
+( (h)->temp = (length),                                                        \
+  (((h)->next_free + (h)->temp > (h)->chunk_limit)                     \
+   ? _obstack_newchunk ((h), (h)->temp) : 0),                          \
+  bcopy (where, (h)->next_free, (h)->temp),                            \
+  (h)->next_free += (h)->temp)
+
+#define obstack_grow0(h,where,length)                                  \
+( (h)->temp = (length),                                                        \
+  (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit)                 \
+   ? _obstack_newchunk ((h), (h)->temp + 1) : 0),                      \
+  bcopy (where, (h)->next_free, (h)->temp),                            \
+  (h)->next_free += (h)->temp,                                         \
+  *((h)->next_free)++ = 0)
+
+#define obstack_1grow(h,datum)                                         \
+( (((h)->next_free + 1 > (h)->chunk_limit)                             \
+   ? _obstack_newchunk ((h), 1) : 0),                                  \
+  *((h)->next_free)++ = (datum))
+
+#define obstack_ptr_grow(h,datum)                                      \
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit)               \
+   ? _obstack_newchunk ((h), sizeof (char *)) : 0),                    \
+  *(*(char ***)&(h)->next_free)++ = ((char *)datum))
+
+#define obstack_int_grow(h,datum)                                      \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit)                  \
+   ? _obstack_newchunk ((h), sizeof (int)) : 0),                       \
+  *(*(int **)&(h)->next_free)++ = ((int)datum))
+
+#define obstack_ptr_grow_fast(h,aptr) (*(*(char ***)&(h)->next_free)++ = (char *)aptr)
+#define obstack_int_grow_fast(h,aint) (*(*(int **)&(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(h,length)                                                \
+( (h)->temp = (length),                                                        \
+  (((h)->chunk_limit - (h)->next_free < (h)->temp)                     \
+   ? _obstack_newchunk ((h), (h)->temp) : 0),                          \
+  (h)->next_free += (h)->temp)
+
+#define obstack_alloc(h,length)                                                \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+#define obstack_copy(h,where,length)                                   \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_copy0(h,where,length)                                  \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_finish(h)                                              \
+( (h)->temp = __PTR_TO_INT ((h)->object_base),                         \
+  (h)->next_free                                                       \
+    = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask)        \
+                   & ~ ((h)->alignment_mask)),                         \
+  (((h)->next_free - (char *)(h)->chunk                                        \
+    > (h)->chunk_limit - (char *)(h)->chunk)                           \
+   ? ((h)->next_free = (h)->chunk_limit) : 0),                         \
+  (h)->object_base = (h)->next_free,                                   \
+  __INT_TO_PTR ((h)->temp))
+
+#ifdef __STDC__
+#define obstack_free(h,obj)                                            \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk,                     \
+  (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+   ? (int) ((h)->next_free = (h)->object_base                          \
+           = (h)->temp + (char *) (h)->chunk)                          \
+   : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
+#else
+#define obstack_free(h,obj)                                            \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk,                     \
+  (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+   ? (int) ((h)->next_free = (h)->object_base                          \
+           = (h)->temp + (char *) (h)->chunk)                          \
+   : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
+#endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+/* Declare the external functions we use; they are in obstack.c.  */
+
+#ifdef __STDC__
+  extern int _obstack_newchunk (struct obstack *h, int length);
+  extern int _obstack_free (struct obstack *h, void *obj);
+  extern void _obstack_begin (struct obstack *h, int size, int alignment,
+                             void *(*chunkfun) (), void (*freefun) ());
+#else
+  extern int _obstack_newchunk ();
+  extern int _obstack_free ();
+  extern void _obstack_begin ();
+#endif
+
+#endif /* not __OBSTACKS__ */
+
diff --git a/gdb/param-no-tm.h b/gdb/param-no-tm.h
new file mode 100755 (executable)
index 0000000..2e4af53
--- /dev/null
@@ -0,0 +1,76 @@
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (PARAM_H)
+#define PARAM_H 1
+
+/*  DO NOT #include "tm.h" -- a particular tm file has been inc'd by caller  */
+
+#include "xm.h"
+
+/* TARGET_BYTE_ORDER and HOST_BYTE_ORDER should be defined to one of these.  */
+#if !defined (BIG_ENDIAN)
+#define BIG_ENDIAN 4321
+#endif
+
+#if !defined (LITTLE_ENDIAN)
+#define LITTLE_ENDIAN 1234
+#endif
+
+/* The bit byte-order has to do just with numbering of bits in
+   debugging symbols and such.  Conceptually, it's quite separate
+   from byte/word byte order.  */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BITS_BIG_ENDIAN 1
+#endif
+
+#if TARGET_BYTE_ORDER == LITTLE_ENDIAN
+/*#define BITS_BIG_ENDIAN */
+#endif
+
+/* Swap LEN bytes at BUFFER between target and host byte-order.  */
+#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
+#define SWAP_TARGET_AND_HOST(buffer,len)
+#else /* Target and host byte order differ.  */
+#define SWAP_TARGET_AND_HOST(buffer,len) \
+  {                                                                     \
+    char tmp;                                                           \
+    char *p = (char *)(buffer);                                                 \
+    char *q = ((char *)(buffer)) + len - 1;                             \
+    for (; p < q; p++, q--)                                             \
+      {                                                                         \
+        tmp = *q;                                                       \
+        *q = *p;                                                        \
+        *p = tmp;                                                       \
+      }                                                                         \
+  }
+#endif /* Target and host byte order differ.  */
+
+/* On some machines there are bits in addresses which are not really
+   part of the address, but are used by the kernel, the hardware, etc.
+   for special purposes.  ADDR_BITS_REMOVE takes out any such bits
+   so we get a "real" address such as one would find in a symbol
+   table.  ADDR_BITS_SET sets those bits the way the system wants
+   them.  */
+#if !defined (ADDR_BITS_REMOVE)
+#define ADDR_BITS_REMOVE(addr) (addr)
+#define ADDR_BITS_SET(addr) (addr)
+#endif /* No ADDR_BITS_REMOVE.  */
+
+#endif /* param.h not already included.  */
diff --git a/gdb/param.h b/gdb/param.h
new file mode 100755 (executable)
index 0000000..0a56936
--- /dev/null
@@ -0,0 +1,30 @@
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* The standard thing is to include param.h.  However, files that are
+   specific to a particular target can include that tm-xxx.h file and
+   param-no-tm.h.  Any future inclusions of param.h will be protected
+   against by the #if !defined stuff below.  */
+
+#if !defined (PARAM_H)
+#include "tm.h"
+#endif
+
+#include "param-no-tm.h"
+
+#define PARAM_H 1
diff --git a/gdb/pn-opcode.h b/gdb/pn-opcode.h
new file mode 100755 (executable)
index 0000000..fde4764
--- /dev/null
@@ -0,0 +1,282 @@
+/* Print GOULD PN (PowerNode) instructions for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+struct gld_opcode
+{
+  char *name;
+  unsigned long opcode;
+  unsigned long mask;
+  char *args;
+  int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+   is the most any of them need.  The actual length of an instruction
+   is always at least 2 bytes, and at most four.  The length of the
+   instruction is based on the opcode.
+
+   The mask component is a mask saying which bits must match
+   particular opcode in order for an instruction to be an instance
+   of that opcode.
+
+   The args component is a string containing characters
+   that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+   r  Register in first field
+   R  Register in second field
+   b  Base register in first field
+   B  Base register in second field
+   v  Vector register in first field
+   V  Vector register in first field
+   A  Optional address register (base register)
+   X  Optional index register
+   I  Immediate data (16bits signed)
+   O  Offset field (16bits signed)
+   h  Offset field (15bits signed)
+   d  Offset field (14bits signed)
+   S  Shift count field
+
+   any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+   all instances of the same mnemonic must be consecutive.
+   All instances of the same mnemonic with the same number of operands
+   must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "abm",       0xa0080000,     0xfc080000,     "f,xOA,X",      4 },
+{ "abr",       0x18080000,     0xfc0c0000,     "r,f",          2 },
+{ "aci",       0xfc770000,     0xfc7f8000,     "r,I",          4 },
+{ "adfd",      0xe0080002,     0xfc080002,     "r,xOA,X",      4 },
+{ "adfw",      0xe0080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "adi",       0xc8010000,     0xfc7f0000,     "r,I",          4 },
+{ "admb",      0xb8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "admd",      0xb8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "admh",      0xb8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "admw",      0xb8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "adr",       0x38000000,     0xfc0f0000,     "r,R",          2 },
+{ "adrfd",     0x38090000,     0xfc0f0000,     "r,R",          2 },
+{ "adrfw",     0x38010000,     0xfc0f0000,     "r,R",          2 },
+{ "adrm",      0x38080000,     0xfc0f0000,     "r,R",          2 },
+{ "ai",        0xfc030000,     0xfc07ffff,     "I",            4 },
+{ "anmb",      0x84080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "anmd",      0x84000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "anmh",      0x84000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "anmw",      0x84000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "anr",       0x04000000,     0xfc0f0000,     "r,R",          2 },
+{ "armb",      0xe8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "armd",      0xe8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "armh",      0xe8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "armw",      0xe8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "bcf",       0xf0000000,     0xfc080000,     "I,xOA,X",      4 },
+{ "bct",       0xec000000,     0xfc080000,     "I,xOA,X",      4 },
+{ "bei",       0x00060000,     0xffff0000,     "",             2 },
+{ "bft",       0xf0000000,     0xff880000,     "xOA,X",        4 },
+{ "bib",       0xf4000000,     0xfc780000,     "r,xOA",        4 },
+{ "bid",       0xf4600000,     0xfc780000,     "r,xOA",        4 },
+{ "bih",       0xf4200000,     0xfc780000,     "r,xOA",        4 },
+{ "biw",       0xf4400000,     0xfc780000,     "r,xOA",        4 },
+{ "bl",        0xf8800000,     0xff880000,     "xOA,X",        4 },
+{ "bsub",      0x5c080000,     0xff8f0000,     "",             2 },
+{ "bsubm",     0x28080000,     0xfc080000,     "",             4 },
+{ "bu",        0xec000000,     0xff880000,     "xOA,X",        4 },
+{ "call",      0x28080000,     0xfc0f0000,     "",             2 },
+{ "callm",     0x5c080000,     0xff880000,     "",             4 },
+{ "camb",      0x90080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "camd",      0x90000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "camh",      0x90000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "camw",      0x90000000,     0xfc080000,     "r.xOA,X",      4 },
+{ "car",       0x10000000,     0xfc0f0000,     "r,R",          2 },
+{ "cd",        0xfc060000,     0xfc070000,     "r,f",          4 },
+{ "cea",       0x000f0000,     0xffff0000,     "",             2 },
+{ "ci",        0xc8050000,     0xfc7f0000,     "r,I",          4 },
+{ "cmc",       0x040a0000,     0xfc7f0000,     "r",            2 },
+{ "cmmb",      0x94080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "cmmd",      0x94000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "cmmh",      0x94000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "cmmw",      0x94000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "cmr",       0x14000000,     0xfc0f0000,     "r,R",          2 },
+{ "daci",      0xfc7f0000,     0xfc7f8000,     "r,I",          4 },
+{ "dae",       0x000e0000,     0xffff0000,     "",             2 },
+{ "dai",       0xfc040000,     0xfc07ffff,     "I",            4 },
+{ "dci",       0xfc6f0000,     0xfc7f8000,     "r,I",          4 },
+{ "di",        0xfc010000,     0xfc07ffff,     "I",            4 },
+{ "dvfd",      0xe4000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "dvfw",      0xe4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "dvi",       0xc8040000,     0xfc7f0000,     "r,I",          4 },
+{ "dvmb",      0xc4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "dvmh",      0xc4000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "dvmw",      0xc4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "dvr",       0x380a0000,     0xfc0f0000,     "r,R",          2 },
+{ "dvrfd",     0x380c0000,     0xfc0f0000,     "r,R",          4 },
+{ "dvrfw",     0x38040000,     0xfc0f0000,     "r,xOA,X",      4 },
+{ "eae",       0x00080000,     0xffff0000,     "",             2 },
+{ "eci",       0xfc670000,     0xfc7f8080,     "r,I",          4 },
+{ "ecwcs",     0xfc4f0000,     0xfc7f8000,     "",             4 },
+{ "ei",        0xfc000000,     0xfc07ffff,     "I",            4 },
+{ "eomb",      0x8c080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "eomd",      0x8c000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "eomh",      0x8c000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "eomw",      0x8c000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "eor",       0x0c000000,     0xfc0f0000,     "r,R",          2 },
+{ "eorm",      0x0c080000,     0xfc0f0000,     "r,R",          2 },
+{ "es",        0x00040000,     0xfc7f0000,     "r",            2 },
+{ "exm",       0xa8000000,     0xff880000,     "xOA,X",        4 },
+{ "exr",       0xc8070000,     0xfc7f0000,     "r",            2 },
+{ "exrr",      0xc8070002,     0xfc7f0002,     "r",            2 },
+{ "fixd",      0x380d0000,     0xfc0f0000,     "r,R",          2 },
+{ "fixw",      0x38050000,     0xfc0f0000,     "r,R",          2 },
+{ "fltd",      0x380f0000,     0xfc0f0000,     "r,R",          2 },
+{ "fltw",      0x38070000,     0xfc0f0000,     "r,R",          2 },
+{ "grio",      0xfc3f0000,     0xfc7f8000,     "r,I",          4 },
+{ "halt",      0x00000000,     0xffff0000,     "",             2 },
+{ "hio",       0xfc370000,     0xfc7f8000,     "r,I",          4 },
+{ "jwcs",      0xfa080000,     0xff880000,     "xOA,X",        4 },
+{ "la",        0x50000000,     0xfc000000,     "r,xOA,X",      4 },
+{ "labr",      0x58080000,     0xfc080000,     "b,xOA,X",      4 },
+{ "lb",        0xac080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lcs",       0x00030000,     0xfc7f0000,     "r",            2 },
+{ "ld",        0xac000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "lear",      0x80000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lf",        0xcc000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lfbr",      0xcc080000,     0xfc080000,     "b,xOA,X",      4 },
+{ "lh",        0xac000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "li",        0xc8000000,     0xfc7f0000,     "r,I",          4 },
+{ "lmap",      0x2c070000,     0xfc7f0000,     "r",            2 },
+{ "lmb",       0xb0080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lmd",       0xb0000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "lmh",       0xb0000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "lmw",       0xb0000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lnb",       0xb4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lnd",       0xb4000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "lnh",       0xb4000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "lnw",       0xb4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lpsd",      0xf9800000,     0xff880000,     "r,xOA,X",      4 },
+{ "lpsdcm",    0xfa800000,     0xff880000,     "r,xOA,X",      4 },
+{ "lw",        0xac000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "lwbr",      0x5c000000,     0xfc080000,     "b,xOA,X",      4 },
+{ "mpfd",      0xe4080002,     0xfc080002,     "r,xOA,X",      4 },
+{ "mpfw",      0xe4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "mpi",       0xc8030000,     0xfc7f0000,     "r,I",          4 },
+{ "mpmb",      0xc0080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "mpmh",      0xc0000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "mpmw",      0xc0000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "mpr",       0x38020000,     0xfc0f0000,     "r,R",          2 },
+{ "mprfd",     0x380e0000,     0xfc0f0000,     "r,R",          2 },
+{ "mprfw",     0x38060000,     0xfc0f0000,     "r,R",          2 },
+{ "nop",       0x00020000,     0xffff0000,     "",             2 },
+{ "ormb",      0x88080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "ormd",      0x88000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "ormh",      0x88000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "ormw",      0x88000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "orr",       0x08000000,     0xfc0f0000,     "r,R",          2 },
+{ "orrm",      0x08080000,     0xfc0f0000,     "r,R",          2 },
+{ "rdsts",     0x00090000,     0xfc7f0000,     "r",            2 },
+{ "return",    0x280e0000,     0xfc7f0000,     "",             2 },
+{ "ri",        0xfc020000,     0xfc07ffff,     "I",            4 },
+{ "rnd",       0x00050000,     0xfc7f0000,     "r",            2 },
+{ "rpswt",     0x040b0000,     0xfc7f0000,     "r",            2 },
+{ "rschnl",    0xfc2f0000,     0xfc7f8000,     "r,I",          4 },
+{ "rsctl",     0xfc470000,     0xfc7f8000,     "r,I",          4 },
+{ "rwcs",      0x000b0000,     0xfc0f0000,     "r,R",          2 },
+{ "sacz",      0x10080000,     0xfc0f0000,     "r,R",          2 },
+{ "sbm",       0x98080000,     0xfc080000,     "f,xOA,X",      4 },
+{ "sbr",       0x18000000,     0xfc0c0000,     "r,f",          4 },
+{ "sea",       0x000d0000,     0xffff0000,     "",             2 },
+{ "setcpu",    0x2c090000,     0xfc7f0000,     "r",            2 },
+{ "sio",       0xfc170000,     0xfc7f8000,     "r,I",          4 },
+{ "sipu",      0x000a0000,     0xffff0000,     "",             2 },
+{ "sla",       0x1c400000,     0xfc600000,     "r,S",          2 },
+{ "slad",      0x20400000,     0xfc600000,     "r,S",          2 },
+{ "slc",       0x24400000,     0xfc600000,     "r,S",          2 },
+{ "sll",       0x1c600000,     0xfc600000,     "r,S",          2 },
+{ "slld",      0x20600000,     0xfc600000,     "r,S",          2 },
+{ "smc",       0x04070000,     0xfc070000,     "",             2 },
+{ "sra",       0x1c000000,     0xfc600000,     "r,S",          2 },
+{ "srad",      0x20000000,     0xfc600000,     "r,S",          2 },
+{ "src",       0x24000000,     0xfc600000,     "r,S",          2 },
+{ "srl",       0x1c200000,     0xfc600000,     "r,S",          2 },
+{ "srld",      0x20200000,     0xfc600000,     "r,S",          2 },
+{ "stb",       0xd4080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "std",       0xd4000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "stf",       0xdc000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "stfbr",     0x54000000,     0xfc080000,     "b,xOA,X",      4 },
+{ "sth",       0xd4000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "stmb",      0xd8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "stmd",      0xd8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "stmh",      0xd8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "stmw",      0xd8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "stpio",     0xfc270000,     0xfc7f8000,     "r,I",          4 },
+{ "stw",       0xd4000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "stwbr",     0x54000000,     0xfc080000,     "b,xOA,X",      4 },
+{ "suabr",     0x58000000,     0xfc080000,     "b,xOA,X",      4 },
+{ "sufd",      0xe0000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "sufw",      0xe0000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "sui",       0xc8020000,     0xfc7f0000,     "r,I",          4 },
+{ "sumb",      0xbc080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "sumd",      0xbc000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "sumh",      0xbc000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "sumw",      0xbc000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "sur",       0x3c000000,     0xfc0f0000,     "r,R",          2 },
+{ "surfd",     0x380b0000,     0xfc0f0000,     "r,xOA,X",      4 },
+{ "surfw",     0x38030000,     0xfc0f0000,     "r,R",          2 },
+{ "surm",      0x3c080000,     0xfc0f0000,     "r,R",          2 },
+{ "svc",       0xc8060000,     0xffff0000,     "",             4 },
+{ "tbm",       0xa4080000,     0xfc080000,     "f,xOA,X",      4 },
+{ "tbr",       0x180c0000,     0xfc0c0000,     "r,f",          2 },
+{ "tbrr",      0x2c020000,     0xfc0f0000,     "r,B",          2 },
+{ "tccr",      0x28040000,     0xfc7f0000,     "",             2 },
+{ "td",        0xfc050000,     0xfc070000,     "r,f",          4 },
+{ "tio",       0xfc1f0000,     0xfc7f8000,     "r,I",          4 },
+{ "tmapr",     0x2c0a0000,     0xfc0f0000,     "r,R",          2 },
+{ "tpcbr",     0x280c0000,     0xfc7f0000,     "r",            2 },
+{ "trbr",      0x2c010000,     0xfc0f0000,     "b,R",          2 },
+{ "trc",       0x2c030000,     0xfc0f0000,     "r,R",          2 },
+{ "trcc",      0x28050000,     0xfc7f0000,     "",             2 },
+{ "trcm",      0x2c0b0000,     0xfc0f0000,     "r,R",          2 },
+{ "trn",       0x2c040000,     0xfc0f0000,     "r,R",          2 },
+{ "trnm",      0x2c0c0000,     0xfc0f0000,     "r,R",          2 },
+{ "trr",       0x2c000000,     0xfc0f0000,     "r,R",          2 },
+{ "trrm",      0x2c080000,     0xfc0f0000,     "r,R",          2 },
+{ "trsc",      0x2c0e0000,     0xfc0f0000,     "r,R",          2 },
+{ "trsw",      0x28000000,     0xfc7f0000,     "r",            2 },
+{ "tscr",      0x2c0f0000,     0xfc0f0000,     "r,R",          2 },
+{ "uei",       0x00070000,     0xffff0000,     "",             2 },
+{ "wait",      0x00010000,     0xffff0000,     "",             2 },
+{ "wcwcs",     0xfc5f0000,     0xfc7f8000,     "",             4 },
+{ "wwcs",      0x000c0000,     0xfc0f0000,     "r,R",          2 },
+{ "xcbr",      0x28020000,     0xfc0f0000,     "b,B",          2 },
+{ "xcr",       0x2c050000,     0xfc0f0000,     "r,R",          2 },
+{ "xcrm",      0x2c0d0000,     0xfc0f0000,     "r,R",          2 },
+{ "zbm",       0x9c080000,     0xfc080000,     "f,xOA,X",      4 },
+{ "zbr",       0x18040000,     0xfc0c0000,     "r,f",          2 },
+{ "zmb",       0xf8080000,     0xfc080000,     "r,xOA,X",      4 },
+{ "zmd",       0xf8000002,     0xfc080002,     "r,xOA,X",      4 },
+{ "zmh",       0xf8000001,     0xfc080001,     "r,xOA,X",      4 },
+{ "zmw",       0xf8000000,     0xfc080000,     "r,xOA,X",      4 },
+{ "zr",        0x0c000000,     0xfc0f0000,     "r",            2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+               sizeof(gld_opcodes[0]);
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
new file mode 100644 (file)
index 0000000..b8bc298
--- /dev/null
@@ -0,0 +1,1960 @@
+/* Print values for GNU debugger GDB.
+   Copyright (C) 1986-1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "symtab.h"
+#include "value.h"
+#include "expression.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "target.h"
+
+extern int asm_demangle;       /* Whether to demangle syms in asm printouts */
+
+extern struct block *get_current_block ();
+
+static void print_frame_nameless_args ();
+
+struct format_data
+{
+  int count;
+  char format;
+  char size;
+};
+
+/* Last specified output format.  */
+
+static char last_format = 'x';
+
+/* Last specified examination size.  'b', 'h', 'w' or `q'.  */
+
+static char last_size = 'w';
+
+/* Default address to examine next.  */
+
+static CORE_ADDR next_address;
+
+/* Last address examined.  */
+
+static CORE_ADDR last_examine_address;
+
+/* Contents of last address examined.
+   This is not valid past the end of the `x' command!  */
+
+static value last_examine_value;
+
+/* Number of auto-display expression currently being displayed.
+   So that we can deleted it if we get an error or a signal within it.
+   -1 when not doing one.  */
+
+int current_display_number;
+
+/* Flag to low-level print routines that this value is being printed
+   in an epoch window.  We'd like to pass this as a parameter, but
+   every routine would need to take it.  Perhaps we can encapsulate
+   this in the I/O stream once we have GNU stdio. */
+
+int inspect_it = 0;
+
+static void do_one_display ();
+
+void do_displays ();
+void print_scalar_formatted ();
+
+\f
+/* Decode a format specification.  *STRING_PTR should point to it.
+   OFORMAT and OSIZE are used as defaults for the format and size
+   if none are given in the format specification.
+   If OSIZE is zero, then the size field of the returned value
+   should be set only if a size is explicitly specified by the
+   user.
+   The structure returned describes all the data
+   found in the specification.  In addition, *STRING_PTR is advanced
+   past the specification and past all whitespace following it.  */
+
+struct format_data
+decode_format (string_ptr, oformat, osize)
+     char **string_ptr;
+     char oformat;
+     char osize;
+{
+  struct format_data val;
+  register char *p = *string_ptr;
+
+  val.format = '?';
+  val.size = '?';
+  val.count = 1;
+
+  if (*p >= '0' && *p <= '9')
+    val.count = atoi (p);
+  while (*p >= '0' && *p <= '9') p++;
+
+  /* Now process size or format letters that follow.  */
+
+  while (1)
+    {
+      if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g')
+       val.size = *p++;
+#ifdef LONG_LONG
+      else if (*p == 'l')
+       {
+         val.size = 'g';
+         p++;
+       }
+#endif
+      else if (*p >= 'a' && *p <= 'z')
+       val.format = *p++;
+      else
+       break;
+    }
+
+#ifndef LONG_LONG
+  /* Make sure 'g' size is not used on integer types.
+     Well, actually, we can handle hex.  */
+  if (val.size == 'g' && val.format != 'f' && val.format != 'x')
+    val.size = 'w';
+#endif
+
+  while (*p == ' ' || *p == '\t') p++;
+  *string_ptr = p;
+
+  /* Set defaults for format and size if not specified.  */
+  if (val.format == '?')
+    {
+      if (val.size == '?')
+       {
+         /* Neither has been specified.  */
+         val.format = oformat;
+         val.size = osize;
+       }
+      else
+       /* If a size is specified, any format makes a reasonable
+          default except 'i'.  */
+       val.format = oformat == 'i' ? 'x' : oformat;
+    }
+  else if (val.size == '?')
+    switch (val.format)
+      {
+      case 'a':
+      case 's':
+       /* Addresses must be words.  */
+       val.size = osize ? 'w' : osize;
+       break;
+      case 'f':
+       /* Floating point has to be word or giantword.  */
+       if (osize == 'w' || osize == 'g')
+         val.size = osize;
+       else
+         /* Default it to giantword if the last used size is not
+            appropriate.  */
+         val.size = osize ? 'g' : osize;
+       break;
+      case 'c':
+       /* Characters default to one byte.  */
+       val.size = osize ? 'b' : osize;
+       break;
+      default:
+       /* The default is the size most recently specified.  */
+       val.size = osize;
+      }
+
+  return val;
+}
+\f
+/* Print value VAL on stdout according to FORMAT, a letter or 0.
+   Do not end with a newline.
+   0 means print VAL according to its own type.
+   SIZE is the letter for the size of datum being printed.
+   This is used to pad hex numbers so they line up.  */
+
+static void
+print_formatted (val, format, size)
+     register value val;
+     register char format;
+     char size;
+{
+  int len = TYPE_LENGTH (VALUE_TYPE (val));
+
+  if (VALUE_LVAL (val) == lval_memory)
+    next_address = VALUE_ADDRESS (val) + len;
+
+  switch (format)
+    {
+    case 's':
+      next_address = VALUE_ADDRESS (val)
+       + value_print (value_addr (val), stdout, format, Val_pretty_default);
+      break;
+
+    case 'i':
+      next_address = VALUE_ADDRESS (val)
+       + print_insn (VALUE_ADDRESS (val), stdout);
+      break;
+
+    default:
+      if (format == 0
+         || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY
+         || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT
+         || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION
+         || VALUE_REPEATED (val))
+       value_print (val, stdout, format, Val_pretty_default);
+      else
+       print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val),
+                               format, size, stdout);
+    }
+}
+
+/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
+   according to letters FORMAT and SIZE on STREAM.
+   FORMAT may not be zero.  Formats s and i are not supported at this level.
+
+   This is how the elements of an array or structure are printed
+   with a format.  */
+
+void
+print_scalar_formatted (valaddr, type, format, size, stream)
+     char *valaddr;
+     struct type *type;
+     char format;
+     int size;
+     FILE *stream;
+{
+  LONGEST val_long;
+  int len = TYPE_LENGTH (type);
+
+  if (size == 'g' && sizeof (LONGEST) < 8
+      && format == 'x')
+    {
+      /* ok, we're going to have to get fancy here.  Assumption: a
+         long is four bytes.  FIXME.  */
+      unsigned long v1, v2, tmp;
+
+      v1 = unpack_long (builtin_type_long, valaddr);
+      v2 = unpack_long (builtin_type_long, valaddr + 4);
+
+#if TARGET_BYTE_ORDER == LITTLE_ENDIAN
+      /* Swap the two for printing */
+      tmp = v1;
+      v1 = v2;
+      v2 = tmp;
+#endif
+  
+      switch (format)
+       {
+       case 'x':
+         fprintf_filtered (stream, "0x%08x%08x", v1, v2);
+         break;
+       default:
+         error ("Output size \"g\" unimplemented for format \"%c\".",
+                format);
+       }
+      return;
+    }
+      
+  val_long = unpack_long (type, valaddr);
+
+  /* If value is unsigned, truncate it in case negative.  */
+  if (format != 'd')
+    {
+      if (len == sizeof (char))
+       val_long &= (1 << 8 * sizeof(char)) - 1;
+      else if (len == sizeof (short))
+       val_long &= (1 << 8 * sizeof(short)) - 1;
+      else if (len == sizeof (long))
+       val_long &= (unsigned long) - 1;
+    }
+
+  switch (format)
+    {
+    case 'x':
+      if (!size)
+       {
+         /* no size specified, like in print.  Print varying # of digits. */
+#if defined (LONG_LONG)
+         fprintf_filtered (stream, "0x%llx", val_long);
+#else /* not LONG_LONG.  */
+         fprintf_filtered (stream, "0x%lx", val_long);
+#endif /* not LONG_LONG.  */
+       }
+      else
+#if defined (LONG_LONG)
+      switch (size)
+       {
+       case 'b':
+         fprintf_filtered (stream, "0x%02llx", val_long);
+         break;
+       case 'h':
+         fprintf_filtered (stream, "0x%04llx", val_long);
+         break;
+       case 'w':
+         fprintf_filtered (stream, "0x%08llx", val_long);
+         break;
+       case 'g':
+         fprintf_filtered (stream, "0x%016llx", val_long);
+         break;
+       default:
+         error ("Undefined output size \"%c\".", size);
+       }
+#else /* not LONG_LONG.  */
+      switch (size)
+       {
+       case 'b':
+         fprintf_filtered (stream, "0x%02x", val_long);
+         break;
+       case 'h':
+         fprintf_filtered (stream, "0x%04x", val_long);
+         break;
+       case 'w':
+         fprintf_filtered (stream, "0x%08x", val_long);
+         break;
+       case 'g':
+         fprintf_filtered (stream, "0x%016x", val_long);
+         break;
+       default:
+         error ("Undefined output size \"%c\".", size);
+       }
+#endif /* not LONG_LONG */
+      break;
+
+    case 'd':
+#ifdef LONG_LONG
+      fprintf_filtered (stream, "%lld", val_long);
+#else
+      fprintf_filtered (stream, "%d", val_long);
+#endif
+      break;
+
+    case 'u':
+#ifdef LONG_LONG
+      fprintf_filtered (stream, "%llu", val_long);
+#else
+      fprintf_filtered (stream, "%u", val_long);
+#endif
+      break;
+
+    case 'o':
+      if (val_long)
+#ifdef LONG_LONG
+       fprintf_filtered (stream, "0%llo", val_long);
+#else
+       fprintf_filtered (stream, "0%o", val_long);
+#endif
+      else
+       fprintf_filtered (stream, "0");
+      break;
+
+    case 'a':
+      print_address ((CORE_ADDR) val_long, stream);
+      break;
+
+    case 'c':
+      value_print (value_from_long (builtin_type_char, val_long), stream, 0,
+                  Val_pretty_default);
+      break;
+
+    case 'f':
+      if (len == sizeof (float))
+       type = builtin_type_float;
+      else if (len == sizeof (double))
+       type = builtin_type_double;
+      print_floating (valaddr, type, stream);
+      break;
+
+    case 0:
+      abort ();
+
+    default:
+      error ("Undefined output format \"%c\".", format);
+    }
+}
+
+/* Specify default address for `x' command.
+   `info lines' uses this.  */
+
+void
+set_next_address (addr)
+     CORE_ADDR addr;
+{
+  next_address = addr;
+
+  /* Make address available to the user as $_.  */
+  set_internalvar (lookup_internalvar ("_"),
+                  value_from_long (builtin_type_int, (LONGEST) addr));
+}
+
+/* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM.
+   DO_DEMANGLE controls whether to print a symbol in its native "raw" form,
+   or to interpret it as a possible C++ name and convert it back to source
+   form. */
+
+void
+print_address_symbolic (addr, stream, do_demangle)
+     CORE_ADDR addr;
+     FILE *stream;
+     int do_demangle;
+{
+  int name_location;
+  register int i = find_pc_misc_function (addr);
+
+  /* If nothing comes out, don't print anything symbolic.  */
+  
+  if (i < 0)
+    return;
+
+  fputs_filtered (" <", stream);
+  if (do_demangle)
+    fputs_demangled (misc_function_vector[i].name, stream, 1);
+  else
+    fputs_filtered (misc_function_vector[i].name, stream);
+  name_location = misc_function_vector[i].address;
+  if (addr - name_location)
+    fprintf_filtered (stream, "+%d>", addr - name_location);
+  else
+    fputs_filtered (">", stream);
+}
+
+/* Print address ADDR symbolically on STREAM.
+   First print it as a number.  Then perhaps print
+   <SYMBOL + OFFSET> after the number.  */
+
+void
+print_address (addr, stream)
+     CORE_ADDR addr;
+     FILE *stream;
+{
+  fprintf_filtered (stream, "0x%x", addr);
+  print_address_symbolic (addr, stream, asm_demangle);
+}
+
+/* Print address ADDR symbolically on STREAM.  Parameter DEMANGLE
+   controls whether to print the symbolic name "raw" or demangled.  */
+
+void
+print_address_demangle (addr, stream, do_demangle)
+     CORE_ADDR addr;
+     FILE *stream;
+     int do_demangle;
+{
+  fprintf_filtered (stream, "0x%x", addr);
+  print_address_symbolic (addr, stream, do_demangle);
+}
+
+\f
+
+/* Examine data at address ADDR in format FMT.
+   Fetch it from memory and print on stdout.  */
+
+static void
+do_examine (fmt, addr)
+     struct format_data fmt;
+     CORE_ADDR addr;
+{
+  register char format = 0;
+  register char size;
+  register int count = 1;
+  struct type *val_type;
+  register int i;
+  register int maxelts;
+
+  format = fmt.format;
+  size = fmt.size;
+  count = fmt.count;
+  next_address = addr;
+
+  /* String or instruction format implies fetch single bytes
+     regardless of the specified size.  */
+  if (format == 's' || format == 'i')
+    size = 'b';
+
+  if (size == 'b')
+    val_type = builtin_type_char;
+  else if (size == 'h')
+    val_type = builtin_type_short;
+  else if (size == 'w')
+    val_type = builtin_type_long;
+  else if (size == 'g')
+#ifndef LONG_LONG
+    val_type = builtin_type_double;
+#else
+    val_type = builtin_type_long_long;
+#endif
+
+  maxelts = 8;
+  if (size == 'w')
+    maxelts = 4;
+  if (size == 'g')
+    maxelts = 2;
+  if (format == 's' || format == 'i')
+    maxelts = 1;
+
+  /* Print as many objects as specified in COUNT, at most maxelts per line,
+     with the address of the next one at the start of each line.  */
+
+  while (count > 0)
+    {
+      print_address (next_address, stdout);
+      printf_filtered (":");
+      for (i = maxelts;
+          i > 0 && count > 0;
+          i--, count--)
+       {
+         printf_filtered ("\t");
+         /* Note that print_formatted sets next_address for the next
+            object.  */
+         last_examine_address = next_address;
+         last_examine_value = value_at (val_type, next_address);
+         print_formatted (last_examine_value, format, size);
+       }
+      printf_filtered ("\n");
+      fflush (stdout);
+    }
+}
+\f
+static void
+validate_format (fmt, cmdname)
+     struct format_data fmt;
+     char *cmdname;
+{
+  if (fmt.size != 0)
+    error ("Size letters are meaningless in \"%s\" command.", cmdname);
+  if (fmt.count != 1)
+    error ("Item count other than 1 is meaningless in \"%s\" command.",
+          cmdname);
+  if (fmt.format == 'i' || fmt.format == 's')
+    error ("Format letter \"%c\" is meaningless in \"%s\" command.",
+          fmt.format, cmdname);
+}
+
+static void
+print_command_1 (exp, inspect, voidprint)
+     char *exp;
+     int inspect;
+     int voidprint;
+{
+  struct expression *expr;
+  register struct cleanup *old_chain = 0;
+  register char format = 0;
+  register value val;
+  struct format_data fmt;
+  int cleanup = 0;
+
+  /* Pass inspect flag to the rest of the print routines in a global (sigh). */
+  inspect_it = inspect;
+
+  if (exp && *exp == '/')
+    {
+      exp++;
+      fmt = decode_format (&exp, last_format, 0);
+      validate_format (fmt, "print");
+      last_format = format = fmt.format;
+    }
+  else
+    {
+      fmt.count = 1;
+      fmt.format = 0;
+      fmt.size = 0;
+    }
+
+  if (exp && *exp)
+    {
+      expr = parse_c_expression (exp);
+      old_chain = make_cleanup (free_current_contents, &expr);
+      cleanup = 1;
+      val = evaluate_expression (expr);
+    }
+  else
+    val = access_value_history (0);
+
+  if (voidprint || (val && VALUE_TYPE (val) &&
+                    TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_VOID))
+    {
+      int histindex = record_latest_value (val);
+
+      if (inspect)
+       printf ("\031(gdb-makebuffer \"%s\"  %d '(\"", exp, histindex);
+      else
+       if (histindex >= 0) printf_filtered ("$%d = ", histindex);
+
+      print_formatted (val, format, fmt.size);
+      printf_filtered ("\n");
+      if (inspect)
+       printf("\") )\030");
+    }
+
+  if (cleanup)
+    do_cleanups (old_chain);
+  inspect_it = 0;      /* Reset print routines to normal */
+}
+
+static void
+print_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  print_command_1 (exp, 0, 1);
+}
+
+/* Same as print, except in epoch, it gets its own window */
+static void
+inspect_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  extern int epoch_interface;
+
+  print_command_1 (exp, epoch_interface, 1);
+}
+
+/* Same as print, except it doesn't print void results. */
+static void
+call_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  print_command_1 (exp, 0, 0);
+}
+
+static void
+output_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  struct expression *expr;
+  register struct cleanup *old_chain;
+  register char format = 0;
+  register value val;
+  struct format_data fmt;
+
+  if (exp && *exp == '/')
+    {
+      exp++;
+      fmt = decode_format (&exp, 0, 0);
+      validate_format (fmt, "print");
+      format = fmt.format;
+    }
+
+  expr = parse_c_expression (exp);
+  old_chain = make_cleanup (free_current_contents, &expr);
+
+  val = evaluate_expression (expr);
+
+  print_formatted (val, format, fmt.size);
+
+  do_cleanups (old_chain);
+}
+
+static void
+set_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  struct expression *expr = parse_c_expression (exp);
+  register struct cleanup *old_chain
+    = make_cleanup (free_current_contents, &expr);
+  evaluate_expression (expr);
+  do_cleanups (old_chain);
+}
+
+static void
+address_info (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  register struct symbol *sym;
+  register CORE_ADDR val;
+  int is_a_field_of_this;      /* C++: lookup_symbol sets this to nonzero
+                                  if exp is a field of `this'. */
+
+  if (exp == 0)
+    error ("Argument required.");
+
+  sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE, 
+                      &is_a_field_of_this, (struct symtab **)NULL);
+  if (sym == 0)
+    {
+      register int i;
+
+      if (is_a_field_of_this)
+       {
+         printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp);
+         return;
+       }
+
+      for (i = 0; i < misc_function_count; i++)
+       if (!strcmp (misc_function_vector[i].name, exp))
+         break;
+
+      if (i < misc_function_count)
+       printf ("Symbol \"%s\" is at 0x%x in a file compiled without -g.\n",
+               exp, misc_function_vector[i].address);
+      else
+       error ("No symbol \"%s\" in current context.", exp);
+      return;
+    }
+
+  printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym));
+  val = SYMBOL_VALUE (sym);
+
+  switch (SYMBOL_CLASS (sym))
+    {
+    case LOC_CONST:
+    case LOC_CONST_BYTES:
+      printf ("constant");
+      break;
+
+    case LOC_LABEL:
+      printf ("a label at address 0x%x", SYMBOL_VALUE_ADDRESS (sym));
+      break;
+
+    case LOC_REGISTER:
+      printf ("a variable in register %s", reg_names[val]);
+      break;
+
+    case LOC_STATIC:
+      printf ("static at address 0x%x", SYMBOL_VALUE_ADDRESS (sym));
+      break;
+
+    case LOC_REGPARM:
+      printf ("an argument in register %s", reg_names[val]);
+      break;
+      
+    case LOC_ARG:
+      printf ("an argument at offset %d", (int)val);
+      break;
+
+    case LOC_LOCAL_ARG:
+      printf ("an argument at frame offset %d", (int)val);
+      break;
+
+    case LOC_LOCAL:
+      printf ("a local variable at frame offset %d", (int)val);
+      break;
+
+    case LOC_REF_ARG:
+      printf ("a reference argument at offset %d", (int)val);
+      break;
+
+    case LOC_TYPEDEF:
+      printf ("a typedef");
+      break;
+
+    case LOC_BLOCK:
+      printf ("a function at address 0x%x",
+             BLOCK_START (SYMBOL_BLOCK_VALUE (sym)));
+      break;
+
+    case LOC_EXTERNAL:
+      printf ("an external symbol at address 0x%x",
+             SYMBOL_VALUE_ADDRESS (sym));
+      break;
+
+    default:
+      printf ("of unknown (botched) type");
+      break;
+    }
+  printf (".\n");
+}
+\f
+static void
+x_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  struct expression *expr;
+  struct format_data fmt;
+  struct cleanup *old_chain;
+  struct value *val;
+
+  fmt.format = last_format;
+  fmt.size = last_size;
+  fmt.count = 1;
+
+  if (exp && *exp == '/')
+    {
+      exp++;
+      fmt = decode_format (&exp, last_format, last_size);
+      last_size = fmt.size;
+      last_format = fmt.format;
+    }
+
+  /* If we have an expression, evaluate it and use it as the address.  */
+
+  if (exp != 0 && *exp != 0)
+    {
+      expr = parse_c_expression (exp);
+      /* Cause expression not to be there any more
+        if this command is repeated with Newline.
+        But don't clobber a user-defined command's definition.  */
+      if (from_tty)
+       *exp = 0;
+      old_chain = make_cleanup (free_current_contents, &expr);
+      val = evaluate_expression (expr);
+      /* In rvalue contexts, such as this, functions are coerced into
+        pointers to functions.  This makes "x/i main" work.  */
+      if (/* last_format == 'i'
+         && */ TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC
+         && VALUE_LVAL (val) == lval_memory)
+       next_address = VALUE_ADDRESS (val);
+      else
+       next_address = (CORE_ADDR) value_as_long (val);
+      do_cleanups (old_chain);
+    }
+
+  do_examine (fmt, next_address);
+
+  /* Set a couple of internal variables if appropriate. */
+  if (last_examine_value)
+    {
+      /* Make last address examined available to the user as $_.  */
+      set_internalvar (lookup_internalvar ("_"),
+                      value_from_long (builtin_type_int, 
+                                       (LONGEST) last_examine_address));
+      
+      /* Make contents of last address examined available to the user as $__.*/
+      set_internalvar (lookup_internalvar ("__"), last_examine_value);
+    }
+}
+\f
+/* Commands for printing types of things.  */
+
+/* Print type of EXP, or last thing in value history if EXP == NULL.
+   show is passed to type_print.  */
+static void
+whatis_exp (exp, show)
+     char *exp;
+     int show;
+{
+  struct expression *expr;
+  register value val;
+  register struct cleanup *old_chain;
+
+  if (exp)
+    {
+      expr = parse_c_expression (exp);
+      old_chain = make_cleanup (free_current_contents, &expr);
+      val = evaluate_type (expr);
+    }
+  else
+    val = access_value_history (0);
+
+  printf_filtered ("type = ");
+  type_print (VALUE_TYPE (val), "", stdout, show);
+  printf_filtered ("\n");
+
+  if (exp)
+    do_cleanups (old_chain);
+}
+
+static void
+whatis_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  /* Most of the time users do not want to see all the fields
+     in a structure.  If they do they can use the "ptype" command.
+     Hence the "-1" below.  */
+  whatis_exp (exp, -1);
+}
+
+/* TYPENAME is either the name of a type, or an expression.  */
+static void
+ptype_command (typename, from_tty)
+     char *typename;
+     int from_tty;
+{
+  register char *p = typename;
+  register int len;
+  register struct block *b
+    = target_has_stack ? get_current_block () : 0;
+  register struct type *type;
+
+  if (typename == 0)
+    {
+      whatis_exp (typename, 1);
+      return;
+    }
+
+  while (*p && *p != ' ' && *p != '\t') p++;
+  len = p - typename;
+  while (*p == ' ' || *p == '\t') p++;
+
+  if (len == 6 && !strncmp (typename, "struct", 6))
+    type = lookup_struct (p, b);
+  else if (len == 5 && !strncmp (typename, "union", 5))
+    type = lookup_union (p, b);
+  else if (len == 4 && !strncmp (typename, "enum", 4))
+    type = lookup_enum (p, b);
+  else
+    {
+      type = lookup_typename (typename, b, 1);
+      if (type == 0)
+       {
+         register struct symbol *sym
+           = lookup_symbol (typename, b, STRUCT_NAMESPACE, 0,
+                            (struct symtab **)NULL);
+         if (sym == 0)
+           {
+             whatis_exp (typename, 1 /* FIXME: right? */);
+             return;
+           }
+         printf_filtered ("No type named %s, but there is a ",
+                 typename);
+         switch (TYPE_CODE (SYMBOL_TYPE (sym)))
+           {
+           case TYPE_CODE_STRUCT:
+             printf_filtered ("struct");
+             break;
+
+           case TYPE_CODE_UNION:
+             printf_filtered ("union");
+             break;
+
+           case TYPE_CODE_ENUM:
+             printf_filtered ("enum");
+             break;
+
+           default:
+             printf_filtered ("(Internal error in gdb)");
+             break;
+           }
+         printf_filtered (" %s.  Type \"help ptype\".\n", typename);
+         type = SYMBOL_TYPE (sym);
+       }
+    }
+
+  type_print (type, "", stdout, 1);
+  printf_filtered ("\n");
+}
+\f
+#if 0
+/* This is not necessary.  Instead, decode_line_1 takes any variable,
+   so "info line foo" is a close equivalent to "whereis foo".  */
+static void
+whereis_command (var, from_tty)
+     char *var;
+     int from_tty;
+{
+  struct symtab *s;
+  struct symbol *sym;
+  
+  if (var == NULL)
+    error_no_arg ("Variable name.");
+
+  sym = lookup_symbol (var, get_selected_block (), VAR_NAMESPACE,
+                      NULL, &s);
+  
+  if (sym != NULL && s != NULL)
+    printf_filtered ("Symbol \"%s\" is at line %d of file %s\n",
+                    var, sym->line, s->filename);
+  else
+    {
+      if (lookup_misc_func (var) >= 0)
+       printf_filtered ("Symbol \"%s\" is in a file compiled without -g.",
+                        var);
+      else
+       error ("No symbol \"%s\" in current context.", var);
+    }
+}
+#endif /* 0 */
+\f
+enum display_status {disabled, enabled};
+
+struct display
+{
+  /* Chain link to next auto-display item.  */
+  struct display *next;
+  /* Expression to be evaluated and displayed.  */
+  struct expression *exp;
+  /* Item number of this auto-display item.  */
+  int number;
+  /* Display format specified.  */
+  struct format_data format;
+  /* Innermost block required by this expression when evaluated */
+  struct block *block;
+  /* Status of this display (enabled or disabled) */
+  enum display_status status;
+};
+
+/* Chain of expressions whose values should be displayed
+   automatically each time the program stops.  */
+
+static struct display *display_chain;
+
+static int display_number;
+
+/* Add an expression to the auto-display chain.
+   Specify the expression.  */
+
+static void
+display_command (exp, from_tty)
+     char *exp;
+     int from_tty;
+{
+  struct format_data fmt;
+  register struct expression *expr;
+  register struct display *new;
+
+  if (exp == 0)
+    {
+      do_displays ();
+      return;
+    }
+
+  if (*exp == '/')
+    {
+      exp++;
+      fmt = decode_format (&exp, 0, 0);
+      if (fmt.size && fmt.format == 0)
+       fmt.format = 'x';
+      if (fmt.format == 'i' || fmt.format == 's')
+       fmt.size = 'b';
+    }
+  else
+    {
+      fmt.format = 0;
+      fmt.size = 0;
+      fmt.count = 0;
+    }
+
+  innermost_block = 0;
+  expr = parse_c_expression (exp);
+
+  new = (struct display *) xmalloc (sizeof (struct display));
+
+  new->exp = expr;
+  new->block = innermost_block;
+  new->next = display_chain;
+  new->number = ++display_number;
+  new->format = fmt;
+  new->status = enabled;
+  display_chain = new;
+
+  if (from_tty && target_has_execution)
+    do_one_display (new);
+
+  dont_repeat ();
+}
+
+static void
+free_display (d)
+     struct display *d;
+{
+  free (d->exp);
+  free (d);
+}
+
+/* Clear out the display_chain.
+   Done when new symtabs are loaded, since this invalidates
+   the types stored in many expressions.  */
+
+void
+clear_displays ()
+{
+  register struct display *d;
+
+  while (d = display_chain)
+    {
+      free (d->exp);
+      display_chain = d->next;
+      free (d);
+    }
+}
+
+/* Delete the auto-display number NUM.  */
+
+void
+delete_display (num)
+     int num;
+{
+  register struct display *d1, *d;
+
+  if (!display_chain)
+    error ("No display number %d.", num);
+
+  if (display_chain->number == num)
+    {
+      d1 = display_chain;
+      display_chain = d1->next;
+      free_display (d1);
+    }
+  else
+    for (d = display_chain; ; d = d->next)
+      {
+       if (d->next == 0)
+         error ("No display number %d.", num);
+       if (d->next->number == num)
+         {
+           d1 = d->next;
+           d->next = d1->next;
+           free_display (d1);
+           break;
+         }
+      }
+}
+
+/* Delete some values from the auto-display chain.
+   Specify the element numbers.  */
+
+static void
+undisplay_command (args)
+     char *args;
+{
+  register char *p = args;
+  register char *p1;
+  register int num;
+
+  if (args == 0)
+    {
+      if (query ("Delete all auto-display expressions? "))
+       clear_displays ();
+      dont_repeat ();
+      return;
+    }
+
+  while (*p)
+    {
+      p1 = p;
+      while (*p1 >= '0' && *p1 <= '9') p1++;
+      if (*p1 && *p1 != ' ' && *p1 != '\t')
+       error ("Arguments must be display numbers.");
+
+      num = atoi (p);
+
+      delete_display (num);
+
+      p = p1;
+      while (*p == ' ' || *p == '\t') p++;
+    }
+  dont_repeat ();
+}
+
+/* Display a single auto-display.  
+   Do nothing if the display cannot be printed in the current context,
+   or if the display is disabled. */
+
+static void
+do_one_display (d)
+     struct display *d;
+{
+  int within_current_scope;
+
+  if (d->status == disabled)
+    return;
+
+  if (d->block)
+    within_current_scope = contained_in (get_selected_block (), d->block);
+  else
+    within_current_scope = 1;
+  if (!within_current_scope)
+    return;
+
+  current_display_number = d->number;
+
+  printf_filtered ("%d: ", d->number);
+  if (d->format.size)
+    {
+      CORE_ADDR addr;
+      
+      printf_filtered ("x/");
+      if (d->format.count != 1)
+       printf_filtered ("%d", d->format.count);
+      printf_filtered ("%c", d->format.format);
+      if (d->format.format != 'i' && d->format.format != 's')
+       printf_filtered ("%c", d->format.size);
+      printf_filtered (" ");
+      print_expression (d->exp, stdout);
+      if (d->format.count != 1)
+       printf_filtered ("\n");
+      else
+       printf_filtered ("  ");
+      
+      addr = (CORE_ADDR) value_as_long (evaluate_expression (d->exp));
+      if (d->format.format == 'i')
+       addr = ADDR_BITS_REMOVE (addr);
+      
+      do_examine (d->format, addr);
+    }
+  else
+    {
+      if (d->format.format)
+       printf_filtered ("/%c ", d->format.format);
+      print_expression (d->exp, stdout);
+      printf_filtered (" = ");
+      print_formatted (evaluate_expression (d->exp),
+                      d->format.format, d->format.size);
+      printf_filtered ("\n");
+    }
+
+  fflush (stdout);
+  current_display_number = -1;
+}
+
+/* Display all of the values on the auto-display chain which can be
+   evaluated in the current scope.  */
+
+void
+do_displays ()
+{
+  register struct display *d;
+
+  for (d = display_chain; d; d = d->next)
+    do_one_display (d);
+}
+
+/* Delete the auto-display which we were in the process of displaying.
+   This is done when there is an error or a signal.  */
+
+void
+disable_display (num)
+     int num;
+{
+  register struct display *d;
+
+  for (d = display_chain; d; d = d->next)
+    if (d->number == num)
+      {
+       d->status = disabled;
+       return;
+      }
+  printf ("No display number %d.\n", num);
+}
+  
+void
+disable_current_display ()
+{
+  if (current_display_number >= 0)
+    {
+      disable_display (current_display_number);
+      fprintf (stderr, "Disabling display %d to avoid infinite recursion.\n",
+              current_display_number);
+    }
+  current_display_number = -1;
+}
+
+static void
+display_info ()
+{
+  register struct display *d;
+
+  if (!display_chain)
+    printf ("There are no auto-display expressions now.\n");
+  else
+      printf_filtered ("Auto-display expressions now in effect:\n\
+Num Enb Expression\n");
+
+  for (d = display_chain; d; d = d->next)
+    {
+      printf_filtered ("%d:   %c  ", d->number, "ny"[(int)d->status]);
+      if (d->format.size)
+       printf_filtered ("/%d%c%c ", d->format.count, d->format.size,
+               d->format.format);
+      else if (d->format.format)
+       printf_filtered ("/%c ", d->format.format);
+      print_expression (d->exp, stdout);
+      if (d->block && !contained_in (get_selected_block (), d->block))
+       printf_filtered (" (cannot be evaluated in the current context)");
+      printf_filtered ("\n");
+      fflush (stdout);
+    }
+}
+
+void
+enable_display (args)
+     char *args;
+{
+  register char *p = args;
+  register char *p1;
+  register int num;
+  register struct display *d;
+
+  if (p == 0)
+    {
+      for (d = display_chain; d; d = d->next)
+       d->status = enabled;
+    }
+  else
+    while (*p)
+      {
+       p1 = p;
+       while (*p1 >= '0' && *p1 <= '9')
+         p1++;
+       if (*p1 && *p1 != ' ' && *p1 != '\t')
+         error ("Arguments must be display numbers.");
+       
+       num = atoi (p);
+       
+       for (d = display_chain; d; d = d->next)
+         if (d->number == num)
+           {
+             d->status = enabled;
+             goto win;
+           }
+       printf ("No display number %d.\n", num);
+      win:
+       p = p1;
+       while (*p == ' ' || *p == '\t')
+         p++;
+      }
+}
+
+void
+disable_display_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  register char *p = args;
+  register char *p1;
+  register struct display *d;
+
+  if (p == 0)
+    {
+      for (d = display_chain; d; d = d->next)
+       d->status = disabled;
+    }
+  else
+    while (*p)
+      {
+       p1 = p;
+       while (*p1 >= '0' && *p1 <= '9')
+         p1++;
+       if (*p1 && *p1 != ' ' && *p1 != '\t')
+         error ("Arguments must be display numbers.");
+       
+       disable_display (atoi (p));
+
+       p = p1;
+       while (*p == ' ' || *p == '\t')
+         p++;
+      }
+}
+
+\f
+/* Print the value in stack frame FRAME of a variable
+   specified by a struct symbol.  */
+
+void
+print_variable_value (var, frame, stream)
+     struct symbol *var;
+     FRAME frame;
+     FILE *stream;
+{
+  value val = read_var_value (var, frame);
+  value_print (val, stream, 0, Val_pretty_default);
+}
+
+/* Print the arguments of a stack frame, given the function FUNC
+   running in that frame (as a symbol), the info on the frame,
+   and the number of args according to the stack frame (or -1 if unknown).  */
+
+/* References here and elsewhere to "number of args according to the
+   stack frame" appear in all cases to refer to "number of ints of args
+   according to the stack frame".  At least for VAX, i386, isi.  */
+
+void
+print_frame_args (func, fi, num, stream)
+     struct symbol *func;
+     struct frame_info *fi;
+     int num;
+     FILE *stream;
+{
+  struct block *b;
+  int nsyms = 0;
+  int first = 1;
+  register int i;
+  register struct symbol *sym;
+  register value val;
+  /* Offset of next stack argument beyond the one we have seen that is
+     at the highest offset.
+     -1 if we haven't come to a stack argument yet.  */
+  int highest_offset = -1;
+  int arg_size;
+  /* Number of ints of arguments that we have printed so far.  */
+  int args_printed = 0;
+
+  if (func)
+    {
+      b = SYMBOL_BLOCK_VALUE (func);
+      nsyms = BLOCK_NSYMS (b);
+    }
+
+  for (i = 0; i < nsyms; i++)
+    {
+      QUIT;
+      sym = BLOCK_SYM (b, i);
+
+      if (SYMBOL_CLASS (sym) != LOC_REGPARM
+         && SYMBOL_CLASS (sym) != LOC_ARG
+         && SYMBOL_CLASS (sym) != LOC_LOCAL_ARG
+         && SYMBOL_CLASS (sym) != LOC_REF_ARG)
+       continue;
+
+      /* We have to re-look-up the symbol because arguments often have
+        two entries (one a parameter, one a register or local), and the one
+        we want is the non-parm, which lookup_symbol will find for
+        us.  After this, sym could be any SYMBOL_CLASS...  */
+      sym = lookup_symbol (SYMBOL_NAME (sym),
+                   b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+
+      switch (SYMBOL_CLASS (sym)) {
+
+      /* Keep track of the highest stack argument offset seen */
+      case LOC_ARG:
+      case LOC_REF_ARG:
+       {
+         int current_offset = SYMBOL_VALUE (sym);
+
+         arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym));
+         
+         /* Compute address of next argument by adding the size of
+            this argument and rounding to an int boundary.  */
+         current_offset
+           = ((current_offset + arg_size + sizeof (int) - 1)
+              & ~(sizeof (int) - 1));
+
+         /* If this is the highest offset seen yet, set highest_offset.  */
+         if (highest_offset == -1
+             || (current_offset > highest_offset))
+           highest_offset = current_offset;
+
+         /* Add the number of ints we're about to print to args_printed.  */
+         args_printed += (arg_size + sizeof (int) - 1) / sizeof (int);
+       }
+
+      /* Other types of symbols don't need to be kept track of.  */
+      default:
+       break;
+      }
+
+      /* Print the current arg.  */
+      if (! first)
+       fprintf_filtered (stream, ", ");
+      wrap_here ("    ");
+      fprint_symbol (stream, SYMBOL_NAME (sym));
+      fputs_filtered ("=", stream);
+
+      /* Avoid value_print because it will deref ref parameters.  We just
+        want to print their addresses.  Print ??? for args whose address
+        we do not know.  */
+      val = read_var_value (sym, FRAME_INFO_ID (fi));
+      if (val)
+        val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val),
+                  stream, 0, 0, 0, Val_no_prettyprint);
+      else
+       fputs_filtered ("???", stream);
+      first = 0;
+    }
+
+  /* Don't print nameless args in situations where we don't know
+     enough about the stack to find them.  */
+  if (num != -1)
+    {
+      int start;
+      CORE_ADDR addr;
+
+      if (highest_offset == -1)
+       start = FRAME_ARGS_SKIP;
+      else
+       start = highest_offset;
+
+      addr = FRAME_ARGS_ADDRESS (fi);
+      if (addr)
+        print_frame_nameless_args (addr, start, num - args_printed,
+                                  first, stream);
+    }
+}
+
+/* Print nameless args on STREAM.
+   ARGSADDR is the address of the arglist, START is the offset
+   of the first nameless arg, and NUM is the number of nameless args to
+   print.  FIRST is nonzero if this is the first argument (not just
+   the first nameless arg).  */
+static void
+print_frame_nameless_args (argsaddr, start, num, first, stream)
+     CORE_ADDR argsaddr;
+     int start;
+     int num;
+     int first;
+     FILE *stream;
+{
+  int i;
+  for (i = 0; i < num; i++)
+    {
+      QUIT;
+      if (!first)
+       fprintf_filtered (stream, ", ");
+#ifndef PRINT_TYPELESS_INTEGER
+      fprintf_filtered (stream, "%d",
+              read_memory_integer (argsaddr + start, sizeof (int)));
+#else
+      PRINT_TYPELESS_INTEGER (stream, builtin_type_int,
+                             (LONGEST)
+                             read_memory_integer (argsaddr + start,
+                                                  sizeof (int)));
+#endif
+      first = 0;
+      start += sizeof (int);
+    }
+}
+\f
+static void
+printf_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  register char *f;
+  register char *s = arg;
+  char *string;
+  value *val_args;
+  int nargs = 0;
+  int allocated_args = 20;
+  char *arg_bytes;
+
+  val_args = (value *) xmalloc (allocated_args * sizeof (value));
+
+  if (s == 0)
+    error_no_arg ("format-control string and values to print");
+
+  /* Skip white space before format string */
+  while (*s == ' ' || *s == '\t') s++;
+
+  /* A format string should follow, enveloped in double quotes */
+  if (*s++ != '"')
+    error ("Bad format string, missing '\"'.");
+
+  /* Parse the format-control string and copy it into the string STRING,
+     processing some kinds of escape sequence.  */
+
+  f = string = (char *) alloca (strlen (s) + 1);
+  while (*s != '"')
+    {
+      int c = *s++;
+      switch (c)
+       {
+       case '\0':
+         error ("Bad format string, non-terminated '\"'.");
+         /* doesn't return */
+
+       case '\\':
+         switch (c = *s++)
+           {
+           case '\\':
+             *f++ = '\\';
+             break;
+           case 'n':
+             *f++ = '\n';
+             break;
+           case 't':
+             *f++ = '\t';
+             break;
+           case 'r':
+             *f++ = '\r';
+             break;
+           case '"':
+             *f++ = '"';
+             break;
+           default:
+             /* ??? TODO: handle other escape sequences */
+             error ("Unrecognized \\ escape character in format string.");
+           }
+         break;
+
+       default:
+         *f++ = c;
+       }
+    }
+
+  /* Skip over " and following space and comma.  */
+  s++;
+  *f++ = '\0';
+  while (*s == ' ' || *s == '\t') s++;
+
+  if (*s != ',' && *s != 0)
+    error ("Invalid argument syntax");
+
+  if (*s == ',') s++;
+  while (*s == ' ' || *s == '\t') s++;
+
+  {
+    /* Now scan the string for %-specs and see what kinds of args they want.
+       argclass[I] classifies the %-specs so we can give vprintf something
+       of the right size.  */
+    enum argclass {int_arg, string_arg, double_arg, long_long_arg};
+    enum argclass *argclass;
+    int nargs_wanted;
+    int argindex;
+    int lcount;
+    int i;
+    argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass);
+    nargs_wanted = 0;
+    f = string;
+    while (*f)
+      if (*f++ == '%')
+       {
+         lcount = 0;
+         while (strchr ("0123456789.hlL-+ #", *f)) 
+           {
+             if (*f == 'l' || *f == 'L')
+               lcount++;
+             f++;
+           }
+         if (*f == 's')
+           argclass[nargs_wanted++] = string_arg;
+         else if (*f == 'e' || *f == 'f' || *f == 'g')
+           argclass[nargs_wanted++] = double_arg;
+         else if (lcount > 1)
+           argclass[nargs_wanted++] = long_long_arg;
+         else if (*f != '%')
+           argclass[nargs_wanted++] = int_arg;
+         f++;
+       }
+    /* Now, parse all arguments and evaluate them.
+       Store the VALUEs in VAL_ARGS.  */
+    while (*s != '\0')
+      {
+       char *s1;
+       if (nargs == allocated_args)
+         val_args = (value *) xrealloc (val_args,
+                                        (allocated_args *= 2)
+                                        * sizeof (value));
+       s1 = s;
+       val_args[nargs] = parse_to_comma_and_eval (&s1);
+       /* If format string wants a float, unchecked-convert the value to
+          floating point of the same size */
+       if (argclass[nargs] == double_arg)
+         {
+           if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float))
+             VALUE_TYPE (val_args[nargs]) = builtin_type_float;
+           if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double))
+             VALUE_TYPE (val_args[nargs]) = builtin_type_double;
+         }
+       nargs++;
+       s = s1;
+       if (*s == ',')
+         s++;
+      }
+    if (nargs != nargs_wanted)
+      error ("Wrong number of arguments for specified format-string");
+    /* Now lay out an argument-list containing the arguments
+       as doubles, integers and C pointers.  */
+    arg_bytes = (char *) alloca (sizeof (double) * nargs);
+    argindex = 0;
+    for (i = 0; i < nargs; i++)
+      {
+       if (argclass[i] == string_arg)
+         {
+           char *str;
+           int tem, j;
+           tem = value_as_long (val_args[i]);
+           /* This is a %s argument.  Find the length of the string.  */
+           for (j = 0; ; j++)
+             {
+               char c;
+               QUIT;
+               read_memory (tem + j, &c, 1);
+               if (c == 0)
+                 break;
+             }
+           /* Copy the string contents into a string inside GDB.  */
+           str = (char *) alloca (j + 1);
+           read_memory (tem, str, j);
+           str[j] = 0;
+           /* Pass address of internal copy as the arg to vprintf.  */
+           *((int *) &arg_bytes[argindex]) = (int) str;
+           argindex += sizeof (int);
+         }
+       else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT)
+         {
+           *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]);
+           argindex += sizeof (double);
+         }
+       else
+#ifdef LONG_LONG
+         if (argclass[i] == long_long_arg)
+           {
+             *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]);
+             argindex += sizeof (long long);
+           }
+         else
+#endif
+           {
+             *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]);
+             argindex += sizeof (int);
+           }
+      }
+  }
+
+  /* There is not a standard way to make a va_list, so we need
+     to do various things for different systems.  */
+#if defined (__INT_VARARGS_H)
+  {
+    va_list list;
+
+    list.__va_arg = 0;
+    list.__va_stk = (int *) arg_bytes;
+    list.__va_reg = (int *) arg_bytes;
+    vprintf (string, list);
+  }
+#else /* No __INT_VARARGS_H.  */
+  vprintf (string, arg_bytes);
+#endif /* No __INT_VARARGS_H.  */
+}
+\f
+/* Helper function for asdump_command.  Finds the bounds of a function
+   for a specified section of text.  PC is an address within the
+   function which you want bounds for; *LOW and *HIGH are set to the
+   beginning (inclusive) and end (exclusive) of the function.  This
+   function returns 1 on success and 0 on failure.  */
+
+static int
+containing_function_bounds (pc, low, high)
+     CORE_ADDR pc, *low, *high;
+{
+  int scan;
+
+  if (!find_pc_partial_function (pc, 0, low))
+    return 0;
+
+  scan = *low;
+  do {
+    scan++;
+    if (!find_pc_partial_function (scan, 0, high))
+      return 0;
+  } while (*low == *high);
+
+  return 1;
+}
+
+/* Dump a specified section of assembly code.  With no command line
+   arguments, this command will dump the assembly code for the
+   function surrounding the pc value in the selected frame.  With one
+   argument, it will dump the assembly code surrounding that pc value.
+   Two arguments are interpeted as bounds within which to dump
+   assembly.  */
+
+static void
+disassemble_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  CORE_ADDR low, high;
+  CORE_ADDR pc;
+  char *space_index;
+
+  if (!arg)
+    {
+      if (!selected_frame)
+       error ("No frame selected.\n");
+
+      pc = get_frame_pc (selected_frame);
+      if (!containing_function_bounds (pc, &low, &high))
+       error ("No function contains pc specified by selected frame.\n");
+    }
+  else if (!(space_index = (char *) strchr (arg, ' ')))
+    {
+      /* One argument.  */
+      pc = parse_and_eval_address (arg);
+      if (!containing_function_bounds (pc, &low, &high))
+       error ("No function contains specified pc.\n");
+    }
+  else
+    {
+      /* Two arguments.  */
+      *space_index = '\0';
+      low = parse_and_eval_address (arg);
+      high = parse_and_eval_address (space_index + 1);
+    }
+
+  printf_filtered ("Dump of assembler code ");
+  if (!space_index)
+    {
+      char *name;
+      find_pc_partial_function (pc, &name, 0);
+      printf_filtered ("for function %s:\n", name);
+    }
+  else
+    printf_filtered ("from 0x%x to 0x%x:\n", low, high);
+
+  /* Dump the specified range.  */
+  for (pc = low; pc < high; )
+    {
+      QUIT;
+      print_address (pc, stdout);
+      printf_filtered (":\t");
+      pc += print_insn (pc, stdout);
+      printf_filtered ("\n");
+    }
+  printf_filtered ("End of assembler dump.\n");
+  fflush (stdout);
+}
+
+\f
+void
+_initialize_printcmd ()
+{
+  current_display_number = -1;
+
+  add_info ("address", address_info,
+          "Describe where variable VAR is stored.");
+
+  add_com ("x", class_vars, x_command,
+          "Examine memory: x/FMT ADDRESS.\n\
+ADDRESS is an expression for the memory address to examine.\n\
+FMT is a repeat count followed by a format letter and a size letter.\n\
+Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\
+ f(float), a(address), i(instruction), c(char) and s(string).\n\
+Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\
+  g is meaningful only with f, for type double.\n\
+The specified number of objects of the specified size are printed\n\
+according to the format.\n\n\
+Defaults for format and size letters are those previously used.\n\
+Default count is 1.  Default address is following last thing printed\n\
+with this command or \"print\".");
+
+  add_com ("disassemble", class_vars, disassemble_command,
+          "Disassemble a specified section of memory.\n\
+Default is the function surrounding the pc of the selected frame.\n\
+With a single argument, the function surrounding that address is dumped.\n\
+Two arguments are taken as a range of memory to dump.");
+
+  add_com ("ptype", class_vars, ptype_command,
+          "Print definition of type TYPE.\n\
+Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\
+or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\
+The selected stack frame's lexical context is used to look up the name.");
+
+  add_com ("whatis", class_vars, whatis_command,
+          "Print data type of expression EXP.");
+
+#if 0
+  add_com ("whereis", class_vars, whereis_command,
+          "Print line number and file of definition of variable.");
+#endif
+  
+  add_info ("display", display_info,
+           "Expressions to display when program stops, with code numbers.");
+
+  add_cmd ("undisplay", class_vars, undisplay_command,
+          "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+\"delete display\" has the same effect as this command.\n\
+Do \"info display\" to see current list of code numbers.",
+                 &cmdlist);
+
+  add_com ("display", class_vars, display_command,
+          "Print value of expression EXP each time the program stops.\n\
+/FMT may be used before EXP as in the \"print\" command.\n\
+/FMT \"i\" or \"s\" or including a size-letter is allowed,\n\
+as in the \"x\" command, and then EXP is used to get the address to examine\n\
+and examining is done as in the \"x\" command.\n\n\
+With no argument, display all currently requested auto-display expressions.\n\
+Use \"undisplay\" to cancel display requests previously made.");
+
+  add_cmd ("display", class_vars, enable_display, 
+          "Enable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to resume displaying.\n\
+No argument means enable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &enablelist);
+
+  add_cmd ("display", class_vars, disable_display_command, 
+          "Disable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means disable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &disablelist);
+
+  add_cmd ("display", class_vars, undisplay_command, 
+          "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &deletelist);
+
+  add_com ("printf", class_vars, printf_command,
+       "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
+This is useful for formatted output in user-defined commands.");
+  add_com ("output", class_vars, output_command,
+          "Like \"print\" but don't put in value history and don't print newline.\n\
+This is useful in user-defined commands.");
+
+  add_prefix_cmd ("set", class_vars, set_command,
+"Perform an assignment VAR = EXP.\n\
+You must type the \"=\".  VAR may be a debugger \"convenience\" variable\n\
+(names starting with $), a register (a few standard names starting with $),\n\
+or an actual variable in the program being debugged.  EXP is any expression.\n\
+Use \"set variable\" for variables with names identical to set subcommands.\n\
+\nWith a subcommand, this command modifies parts of the gdb environment.\n\
+You can see these environment settings with the \"show\" command.",
+                  &setlist, "set ", 1, &cmdlist);
+
+  /* "call" is the same as "set", but handy for dbx users to call fns. */
+  add_com ("call", class_vars, call_command,
+          "Call a function in the inferior process.\n\
+The argument is the function name and arguments, in standard C notation.\n\
+The result is printed and saved in the value history, if it is not void.");
+
+  add_cmd ("variable", class_vars, set_command,
+           "Perform an assignment VAR = EXP.\n\
+You must type the \"=\".  VAR may be a debugger \"convenience\" variable\n\
+(names starting with $), a register (a few standard names starting with $),\n\
+or an actual variable in the program being debugged.  EXP is any expression.\n\
+This may usually be abbreviated to simply \"set\".",
+           &setlist);
+
+  add_com ("print", class_vars, print_command,
+          concat ("Print value of expression EXP.\n\
+Variables accessible are those of the lexical environment of the selected\n\
+stack frame, plus all those whose scope is global or an entire file.\n\
+\n\
+$NUM gets previous value number NUM.  $ and $$ are the last two values.\n\
+$$NUM refers to NUM'th value back from the last one.\n\
+Names starting with $ refer to registers (with the values they would have\n\
+if the program were to return to the stack frame now selected, restoring\n\
+all registers saved by frames farther in) or else to debugger\n\
+\"convenience\" variables (any such name not a known register).\n\
+Use assignment expressions to give values to convenience variables.\n",
+                  "\n\
+{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\
+@ is a binary operator for treating consecutive data objects\n\
+anywhere in memory as an array.  FOO@NUM gives an array whose first\n\
+element is FOO, whose second element is stored in the space following\n\
+where FOO is stored, etc.  FOO must be an expression whose value\n\
+resides in memory.\n",
+                  "\n\
+EXP may be preceded with /FMT, where FMT is a format letter\n\
+but no count or size letter (see \"x\" command)."));
+  add_com_alias ("p", "print", class_vars, 1);
+
+  add_com ("inspect", class_vars, inspect_command,
+"Same as \"print\" command, except that if you are running in the epoch\n\
+environment, the value is printed in its own window.");
+}
diff --git a/gdb/pyr-opcode.h b/gdb/pyr-opcode.h
new file mode 100755 (executable)
index 0000000..06632b8
--- /dev/null
@@ -0,0 +1,287 @@
+/* pyramid.opcode.h -- gdb initial attempt. */
+
+/* pyramid opcode table: wot to do with this
+   particular opcode */
+
+struct pyr_datum
+{
+  char              nargs;
+  char *            args;      /* how to compile said opcode */
+  unsigned long     mask;      /* Bit vector: which operand modes are valid
+                                  for this opcode */
+  unsigned char     code;      /* op-code (always 6(?) bits */
+};
+
+typedef struct pyr_insn_format {
+    unsigned int mode :4;
+    unsigned int operator :8;
+    unsigned int index_scale :2;
+    unsigned int index_reg :6;
+    unsigned int operand_1 :6;
+    unsigned int operand_2:6;
+} pyr_insn_format;
+       
+
+/* We store four bytes of opcode for all opcodes.
+   Pyramid is sufficiently RISCy that:
+      - insns are always an integral number of words;
+      - the length of any insn can be told from the first word of
+        the insn. (ie, if there are zero, one, or two words of
+       immediate operand/offset).
+
+   
+   The args component is a string containing two characters for each
+   operand of the instruction.  The first specifies the kind of operand;
+   the second, the place it is stored. */
+
+/* Kinds of operands:
+   mask         assembler syntax       description
+   0x0001:  movw Rn,Rn         register to register
+   0x0002:  movw K,Rn          quick immediate to register
+   0x0004:  movw I,Rn          long immediate to register
+   0x0008:  movw (Rn),Rn       register indirect to register
+           movw (Rn)[x],Rn     register indirect to register
+   0x0010:  movw I(Rn),Rn      offset register indirect to register
+           movw I(Rn)[x],Rn    offset register indirect, indexed, to register
+
+   0x0020:  movw Rn,(Rn)       register to register indirect                
+   0x0040:  movw K,(Rn)                quick immediate to register indirect         
+   0x0080:  movw I,(Rn)                long immediate to register indirect          
+   0x0100:  movw (Rn),(Rn)     register indirect to-register indirect       
+   0x0100:  movw (Rn),(Rn)     register indirect to-register indirect       
+   0x0200:  movw I(Rn),(Rn)    register indirect+offset to register indirect
+   0x0200:  movw I(Rn),(Rn)    register indirect+offset to register indirect
+
+   0x0400:  movw Rn,I(Rn)      register to register indirect+offset
+   0x0800:  movw K,I(Rn)       quick immediate to register indirect+offset
+   0x1000:  movw I,I(Rn)       long immediate to register indirect+offset
+   0x1000:  movw (Rn),I(Rn)    register indirect to-register indirect+offset
+   0x1000:  movw I(Rn),I(Rn)   register indirect+offset to register indirect
+                                       +offset
+   0x0000:  (irregular)                ???
+   
+
+   Each insn has a four-bit field encoding the type(s) of its operands.
+*/
+
+/* Some common combinations
+   */
+
+/* the first 5,(0x1|0x2|0x4|0x8|0x10) ie (1|2|4|8|16), ie ( 32 -1)*/
+#define GEN_TO_REG (31)
+
+#define        UNKNOWN ((unsigned long)-1)
+#define ANY (GEN_TO_REG | (GEN_TO_REG << 5) | (GEN_TO_REG << 15))
+
+#define CONVERT (1|8|0x10|0x20|0x200)
+
+#define K_TO_REG (2)
+#define I_TO_REG (4)
+#define NOTK_TO_REG (GEN_TO_REG & ~K_TO_REG)
+#define NOTI_TO_REG (GEN_TO_REG & ~I_TO_REG)
+
+/* The assembler requires that this array be sorted as follows:
+   all instances of the same mnemonic must be consecutive.
+   All instances of the same mnemonic with the same number of operands
+   must be consecutive.
+ */
+
+struct pyr_opcode              /* pyr opcode text */
+{
+  char *            name;      /* opcode name: lowercase string  [key]  */
+  struct pyr_datum  datum;     /* rest of opcode table          [datum] */
+};
+
+#define pyr_how args
+#define pyr_nargs nargs
+#define pyr_mask mask
+#define pyr_name name
+
+struct pyr_opcode pyr_opcodes[] =
+{
+  {"movb",     { 2, "", UNKNOWN,               0x11}, },
+  {"movh",     { 2, "", UNKNOWN,               0x12} },
+  {"movw",     { 2, "", ANY,                   0x10} },
+  {"movl",     { 2, "", ANY,                   0x13} },
+  {"mnegw",    { 2, "", (0x1|0x8|0x10),        0x14} },
+  {"mnegf",    { 2, "", 0x1,                   0x15} },
+  {"mnegd",    { 2, "", 0x1,                   0x16} },
+  {"mcomw",    { 2, "", (0x1|0x8|0x10),        0x17} },
+  {"mabsw",    { 2, "", (0x1|0x8|0x10),        0x18} },
+  {"mabsf",    { 2, "", 0x1,                   0x19} },
+  {"mabsd",    { 2, "", 0x1,                   0x1a} },
+  {"mtstw",    { 2, "", (0x1|0x8|0x10),        0x1c} },
+  {"mtstf",    { 2, "", 0x1,                   0x1d} },
+  {"mtstd",    { 2, "", 0x1,                   0x1e} },
+  {"mova",     { 2, "", 0x8|0x10,              0x1f} },
+  {"movzbw",   { 2, "", (0x1|0x8|0x10),        0x20} },
+  {"movzhw",   { 2, "", (0x1|0x8|0x10),        0x21} },
+                               /* 2 insns out of order here */
+  {"movbl",    { 2, "", 1,                     0x4f} },
+  {"filbl",    { 2, "", 1,                     0x4e} },
+
+  {"cvtbw",    { 2, "", CONVERT,               0x22} },
+  {"cvthw",    { 2, "", CONVERT,               0x23} },
+  {"cvtwb",    { 2, "", CONVERT,               0x24} },
+  {"cvtwh",    { 2, "", CONVERT,               0x25} },
+  {"cvtwf",    { 2, "", CONVERT,               0x26} },
+  {"cvtwd",    { 2, "", CONVERT,               0x27} },
+  {"cvtfw",    { 2, "", CONVERT,               0x28} },
+  {"cvtfd",    { 2, "", CONVERT,               0x29} },
+  {"cvtdw",    { 2, "", CONVERT,               0x2a} },
+  {"cvtdf",    { 2, "", CONVERT,               0x2b} },
+
+  {"addw",     { 2, "", GEN_TO_REG,            0x40} },
+  {"addwc",    { 2, "", GEN_TO_REG,            0x41} },
+  {"subw",     { 2, "", GEN_TO_REG,            0x42} },
+  {"subwb",    { 2, "", GEN_TO_REG,            0x43} },
+  {"rsubw",    { 2, "", GEN_TO_REG,            0x44} },
+  {"mulw",     { 2, "", GEN_TO_REG,            0x45} },
+  {"emul",     { 2, "", GEN_TO_REG,            0x47} },
+  {"umulw",    { 2, "", GEN_TO_REG,            0x46} },
+  {"divw",     { 2, "", GEN_TO_REG,            0x48} },
+  {"ediv",     { 2, "", GEN_TO_REG,            0x4a} },
+  {"rdivw",    { 2, "", GEN_TO_REG,            0x4b} },
+  {"udivw",    { 2, "", GEN_TO_REG,            0x49} },
+  {"modw",     { 2, "", GEN_TO_REG,            0x4c} },
+  {"umodw",    { 2, "", GEN_TO_REG,            0x4d} },
+
+
+  {"addf",     { 2, "", 1,                     0x50} },
+  {"addd",     { 2, "", 1,                     0x51} },
+  {"subf",     { 2, "", 1,                     0x52} },
+  {"subd",     { 2, "", 1,                     0x53} },
+  {"mulf",     { 2, "", 1,                     0x56} },
+  {"muld",     { 2, "", 1,                     0x57} },
+  {"divf",     { 2, "", 1,                     0x58} },
+  {"divd",     { 2, "", 1,                     0x59} },
+
+
+  {"cmpb",     { 2, "", UNKNOWN,               0x61} },
+  {"cmph",     { 2, "", UNKNOWN,               0x62} },
+  {"cmpw",     { 2, "", UNKNOWN,               0x60} },
+  {"ucmpb",    { 2, "", UNKNOWN,               0x66} },
+  /* WHY no "ucmph"??? */
+  {"ucmpw",    { 2, "", UNKNOWN,               0x65} },
+  {"xchw",     { 2, "", UNKNOWN,               0x0f} },
+
+
+  {"andw",     { 2, "", GEN_TO_REG,            0x30} },
+  {"orw",      { 2, "", GEN_TO_REG,            0x31} },
+  {"xorw",     { 2, "", GEN_TO_REG,            0x32} },
+  {"bicw",     { 2, "", GEN_TO_REG,            0x33} },
+  {"lshlw",    { 2, "", GEN_TO_REG,            0x38} },
+  {"ashlw",    { 2, "", GEN_TO_REG,            0x3a} },
+  {"ashll",    { 2, "", GEN_TO_REG,            0x3c} },
+  {"ashrw",    { 2, "", GEN_TO_REG,            0x3b} },
+  {"ashrl",    { 2, "", GEN_TO_REG,            0x3d} },
+  {"rotlw",    { 2, "", GEN_TO_REG,            0x3e} },
+  {"rotrw",    { 2, "", GEN_TO_REG,            0x3f} },
+
+  /* push and pop insns are "going away next release". */
+  {"pushw",    { 2, "", GEN_TO_REG,            0x0c} },
+  {"popw",     { 2, "", (0x1|0x8|0x10),        0x0d} },
+  {"pusha",    { 2, "", (0x8|0x10),            0x0e} },
+
+  {"bitsw",    { 2, "", UNKNOWN,               0x35} },
+  {"bitcw",    { 2, "", UNKNOWN,               0x36} },
+  /* some kind of ibra/dbra insns??*/
+  {"icmpw",    { 2, "", UNKNOWN,               0x67} },
+  {"dcmpw",    { 2, "", (1|4|0x20|0x80|0x400|0x1000),  0x69} },/*FIXME*/
+  {"acmpw",    { 2, "", 1,                     0x6b} },
+
+  /* Call is written as a 1-op insn, but is always (dis)assembled as a 2-op
+     insn with a 2nd op of tr14.   The assembler will have to grok this.  */
+  {"call",     { 2, "", GEN_TO_REG,            0x04} },
+  {"call",     { 1, "", GEN_TO_REG,            0x04} },
+
+  {"callk",    { 1, "", UNKNOWN,               0x06} },/* system call?*/
+  /* Ret is usually written as a 0-op insn, but gets disassembled as a
+     1-op insn. The operand is always tr15. */
+  {"ret",      { 0, "", UNKNOWN,               0x09} },
+  {"ret",      { 1, "", UNKNOWN,               0x09} },
+  {"adsf",     { 2, "", (1|2|4),               0x08} },
+  {"retd",     { 2, "", UNKNOWN,               0x0a} },
+  {"btc",      { 2, "", UNKNOWN,               0x01} },
+  {"bfc",      { 2, "", UNKNOWN,               0x02} },
+  /* Careful: halt is 0x00000000. Jump must have some other (mode?)bit set?? */
+  {"jump",     { 1, "", UNKNOWN,               0x00} },
+  {"btp",      { 2, "", UNKNOWN,               0xf00} },
+  /* read control-stack pointer is another 1-or-2 operand insn. */
+  {"rcsp",     { 2, "", UNKNOWN,               0x01f} },
+  {"rcsp",     { 1, "", UNKNOWN,               0x01f} }
+};
+
+/* end: pyramid.opcode.h */
+/* One day I will have to take the time to find out what operands
+   are valid for these insns, and guess at what they mean.
+
+   I can't imagine what the "I???" insns (iglob, etc) do.
+
+   the arithmetic-sounding insns ending in "p" sound awfully like BCD
+   arithmetic insns:
+       dshlp -> Decimal SHift Left Packed
+       dshrp -> Decimal SHift Right Packed
+   and cvtlp would be convert long to packed.
+   I have no idea how the operands are interpreted; but having them be
+   a long register with (address, length) of an in-memory packed BCD operand
+   would not be surprising.
+   They are unlikely to be a packed bcd string: 64 bits of long give
+   is only 15 digits+sign, which isn't enough for COBOL.
+ */ 
+#if 0
+  {"wcsp",     { 2, "", UNKNOWN,               0x00} }, /*write csp?*/
+  /* The OSx Operating System Porting Guide claims SSL does things
+     with tr12 (a register reserved to it) to do with static block-structure
+     references.  SSL=Set Static Link?  It's "Going away next release". */
+  {"ssl",      { 2, "", UNKNOWN,               0x00} },
+  {"ccmps",    { 2, "", UNKNOWN,               0x00} },
+  {"lcd",      { 2, "", UNKNOWN,               0x00} },
+  {"uemul",    { 2, "", UNKNOWN,               0x00} }, /*unsigned emul*/
+  {"srf",      { 2, "", UNKNOWN,               0x00} }, /*Gidget time???*/
+  {"mnegp",    { 2, "", UNKNOWN,               0x00} }, /move-neg phys?*/
+  {"ldp",      { 2, "", UNKNOWN,               0x00} }, /*load phys?*/
+  {"ldti",     { 2, "", UNKNOWN,               0x00} },
+  {"ldb",      { 2, "", UNKNOWN,               0x00} },
+  {"stp",      { 2, "", UNKNOWN,               0x00} },
+  {"stti",     { 2, "", UNKNOWN,               0x00} },
+  {"stb",      { 2, "", UNKNOWN,               0x00} },
+  {"stu",      { 2, "", UNKNOWN,               0x00} },
+  {"addp",     { 2, "", UNKNOWN,               0x00} },
+  {"subp",     { 2, "", UNKNOWN,               0x00} },
+  {"mulp",     { 2, "", UNKNOWN,               0x00} },
+  {"divp",     { 2, "", UNKNOWN,               0x00} },
+  {"dshlp",    { 2, "", UNKNOWN,               0x00} },  /* dec shl packed? */
+  {"dshrp",    { 2, "", UNKNOWN,               0x00} }, /* dec shr packed? */
+  {"movs",     { 2, "", UNKNOWN,               0x00} }, /*move (string?)?*/
+  {"cmpp",     { 2, "", UNKNOWN,               0x00} }, /* cmp phys?*/
+  {"cmps",     { 2, "", UNKNOWN,               0x00} }, /* cmp (string?)?*/
+  {"cvtlp",    { 2, "", UNKNOWN,               0x00} }, /* cvt long to p??*/
+  {"cvtpl",    { 2, "", UNKNOWN,               0x00} }, /* cvt p to l??*/
+  {"dintr",    { 2, "", UNKNOWN,               0x00} }, /* ?? intr ?*/
+  {"rphysw",   { 2, "", UNKNOWN,               0x00} }, /* read phys word?*/
+  {"wphysw",   { 2, "", UNKNOWN,               0x00} }, /* write phys word?*/
+  {"cmovs",    { 2, "", UNKNOWN,               0x00} },
+  {"rsubw",    { 2, "", UNKNOWN,               0x00} },
+  {"bicpsw",   { 2, "", UNKNOWN,               0x00} }, /* clr bit in psw? */
+  {"bispsw",   { 2, "", UNKNOWN,               0x00} }, /* set bit in psw? */
+  {"eio",      { 2, "", UNKNOWN,               0x00} }, /* ?? ?io ? */
+  {"callp",    { 2, "", UNKNOWN,               0x00} }, /* call phys?*/
+  {"callr",    { 2, "", UNKNOWN,               0x00} },
+  {"lpcxt",    { 2, "", UNKNOWN,               0x00} }, /*load proc context*/
+  {"rei",      { 2, "", UNKNOWN,               0x00} }, /*ret from intrpt*/
+  {"rport",    { 2, "", UNKNOWN,               0x00} }, /*read-port?*/
+  {"rtod",     { 2, "", UNKNOWN,               0x00} }, /*read-time-of-day?*/
+  {"ssi",      { 2, "", UNKNOWN,               0x00} },
+  {"vtpa",     { 2, "", UNKNOWN,               0x00} }, /*virt-to-phys-addr?*/
+  {"wicl",     { 2, "", UNKNOWN,               0x00} }, /* write icl ? */
+  {"wport",    { 2, "", UNKNOWN,               0x00} }, /*write-port?*/
+  {"wtod",     { 2, "", UNKNOWN,               0x00} }, /*write-time-of-day?*/
+  {"flic",     { 2, "", UNKNOWN,               0x00} },
+  {"iglob",    { 2, "", UNKNOWN,               0x00} }, /* I global? */
+  {"iphys",    { 2, "", UNKNOWN,               0x00} }, /* I physical? */
+  {"ipid",     { 2, "", UNKNOWN,               0x00} }, /* I pid? */
+  {"ivect",    { 2, "", UNKNOWN,               0x00} }, /* I vector? */
+  {"lamst",    { 2, "", UNKNOWN,               0x00} },
+  {"tio",      { 2, "", UNKNOWN,               0x00} },
+#endif
diff --git a/gdb/pyr-pinsn.c b/gdb/pyr-pinsn.c
new file mode 100644 (file)
index 0000000..d58ae47
--- /dev/null
@@ -0,0 +1,347 @@
+/* Disassembler for the Pyramid Technology 90x
+   Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+This file is part of GDB, the GNU disassembler.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "pyr-opcode.h"
+#include "gdbcore.h"
+
+\f
+/*  A couple of functions used for debugging frame-handling on
+    Pyramids. (The Pyramid-dependent handling of register values for
+    windowed registers is known to be buggy.)
+
+    When debugging, these functions supplant the normal definitions of some
+    of the macros in m-pyramid.h  The quantity of information produced
+    when these functions are used makes the gdb  unusable as a
+    debugger for user programs.  */
+    
+extern unsigned pyr_saved_pc(), pyr_frame_chain();
+
+CORE_ADDR pyr_frame_chain(frame)
+    CORE_ADDR frame;
+{
+    int foo=frame - CONTROL_STACK_FRAME_SIZE;
+    /* printf ("...following chain from %x: got %x\n", frame, foo);*/
+    return foo;
+}
+
+CORE_ADDR pyr_saved_pc(frame)
+    CORE_ADDR frame;
+{
+    int foo=0;
+    foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
+    printf ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
+           frame, 60/4, foo);
+    return foo;
+}
+\f
+
+/* Pyramid instructions are never longer than this many bytes.  */
+#define MAXLEN 24
+
+/* Number of elements in the opcode table.  */
+/*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
+#define NOPCODES (nopcodes)
+
+extern char *reg_names[];
+\f
+/* Let's be byte-independent so we can use this as a cross-assembler.
+   (will this ever be useful?
+ */
+
+#define NEXTLONG(p)  \
+  (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+\f
+/* Print one instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  unsigned char buffer[MAXLEN];
+  register int i, nargs, insn_size =4;
+  register unsigned char *p;
+  register char *d;
+  register int insn_opcode, operand_mode;
+  register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ;
+  long insn;                   /* first word of the insn, not broken down. */
+  pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */
+  long extra_1, extra_2;
+
+  read_memory (memaddr, buffer, MAXLEN);
+  insn_decode = *((pyr_insn_format *) buffer);
+  insn = * ((int *) buffer);
+  insn_opcode = insn_decode.operator;
+  operand_mode = insn_decode.mode;
+  index_multiplier = insn_decode.index_scale;
+  index_reg_regno = insn_decode.index_reg;
+  op_1_regno = insn_decode.operand_1;
+  op_2_regno = insn_decode.operand_2;
+  
+  
+  if (*((int *)buffer) == 0x0) {
+    /* "halt" looks just like an invalid "jump" to the insn decoder,
+       so is dealt with as a special case */
+    fprintf (stream, "halt");
+    return (4);
+  }
+
+  for (i = 0; i < NOPCODES; i++)
+         if (pyr_opcodes[i].datum.code == insn_opcode)
+                 break;
+
+  if (i == NOPCODES)
+         /* FIXME: Handle unrecognised instructions better.  */
+         fprintf (stream, "???\t#%08x\t(op=%x mode =%x)",
+                  insn, insn_decode.operator, insn_decode.mode);
+  else
+    {
+      /* Print the mnemonic for the instruction.  Pyramid insn operands
+         are so regular that we can deal with almost all of them
+         separately.
+        Unconditional branches are an exception: they are encoded as
+        conditional branches (branch if false condition, I think)
+        with no condition specified. The average user will not be
+        aware of this. To maintain their illusion that an
+        unconditional branch insn exists, we will have to FIXME to
+        treat the insn mnemnonic of all branch instructions here as a
+        special case: check the operands of branch insn and print an
+        appropriate mnemonic. */ 
+
+      fprintf (stream, "%s\t", pyr_opcodes[i].name);
+
+    /* Print the operands of the insn (as specified in
+       insn.operand_mode). 
+       Branch operands of branches are a special case: they are a word
+       offset, not a byte offset. */
+  
+    if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
+      register int bit_codes=(insn >> 16)&0xf;
+      register int i;
+      register int displacement = (insn & 0x0000ffff) << 2;
+
+      static char cc_bit_names[] = "cvzn";     /* z,n,c,v: strange order? */
+
+      /* Is bfc and no bits specified an unconditional branch?*/
+      for (i=0;i<4;i++) {
+       if ((bit_codes) & 0x1)
+               fputc (cc_bit_names[i], stream);
+       bit_codes >>= 1;
+      }
+
+      fprintf (stream, ",%0x",
+              displacement + memaddr);
+      return (insn_size);
+    }
+
+      switch (operand_mode) {
+      case 0:
+       fprintf (stream, "%s,%s",
+                reg_names [op_1_regno],
+                reg_names [op_2_regno]);
+       break;
+           
+      case 1:
+       fprintf (stream, " 0x%0x,%s",
+                op_1_regno,
+                reg_names [op_2_regno]);
+       break;
+       
+      case 2:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       fprintf (stream, " $0x%0x,%s",
+                extra_1,
+                reg_names [op_2_regno]);
+       break;
+      case 3:
+       fprintf (stream, " (%s),%s",
+                reg_names [op_1_regno],
+                reg_names [op_2_regno]);
+       break;
+       
+      case 4:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       fprintf (stream, " 0x%0x(%s),%s",
+                extra_1,
+                reg_names [op_1_regno],
+                reg_names [op_2_regno]);
+       break;
+       
+       /* S1 destination mode */
+      case 5:
+       fprintf (stream,
+                ((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"),
+                reg_names [op_1_regno],
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+       
+      case 6:
+       fprintf (stream,
+                ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+                 : " $%#0x,(%s)"),
+                op_1_regno,
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+       
+      case 7:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       fprintf (stream,
+                ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+                 : " $%#0x,(%s)"),
+                extra_1,
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+       
+      case 8:
+       fprintf (stream,
+                ((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"),
+                reg_names [op_1_regno],
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+       
+      case 9:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       fprintf (stream,
+                ((index_reg_regno)
+                 ? "%#0x(%s),(%s)[%s*%1d]"
+                 : "%#0x(%s),(%s)"),
+                extra_1,
+                reg_names [op_1_regno],
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+       
+       /* S2 destination mode */
+      case 10:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       fprintf (stream,
+                ((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
+                reg_names [op_1_regno],
+                extra_1,
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+      case 11:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       fprintf (stream,
+                ((index_reg_regno) ?
+                 " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+                op_1_regno,
+                extra_1,
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+      case 12:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       read_memory (memaddr+8, buffer, MAXLEN);
+       insn_size += 4;
+       extra_2 = * ((int *) buffer);
+       fprintf (stream,
+                ((index_reg_regno) ?
+                 " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+                extra_1,
+                extra_2,
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+       
+      case 13:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       fprintf (stream,
+                ((index_reg_regno)
+                 ? " (%s),%#0x(%s)[%s*%1d]" 
+                 : " (%s),%#0x(%s)"),
+                reg_names [op_1_regno],
+                extra_1,
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+      case 14:
+       read_memory (memaddr+4, buffer, MAXLEN);
+       insn_size += 4;
+       extra_1 = * ((int *) buffer);
+       read_memory (memaddr+8, buffer, MAXLEN);
+       insn_size += 4;
+       extra_2 = * ((int *) buffer);
+       fprintf (stream,
+                ((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
+                 : "%#0x(%s),%#0x(%s) "),
+                extra_1,
+                reg_names [op_1_regno],
+                extra_2,
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       break;
+       
+      default:
+       fprintf (stream,
+                ((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"),
+                reg_names [op_1_regno],
+                reg_names [op_2_regno],
+                reg_names [index_reg_regno],
+                index_multiplier);
+       fprintf (stream,
+                "\t\t# unknown mode in %08x",
+                insn);
+       break;
+      } /* switch */
+    }
+  
+  {
+    return insn_size;
+  }
+  abort ();
+}
diff --git a/gdb/pyr-tdep.c b/gdb/pyr-tdep.c
new file mode 100644 (file)
index 0000000..b79ea0c
--- /dev/null
@@ -0,0 +1,129 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*** Prettier register printing. ***/
+
+/* Print registers in the same format as pyramid's dbx, adb, sdb.  */
+pyr_print_registers(reg_buf, regnum)
+    long *reg_buf[];
+{
+  register int regno;
+  int usp, ksp;
+  struct user u;
+
+  for (regno = 0; regno < 16; regno++) {
+    printf/*_filtered*/ ("%6.6s: %8x  %6.6s: %8x  %6s: %8x  %6s: %8x\n",
+                    reg_names[regno], reg_buf[regno],
+                    reg_names[regno+16], reg_buf[regno+16],
+                    reg_names[regno+32], reg_buf[regno+32],
+                    reg_names[regno+48], reg_buf[regno+48]);
+  }
+  usp = ptrace (3, inferior_pid,
+                     ((char *)&u.u_pcb.pcb_usp) -
+                     ((char *)&u), 0);
+  ksp = ptrace (3, inferior_pid,
+                     ((char *)&u.u_pcb.pcb_ksp) -
+                     ((char *)&u), 0);
+  printf/*_filtered*/ ("\n%6.6s: %8x  %6.6s: %8x (%08x) %6.6s %8x\n",
+                  reg_names[CSP_REGNUM],reg_buf[CSP_REGNUM],
+                  reg_names[KSP_REGNUM], reg_buf[KSP_REGNUM], ksp,
+                  "usp", usp);
+}
+
+/* Print the register regnum, or all registers if regnum is -1. */
+
+pyr_do_registers_info (regnum)
+    int regnum;
+{
+  /* On a pyr, we know a virtual register can always fit in an long.
+     Here (and elsewhere) we take advantage of that.  Yuk.  */
+  long raw_regs[MAX_REGISTER_RAW_SIZE*NUM_REGS];
+  register int i;
+  
+  for (i = 0 ; i < 64 ; i++) {
+    read_relative_register_raw_bytes(i, raw_regs+i);
+  }
+  if (regnum == -1)
+    pyr_print_registers (raw_regs, regnum);
+  else
+    for (i = 0; i < NUM_REGS; i++)
+      if (i == regnum) {
+       long val = raw_regs[i];
+       
+       fputs_filtered (reg_names[i], stdout);
+       printf_filtered(":");
+       print_spaces_filtered (6 - strlen (reg_names[i]), stdout);
+       if (val == 0)
+         printf_filtered ("0");
+       else
+         printf_filtered ("0x%08x  %d", val, val);
+       printf_filtered("\n");
+      }
+}
+\f
+/*** Debugging editions of various macros from m-pyr.h ****/
+
+CORE_ADDR frame_locals_address (frame)
+    FRAME frame;
+{
+  register int addr = find_saved_register (frame,CFP_REGNUM);
+  register int result = read_memory_integer (addr, 4);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+  fprintf (stderr,
+          "\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+          frame->frame,
+          reg_names[CFP_REGNUM],
+          result, addr,
+          frame->frame_cfp, (CFP_REGNUM),
+
+
+          read_register(13), read_register(29), read_register(61),
+          find_saved_register(frame, 61));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+  /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+     or at least CFP_REGNUM relative to FRAME (ie, result).
+     There seems to be a bug in the way the innermost frame is set up.  */
+
+    return ((frame->next) ? result: frame->frame_cfp);
+}
+
+CORE_ADDR frame_args_addr (frame)
+    FRAME frame;
+{
+  register int addr = find_saved_register (frame,CFP_REGNUM);
+  register int result = read_memory_integer (addr, 4);
+
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+  fprintf (stderr,
+          "\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+          frame->frame,
+          reg_names[CFP_REGNUM],
+          result, addr,
+          frame->frame_cfp, read_register(CFP_REGNUM),
+
+          read_register(13), read_register(29), read_register(61),
+          find_saved_register(frame, 61));
+#endif /*  PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+  /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+     or at least CFP_REGNUM relative to FRAME (ie, result).
+     There seems to be a bug in the way the innermost frame is set up.  */
+    return ((frame->next) ? result: frame->frame_cfp);
+}
diff --git a/gdb/pyr-xdep.c b/gdb/pyr-xdep.c
new file mode 100644 (file)
index 0000000..5ba4a8d
--- /dev/null
@@ -0,0 +1,366 @@
+/* Low level Pyramid interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h>  Can we live without this?  */
+
+#include "gdbcore.h"
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+void
+fetch_inferior_registers ()
+{
+  register int regno, datum;
+  register unsigned int regaddr;
+  int reg_buf[NUM_REGS+1];
+  struct user u;
+  register int skipped_frames = 0;
+
+  registers_fetched ();
+  
+  for (regno = 0; regno < 64; regno++) {
+    reg_buf[regno] = ptrace (3, inferior_pid, regno, 0);
+    
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+    printf ("Fetching %s from inferior, got %0x\n",
+           reg_names[regno],
+           reg_buf[regno]);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+    
+    if (reg_buf[regno] == -1 && errno == EIO) {
+      printf("fetch_interior_registers: fetching %s from inferior\n",
+            reg_names[regno]);
+      errno = 0;
+    }
+    supply_register (regno, reg_buf+regno);
+  }
+  /* that leaves regs 64, 65, and 66 */
+  datum = ptrace (3, inferior_pid,
+                 ((char *)&u.u_pcb.pcb_csp) -
+                 ((char *)&u), 0);
+  
+  
+  
+  /* FIXME: Find the Current Frame Pointer (CFP). CFP is a global
+     register (ie, NOT windowed), that gets saved in a frame iff
+     the code for that frame has a prologue (ie, "adsf N").  If
+     there is a prologue, the adsf insn saves the old cfp in
+     pr13, cfp is set to sp, and N bytes of locals are allocated
+     (sp is decremented by n).
+     This makes finding CFP hard. I guess the right way to do it
+     is: 
+     - If this is the innermost frame, believe ptrace() or
+     the core area.
+     - Otherwise:
+     Find the first insn of the current frame.
+     - find the saved pc;
+     - find the call insn that saved it;
+     - figure out where the call is to;
+     - if the first insn is an adsf, we got a frame
+     pointer. */
+  
+  
+  /* Normal processors have separate stack pointers for user and
+     kernel mode. Getting the last user mode frame on such
+     machines is easy: the kernel context of the ptrace()'d
+     process is on the kernel stack, and the USP points to what
+     we want. But Pyramids only have a single cfp for both user and
+     kernel mode.  And processes being ptrace()'d have some
+     kernel-context control frames on their stack.
+     To avoid tracing back into the kernel context of an inferior,
+     we skip 0 or more contiguous control frames where the pc is
+     in the kernel. */ 
+  
+  while (1) {
+    register int inferior_saved_pc;
+    inferior_saved_pc = ptrace (1, inferior_pid, datum+((32+15)*4), 0);
+    if (inferior_saved_pc > 0) break;
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+    printf("skipping kernel frame %08x, pc=%08x\n", datum,
+          inferior_saved_pc);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+    skipped_frames++;
+    datum -= CONTROL_STACK_FRAME_SIZE;
+  }
+  
+  reg_buf[CSP_REGNUM] = datum;
+  supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
+#ifdef  PYRAMID_CONTROL_FRAME_DEBUGGING
+  if (skipped_frames) {
+    fprintf (stderr,
+            "skipped %d frames from %x to %x; cfp was %x, now %x\n",
+            skipped_frames, reg_buf[CSP_REGNUM]);
+  }
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+
+  if (regno >= 0)
+    {
+      if ((0 <= regno) && (regno < 64)) {
+       /*regaddr = register_addr (regno, offset);*/
+       regaddr = regno;
+       errno = 0;
+       ptrace (6, inferior_pid, regaddr, read_register (regno));
+       if (errno != 0)
+         {
+           sprintf (buf, "writing register number %d", regno);
+           perror_with_name (buf);
+         }
+      }
+    }
+  else
+    {
+      for (regno = 0; regno < NUM_REGS; regno++)
+       {
+         /*regaddr = register_addr (regno, offset);*/
+         regaddr = regno;
+         errno = 0;
+         ptrace (6, inferior_pid, regaddr, read_register (regno));
+         if (errno != 0)
+           {
+             sprintf (buf, "writing all regs, number %d", regno);
+             perror_with_name (buf);
+           }
+       }
+}
+\f
+/*** Extensions to  core and dump files, for GDB. */
+
+extern unsigned int last_frame_offset;
+
+#ifdef PYRAMID_CORE
+
+/* Can't make definitions here static, since core.c needs them
+   to do bounds checking on the core-file areas. O well. */
+
+/* have two stacks: one for data, one for register windows. */
+extern CORE_ADDR reg_stack_start;
+extern CORE_ADDR reg_stack_end;
+
+/* need this so we can find the global registers: they never get saved. */
+CORE_ADDR global_reg_offset;
+static CORE_ADDR last_frame_address;
+CORE_ADDR last_frame_offset;
+
+
+/* Address in core file of start of register window stack area.
+   Don't know if is this any of meaningful, useful or necessary.   */
+extern int reg_stack_offset;
+
+#endif /* PYRAMID_CORE */  
+
+\f
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+#ifdef PYRAMID_CORE
+  reg_stack_start = CONTROL_STACK_ADDR;
+  reg_stack_end = CONTROL_STACK_ADDR;  /* this isn't strictly true...*/
+#endif /* PYRAMID_CORE */
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+       struct user u;
+
+       unsigned int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name ("Not a core file: reading upage");
+       if (val != sizeof u)
+         error ("Not a core file: could only read %d bytes", val);
+       data_start = exec_data_start;
+
+       data_end = data_start + NBPG * u.u_dsize;
+       data_offset = NBPG * UPAGES;
+       stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+       /* find registers in core file */
+#ifdef PYRAMID_PTRACE
+       stack_start = stack_end - NBPG * u.u_ussize;
+       reg_stack_offset = stack_offset + (NBPG *u.u_ussize);
+       reg_stack_end = reg_stack_start + NBPG * u.u_cssize;
+
+       last_frame_address = ((int) u.u_pcb.pcb_csp);
+       last_frame_offset = reg_stack_offset + last_frame_address
+               - CONTROL_STACK_ADDR ;
+       global_reg_offset = (char *)&u - (char *)&u.u_pcb.pcb_gr0 ;
+
+       /* skip any control-stack frames that were executed in the
+          kernel. */
+
+       while (1) {
+           char buf[4];
+           val = lseek (corechan, last_frame_offset+(47*4), 0);
+           if (val < 0)
+                   perror_with_name (filename);
+           val = myread (corechan, buf, sizeof buf);
+           if (val < 0)
+                   perror_with_name (filename);
+
+           if (*(int *)buf >= 0)
+                   break;
+           printf ("skipping frame %0x\n", last_frame_address);
+           last_frame_offset -= CONTROL_STACK_FRAME_SIZE;
+           last_frame_address -= CONTROL_STACK_FRAME_SIZE;
+       }
+       reg_offset = last_frame_offset;
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+       printf ("Control stack pointer = 0x%08x\n",
+               u.u_pcb.pcb_csp);
+       printf ("offset to control stack %d outermost frame %d (%0x)\n",
+             reg_stack_offset, reg_offset, last_frame_address);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+#else /* not PYRAMID_CORE */
+       stack_start = stack_end - NBPG * u.u_ssize;
+        reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+#endif /* not PYRAMID_CORE */
+
+#ifdef __not_on_pyr_yet
+       /* Some machines put an absolute address in here and some put
+          the offset in the upage of the regs.  */
+       reg_offset = (int) u.u_ar0;
+       if (reg_offset > NBPG * UPAGES)
+         reg_offset -= KERNEL_U_ADDR;
+#endif
+
+       /* I don't know where to find this info.
+          So, for now, mark it as not available.  */
+       N_SET_MAGIC (core_aouthdr, 0);
+
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < 64; regno++)
+           {
+             char buf[MAX_REGISTER_RAW_SIZE];
+
+             val = lseek (corechan, register_addr (regno, reg_offset), 0);
+             if (val < 0
+                 || (val = myread (corechan, buf, sizeof buf)) < 0)
+               {
+                 char * buffer = (char *) alloca (strlen (reg_names[regno])
+                                                  + 30);
+                 strcpy (buffer, "Reading register ");
+                 strcat (buffer, reg_names[regno]);
+                                                  
+                 perror_with_name (buffer);
+               }
+
+             if (val < 0)
+               perror_with_name (filename);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+      printf ("[reg %s(%d), offset in file %s=0x%0x, addr =0x%0x, =%0x]\n",
+             reg_names[regno], regno, filename,
+             register_addr(regno, reg_offset),
+             regno * 4 + last_frame_address,
+             *((int *)buf));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+      printf ("Providing CSP (%0x) as nominal address of current frame.\n",
+             last_frame_address);
+#endif PYRAMID_CONTROL_FRAME_DEBUGGING
+      /* FIXME: Which of the following is correct? */
+#if 0
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+#else
+      set_current_frame ( create_new_frame (last_frame_address,
+                                           read_pc ()));
+#endif
+
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
diff --git a/gdb/regex.c b/gdb/regex.c
new file mode 100644 (file)
index 0000000..45c3478
--- /dev/null
@@ -0,0 +1,1738 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 1985, 1989 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  */
+
+
+/* To test, compile with -Dtest.
+ This Dtestable feature turns this into a self-contained program
+ which reads a pattern, describes how it compiles,
+ then reads a string and searches for it.  */
+
+#ifdef emacs
+
+/* The `emacs' switch turns on certain special matching commands
+ that make sense only in emacs. */
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+#else  /* not emacs */
+
+#ifdef USG
+#ifndef BSTRING
+#define bcopy(s,d,n)   memcpy((d),(s),(n))
+#define bcmp(s1,s2,n)  memcmp((s1),(s2),(n))
+#define bzero(s,n)     memset((s),0,(n))
+#endif
+#endif
+
+/* Make alloca work the best possible way.  */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef sparc
+#include <alloca.h>
+#endif
+#endif
+
+/*
+ * Define the syntax stuff, so we can do the \<...\> things.
+ */
+
+#ifndef Sword /* must be non-zero in some of the tests below... */
+#define Sword 1
+#endif
+
+#define SYNTAX(c) re_syntax_table[c]
+
+#ifdef SYNTAX_TABLE
+
+char *re_syntax_table;
+
+#else
+
+static char re_syntax_table[256];
+
+static void
+init_syntax_once ()
+{
+   register int c;
+   static int done = 0;
+
+   if (done)
+     return;
+
+   bzero (re_syntax_table, sizeof re_syntax_table);
+
+   for (c = 'a'; c <= 'z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = 'A'; c <= 'Z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = '0'; c <= '9'; c++)
+     re_syntax_table[c] = Sword;
+
+   done = 1;
+}
+
+#endif /* SYNTAX_TABLE */
+#endif /* not emacs */
+
+#include "regex.h"
+
+/* Number of failure points to allocate space for initially,
+ when matching.  If this number is exceeded, more space is allocated,
+ so it is not a hard limit.  */
+
+#ifndef NFAILURES
+#define NFAILURES 80
+#endif /* NFAILURES */
+
+/* width of a byte in bits */
+
+#define BYTEWIDTH 8
+
+#ifndef SIGN_EXTEND_CHAR
+#define SIGN_EXTEND_CHAR(x) (x)
+#endif
+\f
+static int obscure_syntax = 0;
+
+/* Specify the precise syntax of regexp for compilation.
+   This provides for compatibility for various utilities
+   which historically have different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit-mask containing the two bits
+   RE_NO_BK_PARENS and RE_NO_BK_VBAR.  */
+
+int
+re_set_syntax (syntax)
+{
+  int ret;
+
+  ret = obscure_syntax;
+  obscure_syntax = syntax;
+  return ret;
+}
+\f
+/* re_compile_pattern takes a regular-expression string
+   and converts it into a buffer full of byte commands for matching.
+
+  PATTERN   is the address of the pattern string
+  SIZE      is the length of it.
+  BUFP     is a  struct re_pattern_buffer *  which points to the info
+           on where to store the byte commands.
+           This structure contains a  char *  which points to the
+           actual space, which should have been obtained with malloc.
+           re_compile_pattern may use  realloc  to grow the buffer space.
+
+  The number of bytes of commands can be found out by looking in
+  the  struct re_pattern_buffer  that bufp pointed to,
+  after re_compile_pattern returns.
+*/
+
+#define PATPUSH(ch) (*b++ = (char) (ch))
+
+#define PATFETCH(c) \
+ {if (p == pend) goto end_of_pattern; \
+  c = * (unsigned char *) p++; \
+  if (translate) c = translate[c]; }
+
+#define PATFETCH_RAW(c) \
+ {if (p == pend) goto end_of_pattern; \
+  c = * (unsigned char *) p++; }
+
+#define PATUNFETCH p--
+
+#define EXTEND_BUFFER \
+  { char *old_buffer = bufp->buffer; \
+    if (bufp->allocated == (1<<16)) goto too_big; \
+    bufp->allocated *= 2; \
+    if (bufp->allocated > (1<<16)) bufp->allocated = (1<<16); \
+    if (!(bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated))) \
+      goto memory_exhausted; \
+    c = bufp->buffer - old_buffer; \
+    b += c; \
+    if (fixup_jump) \
+      fixup_jump += c; \
+    if (laststart) \
+      laststart += c; \
+    begalt += c; \
+    if (pending_exact) \
+      pending_exact += c; \
+  }
+
+static int store_jump (), insert_jump ();
+
+char *
+re_compile_pattern (pattern, size, bufp)
+     char *pattern;
+     int size;
+     struct re_pattern_buffer *bufp;
+{
+  register char *b = bufp->buffer;
+  register char *p = pattern;
+  char *pend = pattern + size;
+  register unsigned c, c1;
+  char *p1;
+  unsigned char *translate = (unsigned char *) bufp->translate;
+
+  /* address of the count-byte of the most recently inserted "exactn" command.
+    This makes it possible to tell whether a new exact-match character
+    can be added to that command or requires a new "exactn" command. */
+     
+  char *pending_exact = 0;
+
+  /* address of the place where a forward-jump should go
+    to the end of the containing expression.
+    Each alternative of an "or", except the last, ends with a forward-jump
+    of this sort. */
+
+  char *fixup_jump = 0;
+
+  /* address of start of the most recently finished expression.
+    This tells postfix * where to find the start of its operand. */
+
+  char *laststart = 0;
+
+  /* In processing a repeat, 1 means zero matches is allowed */
+
+  char zero_times_ok;
+
+  /* In processing a repeat, 1 means many matches is allowed */
+
+  char many_times_ok;
+
+  /* address of beginning of regexp, or inside of last \( */
+
+  char *begalt = b;
+
+  /* Stack of information saved by \( and restored by \).
+     Four stack elements are pushed by each \(:
+       First, the value of b.
+       Second, the value of fixup_jump.
+       Third, the value of regnum.
+       Fourth, the value of begalt.  */
+
+  int stackb[40];
+  int *stackp = stackb;
+  int *stacke = stackb + 40;
+  int *stackt;
+
+  /* Counts \('s as they are encountered.  Remembered for the matching \),
+     where it becomes the "register number" to put in the stop_memory command */
+
+  int regnum = 1;
+
+  bufp->fastmap_accurate = 0;
+
+#ifndef emacs
+#ifndef SYNTAX_TABLE
+  /*
+   * Initialize the syntax table.
+   */
+   init_syntax_once();
+#endif
+#endif
+
+  if (bufp->allocated == 0)
+    {
+      bufp->allocated = 28;
+      if (bufp->buffer)
+       /* EXTEND_BUFFER loses when bufp->allocated is 0 */
+       bufp->buffer = (char *) realloc (bufp->buffer, 28);
+      else
+       /* Caller did not allocate a buffer.  Do it for him */
+       bufp->buffer = (char *) malloc (28);
+      if (!bufp->buffer) goto memory_exhausted;
+      begalt = b = bufp->buffer;
+    }
+
+  while (p != pend)
+    {
+      if (b - bufp->buffer > bufp->allocated - 10)
+       /* Note that EXTEND_BUFFER clobbers c */
+       EXTEND_BUFFER;
+
+      PATFETCH (c);
+
+      switch (c)
+       {
+       case '$':
+         if (obscure_syntax & RE_TIGHT_VBAR)
+           {
+             if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend)
+               goto normal_char;
+             /* Make operand of last vbar end before this `$'.  */
+             if (fixup_jump)
+               store_jump (fixup_jump, jump, b);
+             fixup_jump = 0;
+             PATPUSH (endline);
+             break;
+           }
+
+         /* $ means succeed if at end of line, but only in special contexts.
+           If randomly in the middle of a pattern, it is a normal character. */
+         if (p == pend || *p == '\n'
+             || (obscure_syntax & RE_CONTEXT_INDEP_OPS)
+             || (obscure_syntax & RE_NO_BK_PARENS
+                 ? *p == ')'
+                 : *p == '\\' && p[1] == ')')
+             || (obscure_syntax & RE_NO_BK_VBAR
+                 ? *p == '|'
+                 : *p == '\\' && p[1] == '|'))
+           {
+             PATPUSH (endline);
+             break;
+           }
+         goto normal_char;
+
+       case '^':
+         /* ^ means succeed if at beg of line, but only if no preceding pattern. */
+
+         if (laststart && p[-2] != '\n'
+             && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+           goto normal_char;
+         if (obscure_syntax & RE_TIGHT_VBAR)
+           {
+             if (p != pattern + 1
+                 && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+               goto normal_char;
+             PATPUSH (begline);
+             begalt = b;
+           }
+         else
+           PATPUSH (begline);
+         break;
+
+       case '+':
+       case '?':
+         if (obscure_syntax & RE_BK_PLUS_QM)
+           goto normal_char;
+       handle_plus:
+       case '*':
+         /* If there is no previous pattern, char not special. */
+         if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+           goto normal_char;
+         /* If there is a sequence of repetition chars,
+            collapse it down to equivalent to just one.  */
+         zero_times_ok = 0;
+         many_times_ok = 0;
+         while (1)
+           {
+             zero_times_ok |= c != '+';
+             many_times_ok |= c != '?';
+             if (p == pend)
+               break;
+             PATFETCH (c);
+             if (c == '*')
+               ;
+             else if (!(obscure_syntax & RE_BK_PLUS_QM)
+                      && (c == '+' || c == '?'))
+               ;
+             else if ((obscure_syntax & RE_BK_PLUS_QM)
+                      && c == '\\')
+               {
+                 int c1;
+                 PATFETCH (c1);
+                 if (!(c1 == '+' || c1 == '?'))
+                   {
+                     PATUNFETCH;
+                     PATUNFETCH;
+                     break;
+                   }
+                 c = c1;
+               }
+             else
+               {
+                 PATUNFETCH;
+                 break;
+               }
+           }
+
+         /* Star, etc. applied to an empty pattern is equivalent
+            to an empty pattern.  */
+         if (!laststart)
+           break;
+
+         /* Now we know whether 0 matches is allowed,
+            and whether 2 or more matches is allowed.  */
+         if (many_times_ok)
+           {
+             /* If more than one repetition is allowed,
+                put in a backward jump at the end.  */
+             store_jump (b, maybe_finalize_jump, laststart - 3);
+             b += 3;
+           }
+         insert_jump (on_failure_jump, laststart, b + 3, b);
+         pending_exact = 0;
+         b += 3;
+         if (!zero_times_ok)
+           {
+             /* At least one repetition required: insert before the loop
+                a skip over the initial on-failure-jump instruction */
+             insert_jump (dummy_failure_jump, laststart, laststart + 6, b);
+             b += 3;
+           }
+         break;
+
+       case '.':
+         laststart = b;
+         PATPUSH (anychar);
+         break;
+
+       case '[':
+         while (b - bufp->buffer
+                > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH)
+           /* Note that EXTEND_BUFFER clobbers c */
+           EXTEND_BUFFER;
+
+         laststart = b;
+         if (*p == '^')
+           PATPUSH (charset_not), p++;
+         else
+           PATPUSH (charset);
+         p1 = p;
+
+         PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+         /* Clear the whole map */
+         bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+         /* Read in characters and ranges, setting map bits */
+         while (1)
+           {
+             PATFETCH (c);
+             if (c == ']' && p != p1 + 1) break;
+             if (*p == '-' && p[1] != ']')
+               {
+                 PATFETCH (c1);
+                 PATFETCH (c1);
+                 while (c <= c1)
+                   b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++;
+               }
+             else
+               {
+                 b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH);
+               }
+           }
+         /* Discard any bitmap bytes that are all 0 at the end of the map.
+            Decrement the map-length byte too. */
+         while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+           b[-1]--;
+         b += b[-1];
+         break;
+
+       case '(':
+         if (! (obscure_syntax & RE_NO_BK_PARENS))
+           goto normal_char;
+         else
+           goto handle_open;
+
+       case ')':
+         if (! (obscure_syntax & RE_NO_BK_PARENS))
+           goto normal_char;
+         else
+           goto handle_close;
+
+       case '\n':
+         if (! (obscure_syntax & RE_NEWLINE_OR))
+           goto normal_char;
+         else
+           goto handle_bar;
+
+       case '|':
+         if (! (obscure_syntax & RE_NO_BK_VBAR))
+           goto normal_char;
+         else
+           goto handle_bar;
+
+        case '\\':
+         if (p == pend) goto invalid_pattern;
+         PATFETCH_RAW (c);
+         switch (c)
+           {
+           case '(':
+             if (obscure_syntax & RE_NO_BK_PARENS)
+               goto normal_backsl;
+           handle_open:
+             if (stackp == stacke) goto nesting_too_deep;
+             if (regnum < RE_NREGS)
+               {
+                 PATPUSH (start_memory);
+                 PATPUSH (regnum);
+               }
+             *stackp++ = b - bufp->buffer;
+             *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0;
+             *stackp++ = regnum++;
+             *stackp++ = begalt - bufp->buffer;
+             fixup_jump = 0;
+             laststart = 0;
+             begalt = b;
+             break;
+
+           case ')':
+             if (obscure_syntax & RE_NO_BK_PARENS)
+               goto normal_backsl;
+           handle_close:
+             if (stackp == stackb) goto unmatched_close;
+             begalt = *--stackp + bufp->buffer;
+             if (fixup_jump)
+               store_jump (fixup_jump, jump, b);
+             if (stackp[-1] < RE_NREGS)
+               {
+                 PATPUSH (stop_memory);
+                 PATPUSH (stackp[-1]);
+               }
+             stackp -= 2;
+             fixup_jump = 0;
+             if (*stackp)
+               fixup_jump = *stackp + bufp->buffer - 1;
+             laststart = *--stackp + bufp->buffer;
+             break;
+
+           case '|':
+             if (obscure_syntax & RE_NO_BK_VBAR)
+               goto normal_backsl;
+           handle_bar:
+             insert_jump (on_failure_jump, begalt, b + 6, b);
+             pending_exact = 0;
+             b += 3;
+             if (fixup_jump)
+               store_jump (fixup_jump, jump, b);
+             fixup_jump = b;
+             b += 3;
+             laststart = 0;
+             begalt = b;
+             break;
+
+#ifdef emacs
+           case '=':
+             PATPUSH (at_dot);
+             break;
+
+           case 's':   
+             laststart = b;
+             PATPUSH (syntaxspec);
+             PATFETCH (c);
+             PATPUSH (syntax_spec_code[c]);
+             break;
+
+           case 'S':
+             laststart = b;
+             PATPUSH (notsyntaxspec);
+             PATFETCH (c);
+             PATPUSH (syntax_spec_code[c]);
+             break;
+#endif /* emacs */
+
+           case 'w':
+             laststart = b;
+             PATPUSH (wordchar);
+             break;
+
+           case 'W':
+             laststart = b;
+             PATPUSH (notwordchar);
+             break;
+
+           case '<':
+             PATPUSH (wordbeg);
+             break;
+
+           case '>':
+             PATPUSH (wordend);
+             break;
+
+           case 'b':
+             PATPUSH (wordbound);
+             break;
+
+           case 'B':
+             PATPUSH (notwordbound);
+             break;
+
+           case '`':
+             PATPUSH (begbuf);
+             break;
+
+           case '\'':
+             PATPUSH (endbuf);
+             break;
+
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+           case '8':
+           case '9':
+             c1 = c - '0';
+             if (c1 >= regnum)
+               goto normal_char;
+             for (stackt = stackp - 2;  stackt > stackb;  stackt -= 4)
+               if (*stackt == c1)
+                 goto normal_char;
+             laststart = b;
+             PATPUSH (duplicate);
+             PATPUSH (c1);
+             break;
+
+           case '+':
+           case '?':
+             if (obscure_syntax & RE_BK_PLUS_QM)
+               goto handle_plus;
+
+           default:
+           normal_backsl:
+             /* You might think it would be useful for \ to mean
+                not to translate; but if we don't translate it
+                it will never match anything.  */
+             if (translate) c = translate[c];
+             goto normal_char;
+           }
+         break;
+
+       default:
+       normal_char:
+         if (!pending_exact || pending_exact + *pending_exact + 1 != b
+             || *pending_exact == 0177 || *p == '*' || *p == '^'
+             || ((obscure_syntax & RE_BK_PLUS_QM)
+                 ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+                 : (*p == '+' || *p == '?')))
+           {
+             laststart = b;
+             PATPUSH (exactn);
+             pending_exact = b;
+             PATPUSH (0);
+           }
+         PATPUSH (c);
+         (*pending_exact)++;
+       }
+    }
+
+  if (fixup_jump)
+    store_jump (fixup_jump, jump, b);
+
+  if (stackp != stackb) goto unmatched_open;
+
+  bufp->used = b - bufp->buffer;
+  return 0;
+
+ invalid_pattern:
+  return "Invalid regular expression";
+
+ unmatched_open:
+  return "Unmatched \\(";
+
+ unmatched_close:
+  return "Unmatched \\)";
+
+ end_of_pattern:
+  return "Premature end of regular expression";
+
+ nesting_too_deep:
+  return "Nesting too deep";
+
+ too_big:
+  return "Regular expression too big";
+
+ memory_exhausted:
+  return "Memory exhausted";
+}
+
+/* Store where `from' points a jump operation to jump to where `to' points.
+  `opcode' is the opcode to store. */
+
+static int
+store_jump (from, opcode, to)
+     char *from, *to;
+     char opcode;
+{
+  from[0] = opcode;
+  from[1] = (to - (from + 3)) & 0377;
+  from[2] = (to - (from + 3)) >> 8;
+}
+
+/* Open up space at char FROM, and insert there a jump to TO.
+   CURRENT_END gives te end of the storage no in use,
+   so we know how much data to copy up.
+   OP is the opcode of the jump to insert.
+
+   If you call this function, you must zero out pending_exact.  */
+
+static int
+insert_jump (op, from, to, current_end)
+     char op;
+     char *from, *to, *current_end;
+{
+  register char *pto = current_end + 3;
+  register char *pfrom = current_end;
+  while (pfrom != from)
+    *--pto = *--pfrom;
+  store_jump (from, op, to);
+}
+\f
+/* Given a pattern, compute a fastmap from it.
+ The fastmap records which of the (1 << BYTEWIDTH) possible characters
+ can start a string that matches the pattern.
+ This fastmap is used by re_search to skip quickly over totally implausible text.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data area
+ as bufp->fastmap.
+ The other components of bufp describe the pattern to be used.  */
+
+void
+re_compile_fastmap (bufp)
+     struct re_pattern_buffer *bufp;
+{
+  unsigned char *pattern = (unsigned char *) bufp->buffer;
+  int size = bufp->used;
+  register char *fastmap = bufp->fastmap;
+  register unsigned char *p = pattern;
+  register unsigned char *pend = pattern + size;
+  register int j, k;
+  unsigned char *translate = (unsigned char *) bufp->translate;
+
+  unsigned char *stackb[NFAILURES];
+  unsigned char **stackp = stackb;
+
+  bzero (fastmap, (1 << BYTEWIDTH));
+  bufp->fastmap_accurate = 1;
+  bufp->can_be_null = 0;
+      
+  while (p)
+    {
+      if (p == pend)
+       {
+         bufp->can_be_null = 1;
+         break;
+       }
+#ifdef SWITCH_ENUM_BUG
+      switch ((int) ((enum regexpcode) *p++))
+#else
+      switch ((enum regexpcode) *p++)
+#endif
+       {
+       case exactn:
+         if (translate)
+           fastmap[translate[p[1]]] = 1;
+         else
+           fastmap[p[1]] = 1;
+         break;
+
+        case begline:
+        case before_dot:
+       case at_dot:
+       case after_dot:
+       case begbuf:
+       case endbuf:
+       case wordbound:
+       case notwordbound:
+       case wordbeg:
+       case wordend:
+         continue;
+
+       case endline:
+         if (translate)
+           fastmap[translate['\n']] = 1;
+         else
+           fastmap['\n'] = 1;
+         if (bufp->can_be_null != 1)
+           bufp->can_be_null = 2;
+         break;
+
+       case finalize_jump:
+       case maybe_finalize_jump:
+       case jump:
+       case dummy_failure_jump:
+         bufp->can_be_null = 1;
+         j = *p++ & 0377;
+         j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+         p += j + 1;           /* The 1 compensates for missing ++ above */
+         if (j > 0)
+           continue;
+         /* Jump backward reached implies we just went through
+            the body of a loop and matched nothing.
+            Opcode jumped to should be an on_failure_jump.
+            Just treat it like an ordinary jump.
+            For a * loop, it has pushed its failure point already;
+            if so, discard that as redundant.  */
+         if ((enum regexpcode) *p != on_failure_jump)
+           continue;
+         p++;
+         j = *p++ & 0377;
+         j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+         p += j + 1;           /* The 1 compensates for missing ++ above */
+         if (stackp != stackb && *stackp == p)
+           stackp--;
+         continue;
+         
+       case on_failure_jump:
+         j = *p++ & 0377;
+         j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+         p++;
+         *++stackp = p + j;
+         continue;
+
+       case start_memory:
+       case stop_memory:
+         p++;
+         continue;
+
+       case duplicate:
+         bufp->can_be_null = 1;
+         fastmap['\n'] = 1;
+       case anychar:
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (j != '\n')
+             fastmap[j] = 1;
+         if (bufp->can_be_null)
+           return;
+         /* Don't return; check the alternative paths
+            so we can set can_be_null if appropriate.  */
+         break;
+
+       case wordchar:
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) == Sword)
+             fastmap[j] = 1;
+         break;
+
+       case notwordchar:
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) != Sword)
+             fastmap[j] = 1;
+         break;
+
+#ifdef emacs
+       case syntaxspec:
+         k = *p++;
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) == (enum syntaxcode) k)
+             fastmap[j] = 1;
+         break;
+
+       case notsyntaxspec:
+         k = *p++;
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) != (enum syntaxcode) k)
+             fastmap[j] = 1;
+         break;
+#endif /* emacs */
+
+       case charset:
+         for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+           if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+             {
+               if (translate)
+                 fastmap[translate[j]] = 1;
+               else
+                 fastmap[j] = 1;
+             }
+         break;
+
+       case charset_not:
+         /* Chars beyond end of map must be allowed */
+         for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+           if (translate)
+             fastmap[translate[j]] = 1;
+           else
+             fastmap[j] = 1;
+
+         for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+           if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+             {
+               if (translate)
+                 fastmap[translate[j]] = 1;
+               else
+                 fastmap[j] = 1;
+             }
+         break;
+       }
+
+      /* Get here means we have successfully found the possible starting characters
+        of one path of the pattern.  We need not follow this path any farther.
+        Instead, look at the next alternative remembered in the stack. */
+      if (stackp != stackb)
+       p = *stackp--;
+      else
+       break;
+    }
+}
+\f
+/* Like re_search_2, below, but only one string is specified. */
+
+int
+re_search (pbufp, string, size, startpos, range, regs)
+     struct re_pattern_buffer *pbufp;
+     char *string;
+     int size, startpos, range;
+     struct re_registers *regs;
+{
+  return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size);
+}
+
+/* Like re_match_2 but tries first a match starting at index STARTPOS,
+   then at STARTPOS + 1, and so on.
+   RANGE is the number of places to try before giving up.
+   If RANGE is negative, the starting positions tried are
+    STARTPOS, STARTPOS - 1, etc.
+   It is up to the caller to make sure that range is not so large
+   as to take the starting position outside of the input strings.
+
+The value returned is the position at which the match was found,
+ or -1 if no match was found,
+ or -2 if error (such as failure stack overflow).  */
+
+int
+re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs, mstop)
+     struct re_pattern_buffer *pbufp;
+     char *string1, *string2;
+     int size1, size2;
+     int startpos;
+     register int range;
+     struct re_registers *regs;
+     int mstop;
+{
+  register char *fastmap = pbufp->fastmap;
+  register unsigned char *translate = (unsigned char *) pbufp->translate;
+  int total = size1 + size2;
+  int val;
+
+  /* Update the fastmap now if not correct already */
+  if (fastmap && !pbufp->fastmap_accurate)
+    re_compile_fastmap (pbufp);
+  
+  /* Don't waste time in a long search for a pattern
+     that says it is anchored.  */
+  if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf
+      && range > 0)
+    {
+      if (startpos > 0)
+       return -1;
+      else
+       range = 1;
+    }
+
+  while (1)
+    {
+      /* If a fastmap is supplied, skip quickly over characters
+        that cannot possibly be the start of a match.
+        Note, however, that if the pattern can possibly match
+        the null string, we must test it at each starting point
+        so that we take the first null string we get.  */
+
+      if (fastmap && startpos < total && pbufp->can_be_null != 1)
+       {
+         if (range > 0)
+           {
+             register int lim = 0;
+             register unsigned char *p;
+             int irange = range;
+             if (startpos < size1 && startpos + range >= size1)
+               lim = range - (size1 - startpos);
+
+             p = ((unsigned char *)
+                  &(startpos >= size1 ? string2 - size1 : string1)[startpos]);
+
+             if (translate)
+               {
+                 while (range > lim && !fastmap[translate[*p++]])
+                   range--;
+               }
+             else
+               {
+                 while (range > lim && !fastmap[*p++])
+                   range--;
+               }
+             startpos += irange - range;
+           }
+         else
+           {
+             register unsigned char c;
+             if (startpos >= size1)
+               c = string2[startpos - size1];
+             else
+               c = string1[startpos];
+             c &= 0xff;
+             if (translate ? !fastmap[translate[c]] : !fastmap[c])
+               goto advance;
+           }
+       }
+
+      if (range >= 0 && startpos == total
+         && fastmap && pbufp->can_be_null == 0)
+       return -1;
+
+      val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, regs, mstop);
+      if (0 <= val)
+       {
+         if (val == -2)
+           return -2;
+         return startpos;
+       }
+
+#ifdef C_ALLOCA
+      alloca (0);
+#endif /* C_ALLOCA */
+
+    advance:
+      if (!range) break;
+      if (range > 0) range--, startpos++; else range++, startpos--;
+    }
+  return -1;
+}
+\f
+#ifndef emacs   /* emacs never uses this */
+int
+re_match (pbufp, string, size, pos, regs)
+     struct re_pattern_buffer *pbufp;
+     char *string;
+     int size, pos;
+     struct re_registers *regs;
+{
+  return re_match_2 (pbufp, 0, 0, string, size, pos, regs, size);
+}
+#endif /* emacs */
+
+/* Maximum size of failure stack.  Beyond this, overflow is an error.  */
+
+int re_max_failures = 2000;
+
+static int bcmp_translate();
+/* Match the pattern described by PBUFP
+   against data which is the virtual concatenation of STRING1 and STRING2.
+   SIZE1 and SIZE2 are the sizes of the two data strings.
+   Start the match at position POS.
+   Do not consider matching past the position MSTOP.
+
+   If pbufp->fastmap is nonzero, then it had better be up to date.
+
+   The reason that the data to match are specified as two components
+   which are to be regarded as concatenated
+   is so this function can be used directly on the contents of an Emacs buffer.
+
+   -1 is returned if there is no match.  -2 is returned if there is
+   an error (such as match stack overflow).  Otherwise the value is the length
+   of the substring which was matched.  */
+
+int
+re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
+     struct re_pattern_buffer *pbufp;
+     unsigned char *string1, *string2;
+     int size1, size2;
+     int pos;
+     struct re_registers *regs;
+     int mstop;
+{
+  register unsigned char *p = (unsigned char *) pbufp->buffer;
+  register unsigned char *pend = p + pbufp->used;
+  /* End of first string */
+  unsigned char *end1;
+  /* End of second string */
+  unsigned char *end2;
+  /* Pointer just past last char to consider matching */
+  unsigned char *end_match_1, *end_match_2;
+  register unsigned char *d, *dend;
+  register int mcnt;
+  unsigned char *translate = (unsigned char *) pbufp->translate;
+
+ /* Failure point stack.  Each place that can handle a failure further down the line
+    pushes a failure point on this stack.  It consists of two char *'s.
+    The first one pushed is where to resume scanning the pattern;
+    the second pushed is where to resume scanning the strings.
+    If the latter is zero, the failure point is a "dummy".
+    If a failure happens and the innermost failure point is dormant,
+    it discards that failure point and tries the next one. */
+
+  unsigned char *initial_stack[2 * NFAILURES];
+  unsigned char **stackb = initial_stack;
+  unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES];
+
+  /* Information on the "contents" of registers.
+     These are pointers into the input strings; they record
+     just what was matched (on this attempt) by some part of the pattern.
+     The start_memory command stores the start of a register's contents
+     and the stop_memory command stores the end.
+
+     At that point, regstart[regnum] points to the first character in the register,
+     regend[regnum] points to the first character beyond the end of the register,
+     regstart_seg1[regnum] is true iff regstart[regnum] points into string1,
+     and regend_seg1[regnum] is true iff regend[regnum] points into string1.  */
+
+  unsigned char *regstart[RE_NREGS];
+  unsigned char *regend[RE_NREGS];
+  unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS];
+
+  /* Set up pointers to ends of strings.
+     Don't allow the second string to be empty unless both are empty.  */
+  if (!size2)
+    {
+      string2 = string1;
+      size2 = size1;
+      string1 = 0;
+      size1 = 0;
+    }
+  end1 = string1 + size1;
+  end2 = string2 + size2;
+
+  /* Compute where to stop matching, within the two strings */
+  if (mstop <= size1)
+    {
+      end_match_1 = string1 + mstop;
+      end_match_2 = string2;
+    }
+  else
+    {
+      end_match_1 = end1;
+      end_match_2 = string2 + mstop - size1;
+    }
+
+  /* Initialize \) text positions to -1
+     to mark ones that no \( or \) has been seen for.  */
+
+  for (mcnt = 0; mcnt < sizeof (regend) / sizeof (*regend); mcnt++)
+    regend[mcnt] = (unsigned char *) -1;
+
+  /* `p' scans through the pattern as `d' scans through the data.
+     `dend' is the end of the input string that `d' points within.
+     `d' is advanced into the following input string whenever necessary,
+     but this happens before fetching;
+     therefore, at the beginning of the loop,
+     `d' can be pointing at the end of a string,
+     but it cannot equal string2.  */
+
+  if (pos <= size1)
+    d = string1 + pos, dend = end_match_1;
+  else
+    d = string2 + pos - size1, dend = end_match_2;
+
+/* Write PREFETCH; just before fetching a character with *d.  */
+#define PREFETCH \
+ while (d == dend)                                                 \
+  { if (dend == end_match_2) goto fail;  /* end of string2 => failure */   \
+    d = string2;  /* end of string1 => advance to string2. */       \
+    dend = end_match_2; }
+
+  /* This loop loops over pattern commands.
+     It exits by returning from the function if match is complete,
+     or it drops through if match fails at this starting point in the input data. */
+
+  while (1)
+    {
+      if (p == pend)
+       /* End of pattern means we have succeeded! */
+       {
+         /* If caller wants register contents data back, convert it to indices */
+         if (regs)
+           {
+             regs->start[0] = pos;
+             if (dend == end_match_1)
+               regs->end[0] = d - string1;
+             else
+               regs->end[0] = d - string2 + size1;
+             for (mcnt = 1; mcnt < RE_NREGS; mcnt++)
+               {
+                 if (regend[mcnt] == (unsigned char *) -1)
+                   {
+                     regs->start[mcnt] = -1;
+                     regs->end[mcnt] = -1;
+                     continue;
+                   }
+                 if (regstart_seg1[mcnt])
+                   regs->start[mcnt] = regstart[mcnt] - string1;
+                 else
+                   regs->start[mcnt] = regstart[mcnt] - string2 + size1;
+                 if (regend_seg1[mcnt])
+                   regs->end[mcnt] = regend[mcnt] - string1;
+                 else
+                   regs->end[mcnt] = regend[mcnt] - string2 + size1;
+               }
+           }
+         if (dend == end_match_1)
+           return (d - string1 - pos);
+         else
+           return d - string2 + size1 - pos;
+       }
+
+      /* Otherwise match next pattern command */
+#ifdef SWITCH_ENUM_BUG
+      switch ((int) ((enum regexpcode) *p++))
+#else
+      switch ((enum regexpcode) *p++)
+#endif
+       {
+
+       /* \( is represented by a start_memory, \) by a stop_memory.
+           Both of those commands contain a "register number" argument.
+           The text matched within the \( and \) is recorded under that number.
+           Then, \<digit> turns into a `duplicate' command which
+           is followed by the numeric value of <digit> as the register number. */
+
+       case start_memory:
+         regstart[*p] = d;
+         regstart_seg1[*p++] = (dend == end_match_1);
+         break;
+
+       case stop_memory:
+         regend[*p] = d;
+         regend_seg1[*p++] = (dend == end_match_1);
+         break;
+
+       case duplicate:
+         {
+           int regno = *p++;   /* Get which register to match against */
+           register unsigned char *d2, *dend2;
+
+           d2 = regstart[regno];
+           dend2 = ((regstart_seg1[regno] == regend_seg1[regno])
+                    ? regend[regno] : end_match_1);
+           while (1)
+             {
+               /* Advance to next segment in register contents, if necessary */
+               while (d2 == dend2)
+                 {
+                   if (dend2 == end_match_2) break;
+                   if (dend2 == regend[regno]) break;
+                   d2 = string2, dend2 = regend[regno];  /* end of string1 => advance to string2. */
+                 }
+               /* At end of register contents => success */
+               if (d2 == dend2) break;
+
+               /* Advance to next segment in data being matched, if necessary */
+               PREFETCH;
+
+               /* mcnt gets # consecutive chars to compare */
+               mcnt = dend - d;
+               if (mcnt > dend2 - d2)
+                 mcnt = dend2 - d2;
+               /* Compare that many; failure if mismatch, else skip them. */
+               if (translate ? bcmp_translate (d, d2, mcnt, translate) : bcmp (d, d2, mcnt))
+                 goto fail;
+               d += mcnt, d2 += mcnt;
+             }
+         }
+         break;
+
+       case anychar:
+         /* fetch a data character */
+         PREFETCH;
+         /* Match anything but a newline.  */
+         if ((translate ? translate[*d++] : *d++) == '\n')
+           goto fail;
+         break;
+
+       case charset:
+       case charset_not:
+         {
+           /* Nonzero for charset_not */
+           int not = 0;
+           register int c;
+           if (*(p - 1) == (unsigned char) charset_not)
+             not = 1;
+
+           /* fetch a data character */
+           PREFETCH;
+
+           if (translate)
+             c = translate [*d];
+           else
+             c = *d;
+
+           if (c < *p * BYTEWIDTH
+               && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+             not = !not;
+
+           p += 1 + *p;
+
+           if (!not) goto fail;
+           d++;
+           break;
+         }
+
+       case begline:
+         if (d == string1 || d[-1] == '\n')
+           break;
+         goto fail;
+
+       case endline:
+         if (d == end2
+             || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n'))
+           break;
+         goto fail;
+
+       /* "or" constructs ("|") are handled by starting each alternative
+           with an on_failure_jump that points to the start of the next alternative.
+           Each alternative except the last ends with a jump to the joining point.
+           (Actually, each jump except for the last one really jumps
+            to the following jump, because tensioning the jumps is a hassle.) */
+
+       /* The start of a stupid repeat has an on_failure_jump that points
+          past the end of the repeat text.
+          This makes a failure point so that, on failure to match a repetition,
+          matching restarts past as many repetitions have been found
+          with no way to fail and look for another one.  */
+
+       /* A smart repeat is similar but loops back to the on_failure_jump
+          so that each repetition makes another failure point. */
+
+       case on_failure_jump:
+         if (stackp == stacke)
+           {
+             unsigned char **stackx;
+             if (stacke - stackb > re_max_failures * 2)
+               return -2;
+             stackx = (unsigned char **) alloca (2 * (stacke - stackb)
+                                        * sizeof (char *));
+             bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+             stackp = stackx + (stackp - stackb);
+             stacke = stackx + 2 * (stacke - stackb);
+             stackb = stackx;
+           }
+         mcnt = *p++ & 0377;
+         mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+         p++;
+         *stackp++ = mcnt + p;
+         *stackp++ = d;
+         break;
+
+       /* The end of a smart repeat has an maybe_finalize_jump back.
+          Change it either to a finalize_jump or an ordinary jump. */
+
+       case maybe_finalize_jump:
+         mcnt = *p++ & 0377;
+         mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+         p++;
+         {
+           register unsigned char *p2 = p;
+           /* Compare what follows with the begining of the repeat.
+              If we can establish that there is nothing that they would
+              both match, we can change to finalize_jump */
+           while (p2 != pend
+                  && (*p2 == (unsigned char) stop_memory
+                      || *p2 == (unsigned char) start_memory))
+             p2++;
+           if (p2 == pend)
+             p[-3] = (unsigned char) finalize_jump;
+           else if (*p2 == (unsigned char) exactn
+                    || *p2 == (unsigned char) endline)
+             {
+               register int c = *p2 == (unsigned char) endline ? '\n' : p2[2];
+               register unsigned char *p1 = p + mcnt;
+               /* p1[0] ... p1[2] are an on_failure_jump.
+                  Examine what follows that */
+               if (p1[3] == (unsigned char) exactn && p1[5] != c)
+                 p[-3] = (unsigned char) finalize_jump;
+               else if (p1[3] == (unsigned char) charset
+                        || p1[3] == (unsigned char) charset_not)
+                 {
+                   int not = p1[3] == (unsigned char) charset_not;
+                   if (c < p1[4] * BYTEWIDTH
+                       && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+                     not = !not;
+                   /* not is 1 if c would match */
+                   /* That means it is not safe to finalize */
+                   if (!not)
+                     p[-3] = (unsigned char) finalize_jump;
+                 }
+             }
+         }
+         p -= 2;
+         if (p[-1] != (unsigned char) finalize_jump)
+           {
+             p[-1] = (unsigned char) jump;
+             goto nofinalize;
+           }
+
+       /* The end of a stupid repeat has a finalize-jump
+          back to the start, where another failure point will be made
+          which will point after all the repetitions found so far. */
+
+       case finalize_jump:
+         stackp -= 2;
+
+       case jump:
+       nofinalize:
+         mcnt = *p++ & 0377;
+         mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+         p += mcnt + 1;        /* The 1 compensates for missing ++ above */
+         break;
+
+       case dummy_failure_jump:
+         if (stackp == stacke)
+           {
+             unsigned char **stackx
+               = (unsigned char **) alloca (2 * (stacke - stackb)
+                                            * sizeof (char *));
+             bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+             stackp = stackx + (stackp - stackb);
+             stacke = stackx + 2 * (stacke - stackb);
+             stackb = stackx;
+           }
+         *stackp++ = 0;
+         *stackp++ = 0;
+         goto nofinalize;
+
+       case wordbound:
+         if (d == string1  /* Points to first char */
+             || d == end2  /* Points to end */
+             || (d == end1 && size2 == 0)) /* Points to end */
+           break;
+         if ((SYNTAX (d[-1]) == Sword)
+             != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+           break;
+         goto fail;
+
+       case notwordbound:
+         if (d == string1  /* Points to first char */
+             || d == end2  /* Points to end */
+             || (d == end1 && size2 == 0)) /* Points to end */
+           goto fail;
+         if ((SYNTAX (d[-1]) == Sword)
+             != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+           goto fail;
+         break;
+
+       case wordbeg:
+         if (d == end2  /* Points to end */
+             || (d == end1 && size2 == 0) /* Points to end */
+             || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */
+           goto fail;
+         if (d == string1  /* Points to first char */
+             || SYNTAX (d[-1]) != Sword)  /* prev char not letter */
+           break;
+         goto fail;
+
+       case wordend:
+         if (d == string1  /* Points to first char */
+             || SYNTAX (d[-1]) != Sword)  /* prev char not letter */
+           goto fail;
+         if (d == end2  /* Points to end */
+             || (d == end1 && size2 == 0) /* Points to end */
+             || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */
+           break;
+         goto fail;
+
+#ifdef emacs
+       case before_dot:
+         if (((d - string2 <= (unsigned) size2)
+              ? d - bf_p2 : d - bf_p1)
+             <= point)
+           goto fail;
+         break;
+
+       case at_dot:
+         if (((d - string2 <= (unsigned) size2)
+              ? d - bf_p2 : d - bf_p1)
+             == point)
+           goto fail;
+         break;
+
+       case after_dot:
+         if (((d - string2 <= (unsigned) size2)
+              ? d - bf_p2 : d - bf_p1)
+             >= point)
+           goto fail;
+         break;
+
+       case wordchar:
+         mcnt = (int) Sword;
+         goto matchsyntax;
+
+       case syntaxspec:
+         mcnt = *p++;
+       matchsyntax:
+         PREFETCH;
+         if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail;
+         break;
+         
+       case notwordchar:
+         mcnt = (int) Sword;
+         goto matchnotsyntax;
+
+       case notsyntaxspec:
+         mcnt = *p++;
+       matchnotsyntax:
+         PREFETCH;
+         if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail;
+         break;
+#else
+       case wordchar:
+         PREFETCH;
+         if (SYNTAX (*d++) == 0) goto fail;
+         break;
+         
+       case notwordchar:
+         PREFETCH;
+         if (SYNTAX (*d++) != 0) goto fail;
+         break;
+#endif /* not emacs */
+
+       case begbuf:
+         if (d == string1)     /* Note, d cannot equal string2 */
+           break;              /* unless string1 == string2.  */
+         goto fail;
+
+       case endbuf:
+         if (d == end2 || (d == end1 && size2 == 0))
+           break;
+         goto fail;
+
+       case exactn:
+         /* Match the next few pattern characters exactly.
+            mcnt is how many characters to match. */
+         mcnt = *p++;
+         if (translate)
+           {
+             do
+               {
+                 PREFETCH;
+                 if (translate[*d++] != *p++) goto fail;
+               }
+             while (--mcnt);
+           }
+         else
+           {
+             do
+               {
+                 PREFETCH;
+                 if (*d++ != *p++) goto fail;
+               }
+             while (--mcnt);
+           }
+         break;
+       }
+      continue;    /* Successfully matched one pattern command; keep matching */
+
+      /* Jump here if any matching operation fails. */
+    fail:
+      if (stackp != stackb)
+       /* A restart point is known.  Restart there and pop it. */
+       {
+         if (!stackp[-2])
+           {   /* If innermost failure point is dormant, flush it and keep looking */
+             stackp -= 2;
+             goto fail;
+           }
+         d = *--stackp;
+         p = *--stackp;
+         if (d >= string1 && d <= end1)
+           dend = end_match_1;
+       }
+      else break;   /* Matching at this starting point really fails! */
+    }
+  return -1;         /* Failure to match */
+}
+
+static int
+bcmp_translate (s1, s2, len, translate)
+     unsigned char *s1, *s2;
+     register int len;
+     unsigned char *translate;
+{
+  register unsigned char *p1 = s1, *p2 = s2;
+  while (len)
+    {
+      if (translate [*p1++] != translate [*p2++]) return 1;
+      len--;
+    }
+  return 0;
+}
+\f
+/* Entry points compatible with bsd4.2 regex library */
+
+#ifndef emacs
+
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+     char *s;
+{
+  if (!s)
+    {
+      if (!re_comp_buf.buffer)
+       return "No previous regular expression";
+      return 0;
+    }
+
+  if (!re_comp_buf.buffer)
+    {
+      if (!(re_comp_buf.buffer = (char *) malloc (200)))
+       return "Memory exhausted";
+      re_comp_buf.allocated = 200;
+      if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH)))
+       return "Memory exhausted";
+    }
+  return re_compile_pattern (s, strlen (s), &re_comp_buf);
+}
+
+int
+re_exec (s)
+     char *s;
+{
+  int len = strlen (s);
+  return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0);
+}
+
+#endif /* emacs */
+\f
+#ifdef test
+
+#include <stdio.h>
+
+/* Indexed by a character, gives the upper case equivalent of the character */
+
+static char upcase[0400] = 
+  { 000, 001, 002, 003, 004, 005, 006, 007,
+    010, 011, 012, 013, 014, 015, 016, 017,
+    020, 021, 022, 023, 024, 025, 026, 027,
+    030, 031, 032, 033, 034, 035, 036, 037,
+    040, 041, 042, 043, 044, 045, 046, 047,
+    050, 051, 052, 053, 054, 055, 056, 057,
+    060, 061, 062, 063, 064, 065, 066, 067,
+    070, 071, 072, 073, 074, 075, 076, 077,
+    0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+    0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+    0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+    0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+    0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+    0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+    0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+    0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+    0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+    0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+    0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+    0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+    0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+    0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+    0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+    0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+    0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+    0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+    0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+    0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+    0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+    0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+    0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+    0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+  };
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char pat[80];
+  struct re_pattern_buffer buf;
+  int i;
+  char c;
+  char fastmap[(1 << BYTEWIDTH)];
+
+  /* Allow a command argument to specify the style of syntax.  */
+  if (argc > 1)
+    obscure_syntax = atoi (argv[1]);
+
+  buf.allocated = 40;
+  buf.buffer = (char *) malloc (buf.allocated);
+  buf.fastmap = fastmap;
+  buf.translate = upcase;
+
+  while (1)
+    {
+      gets (pat);
+
+      if (*pat)
+       {
+          re_compile_pattern (pat, strlen(pat), &buf);
+
+         for (i = 0; i < buf.used; i++)
+           printchar (buf.buffer[i]);
+
+         putchar ('\n');
+
+         printf ("%d allocated, %d used.\n", buf.allocated, buf.used);
+
+         re_compile_fastmap (&buf);
+         printf ("Allowed by fastmap: ");
+         for (i = 0; i < (1 << BYTEWIDTH); i++)
+           if (fastmap[i]) printchar (i);
+         putchar ('\n');
+       }
+
+      gets (pat);      /* Now read the string to match against */
+
+      i = re_match (&buf, pat, strlen (pat), 0, 0);
+      printf ("Match value %d.\n", i);
+    }
+}
+
+#ifdef NOTDEF
+print_buf (bufp)
+     struct re_pattern_buffer *bufp;
+{
+  int i;
+
+  printf ("buf is :\n----------------\n");
+  for (i = 0; i < bufp->used; i++)
+    printchar (bufp->buffer[i]);
+  
+  printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used);
+  
+  printf ("Allowed by fastmap: ");
+  for (i = 0; i < (1 << BYTEWIDTH); i++)
+    if (bufp->fastmap[i])
+      printchar (i);
+  printf ("\nAllowed by translate: ");
+  if (bufp->translate)
+    for (i = 0; i < (1 << BYTEWIDTH); i++)
+      if (bufp->translate[i])
+       printchar (i);
+  printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't");
+  printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not");
+}
+#endif
+
+printchar (c)
+     char c;
+{
+  if (c < 041 || c >= 0177)
+    {
+      putchar ('\\');
+      putchar (((c >> 6) & 3) + '0');
+      putchar (((c >> 3) & 7) + '0');
+      putchar ((c & 7) + '0');
+    }
+  else
+    putchar (c);
+}
+
+error (string)
+     char *string;
+{
+  puts (string);
+  exit (1);
+}
+
+#endif /* test */
diff --git a/gdb/regex.h b/gdb/regex.h
new file mode 100644 (file)
index 0000000..d0d8a82
--- /dev/null
@@ -0,0 +1,185 @@
+/* Definitions for data structures callers pass the regex library.
+   Copyright (C) 1985, 1989 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  */
+
+
+/* Define number of parens for which we record the beginnings and ends.
+   This affects how much space the `struct re_registers' type takes up.  */
+#ifndef RE_NREGS
+#define RE_NREGS 10
+#endif
+
+/* These bits are used in the obscure_syntax variable to choose among
+   alternative regexp syntaxes.  */
+
+/* 1 means plain parentheses serve as grouping, and backslash
+     parentheses are needed for literal searching.
+   0 means backslash-parentheses are grouping, and plain parentheses
+     are for literal searching.  */
+#define RE_NO_BK_PARENS 1
+
+/* 1 means plain | serves as the "or"-operator, and \| is a literal.
+   0 means \| serves as the "or"-operator, and | is a literal.  */
+#define RE_NO_BK_VBAR 2
+
+/* 0 means plain + or ? serves as an operator, and \+, \? are literals.
+   1 means \+, \? are operators and plain +, ? are literals.  */
+#define RE_BK_PLUS_QM 4
+
+/* 1 means | binds tighter than ^ or $.
+   0 means the contrary.  */
+#define RE_TIGHT_VBAR 8
+
+/* 1 means treat \n as an _OR operator
+   0 means treat it as a normal character */
+#define RE_NEWLINE_OR 16
+
+/* 0 means that a special characters (such as *, ^, and $) always have
+     their special meaning regardless of the surrounding context.
+   1 means that special characters may act as normal characters in some
+     contexts.  Specifically, this applies to:
+       ^ - only special at the beginning, or after ( or |
+       $ - only special at the end, or before ) or |
+       *, +, ? - only special when not after the beginning, (, or | */
+#define RE_CONTEXT_INDEP_OPS 32
+
+/* Now define combinations of bits for the standard possibilities.  */
+#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS)
+#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR)
+#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
+#define RE_SYNTAX_EMACS 0
+
+/* This data structure is used to represent a compiled pattern. */
+
+struct re_pattern_buffer
+  {
+    char *buffer;      /* Space holding the compiled pattern commands. */
+    int allocated;     /* Size of space that  buffer  points to */
+    int used;          /* Length of portion of buffer actually occupied */
+    char *fastmap;     /* Pointer to fastmap, if any, or zero if none. */
+                       /* re_search uses the fastmap, if there is one,
+                          to skip quickly over totally implausible characters */
+    char *translate;   /* Translate table to apply to all characters before comparing.
+                          Or zero for no translation.
+                          The translation is applied to a pattern when it is compiled
+                          and to data when it is matched. */
+    char fastmap_accurate;
+                       /* Set to zero when a new pattern is stored,
+                          set to one when the fastmap is updated from it. */
+    char can_be_null;   /* Set to one by compiling fastmap
+                          if this pattern might match the null string.
+                          It does not necessarily match the null string
+                          in that case, but if this is zero, it cannot.
+                          2 as value means can match null string
+                          but at end of range or before a character
+                          listed in the fastmap.  */
+  };
+
+/* Structure to store "register" contents data in.
+
+   Pass the address of such a structure as an argument to re_match, etc.,
+   if you want this information back.
+
+   start[i] and end[i] record the string matched by \( ... \) grouping i,
+   for i from 1 to RE_NREGS - 1.
+   start[0] and end[0] record the entire string matched. */
+
+struct re_registers
+  {
+    int start[RE_NREGS];
+    int end[RE_NREGS];
+  };
+
+/* These are the command codes that appear in compiled regular expressions, one per byte.
+  Some command codes are followed by argument bytes.
+  A command code can specify any interpretation whatever for its arguments.
+  Zero-bytes may appear in the compiled regular expression. */
+
+enum regexpcode
+  {
+    unused,
+    exactn,    /* followed by one byte giving n, and then by n literal bytes */
+    begline,   /* fails unless at beginning of line */
+    endline,   /* fails unless at end of line */
+    jump,       /* followed by two bytes giving relative address to jump to */
+    on_failure_jump,    /* followed by two bytes giving relative address of place
+                           to resume at in case of failure. */
+    finalize_jump,      /* Throw away latest failure point and then jump to address. */
+    maybe_finalize_jump, /* Like jump but finalize if safe to do so.
+                           This is used to jump back to the beginning
+                           of a repeat.  If the command that follows
+                           this jump is clearly incompatible with the
+                           one at the beginning of the repeat, such that
+                           we can be sure that there is no use backtracking
+                           out of repetitions already completed,
+                           then we finalize. */
+    dummy_failure_jump,  /* jump, and push a dummy failure point.
+                           This failure point will be thrown away
+                           if an attempt is made to use it for a failure.
+                           A + construct makes this before the first repeat.  */
+    anychar,    /* matches any one character */
+    charset,     /* matches any one char belonging to specified set.
+                   First following byte is # bitmap bytes.
+                   Then come bytes for a bit-map saying which chars are in.
+                   Bits in each byte are ordered low-bit-first.
+                   A character is in the set if its bit is 1.
+                   A character too large to have a bit in the map
+                   is automatically not in the set */
+    charset_not, /* similar but match any character that is NOT one of those specified */
+    start_memory, /* starts remembering the text that is matched
+                   and stores it in a memory register.
+                   followed by one byte containing the register number.
+                   Register numbers must be in the range 0 through NREGS. */
+    stop_memory, /* stops remembering the text that is matched
+                   and stores it in a memory register.
+                   followed by one byte containing the register number.
+                   Register numbers must be in the range 0 through NREGS. */
+    duplicate,    /* match a duplicate of something remembered.
+                   Followed by one byte containing the index of the memory register. */
+    before_dot,         /* Succeeds if before dot */
+    at_dot,     /* Succeeds if at dot */
+    after_dot,  /* Succeeds if after dot */
+    begbuf,      /* Succeeds if at beginning of buffer */
+    endbuf,      /* Succeeds if at end of buffer */
+    wordchar,    /* Matches any word-constituent character */
+    notwordchar, /* Matches any char that is not a word-constituent */
+    wordbeg,    /* Succeeds if at word beginning */
+    wordend,    /* Succeeds if at word end */
+    wordbound,   /* Succeeds if at a word boundary */
+    notwordbound, /* Succeeds if not at a word boundary */
+    syntaxspec,  /* Matches any character whose syntax is specified.
+                   followed by a byte which contains a syntax code, Sword or such like */
+    notsyntaxspec /* Matches any character whose syntax differs from the specified. */
+  };
+\f
+extern char *re_compile_pattern ();
+/* Is this really advertised? */
+extern void re_compile_fastmap ();
+extern int re_search (), re_search_2 ();
+extern int re_match (), re_match_2 ();
+
+/* 4.2 bsd compatibility (yuck) */
+extern char *re_comp ();
+extern int re_exec ();
+
+#ifdef SYNTAX_TABLE
+extern char *re_syntax_table;
+#endif
diff --git a/gdb/remote-eb.c b/gdb/remote-eb.c
new file mode 100644 (file)
index 0000000..a140905
--- /dev/null
@@ -0,0 +1,932 @@
+/* Remote debugging interface for AMD 29000 EBMON on IBM PC, for GDB.
+   Copyright 1990-1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.  Written by Jim Kingdon for Cygnus.
+
+This file is part of GDB.
+
+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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is like remote.c but is for an esoteric situation--
+   having a 29k board in a PC hooked up to a unix machine with
+   a serial line, and running ctty com1 on the PC, through which
+   the unix machine can run ebmon.  Not to mention that the PC
+   has PC/NFS, so it can access the same executables that gdb can,
+   over the net in real time.  */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "tm-29k.h"
+#include "param-no-tm.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+
+extern void add_syms_addr_command ();
+extern struct value *call_function_by_hand();
+
+extern struct target_ops eb_ops;               /* Forward declaration */
+
+#define LOG_FILE "eb.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 5;
+
+/* Descriptor for I/O to remote machine.  Initialize it to -1 so that
+   eb_open knows that we don't have a file open when the program
+   starts.  */
+int eb_desc = -1;
+
+/* stream which is fdopen'd from eb_desc.  Only valid when
+   eb_desc != -1.  */
+FILE *eb_stream;
+
+/* Read a character from the remote system, doing all the fancy
+   timeout stuff.  */
+static int
+readchar ()
+{
+  char buf;
+
+  buf = '\0';
+#ifdef HAVE_TERMIO
+  /* termio does the timeout for us.  */
+  read (eb_desc, &buf, 1);
+#else
+  alarm (timeout);
+  if (read (eb_desc, &buf, 1) < 0)
+    {
+      if (errno == EINTR)
+       error ("Timeout reading from remote system.");
+      else
+       perror_with_name ("remote");
+    }
+  alarm (0);
+#endif
+
+  if (buf == '\0')
+    error ("Timeout reading from remote system.");
+#if defined (LOG_FILE)
+  putc (buf & 0x7f, log_file);
+#endif
+  return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found. 
+   Let the user break out immediately.  */
+static void
+expect (string)
+     char *string;
+{
+  char *p = string;
+
+  immediate_quit = 1;
+  while (1)
+    {
+      if (readchar() == *p)
+       {
+         p++;
+         if (*p == '\0')
+           {
+             immediate_quit = 0;
+             return;
+           }
+       }
+      else
+       p = string;
+    }
+}
+
+/* Keep discarding input until we see the ebmon prompt.
+
+   The convention for dealing with the prompt is that you
+   o give your command
+   o *then* wait for the prompt.
+
+   Thus the last thing that a procedure does with the serial line
+   will be an expect_prompt().  Exception:  eb_resume does not
+   wait for the prompt, because the terminal is being handed over
+   to the inferior.  However, the next thing which happens after that
+   is a eb_wait which does wait for the prompt.
+   Note that this includes abnormal exit, e.g. error().  This is
+   necessary to prevent getting into states from which we can't
+   recover.  */
+static void
+expect_prompt ()
+{
+#if defined (LOG_FILE)
+  /* This is a convenient place to do this.  The idea is to do it often
+     enough that we never lose much data if we terminate abnormally.  */
+  fflush (log_file);
+#endif
+  expect ("\n# ");
+}
+
+/* Get a hex digit from the remote system & return its value.
+   If ignore_space is nonzero, ignore spaces (not newline, tab, etc).  */
+static int
+get_hex_digit (ignore_space)
+     int ignore_space;
+{
+  int ch;
+  while (1)
+    {
+      ch = readchar ();
+      if (ch >= '0' && ch <= '9')
+       return ch - '0';
+      else if (ch >= 'A' && ch <= 'F')
+       return ch - 'A' + 10;
+      else if (ch >= 'a' && ch <= 'f')
+       return ch - 'a' + 10;
+      else if (ch == ' ' && ignore_space)
+       ;
+      else
+       {
+         expect_prompt ();
+         error ("Invalid hex digit from remote system.");
+       }
+    }
+}
+
+/* Get a byte from eb_desc and put it in *BYT.  Accept any number
+   leading spaces.  */
+static void
+get_hex_byte (byt)
+     char *byt;
+{
+  int val;
+
+  val = get_hex_digit (1) << 4;
+  val |= get_hex_digit (0);
+  *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+   and put them in registers starting at REGNO.  */
+static void
+get_hex_regs (n, regno)
+     int n;
+     int regno;
+{
+  long val;
+  int i;
+
+  for (i = 0; i < n; i++)
+    {
+      int j;
+      
+      val = 0;
+      for (j = 0; j < 8; j++)
+       val = (val << 4) + get_hex_digit (j == 0);
+      supply_register (regno++, &val);
+    }
+}
+
+/* Called when SIGALRM signal sent due to alarm() timeout.  */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+#define volatile /**/
+#endif
+volatile int n_alarms;
+
+void
+eb_timer ()
+{
+#if 0
+  if (kiodebug)
+    printf ("eb_timer called\n");
+#endif
+  n_alarms++;
+}
+#endif
+
+/* malloc'd name of the program on the remote system.  */
+static char *prog_name = NULL;
+
+/* Nonzero if we have loaded the file ("yc") and not yet issued a "gi"
+   command.  "gi" is supposed to happen exactly once for each "yc".  */
+static int need_gi = 0;
+
+/* Number of SIGTRAPs we need to simulate.  That is, the next
+   NEED_ARTIFICIAL_TRAP calls to eb_wait should just return
+   SIGTRAP without actually waiting for anything.  */
+
+static int need_artificial_trap = 0;
+
+/* This is called not only when we first attach, but also when the
+   user types "run" after having attached.  */
+void
+eb_start (inferior_args)
+char *inferior_args;
+{
+  /* OK, now read in the file.  Y=read, C=COFF, D=no symbols
+     0=start address, %s=filename.  */
+
+  fprintf (eb_stream, "YC D,0:%s", prog_name);
+
+  if (inferior_args != NULL)
+      fprintf(eb_stream, " %s", inferior_args);
+
+  fprintf (eb_stream, "\n");
+  fflush (eb_stream);
+
+  expect_prompt ();
+
+  need_gi = 1;
+}
+
+/* Translate baud rates from integers to damn B_codes.  Unix should
+   have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+struct {int rate, damn_b;} baudtab[] = {
+       {0, B0},
+       {50, B50},
+       {75, B75},
+       {110, B110},
+       {134, B134},
+       {150, B150},
+       {200, B200},
+       {300, B300},
+       {600, B600},
+       {1200, B1200},
+       {1800, B1800},
+       {2400, B2400},
+       {4800, B4800},
+       {9600, B9600},
+       {19200, B19200},
+       {38400, B38400},
+       {-1, -1},
+};
+
+int damn_b (rate)
+     int rate;
+{
+  int i;
+
+  for (i = 0; baudtab[i].rate != -1; i++)
+    if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+  return B38400;       /* Random */
+}
+
+
+/* Open a connection to a remote debugger.
+   NAME is the filename used for communication, then a space,
+   then the name of the program as we should name it to EBMON.  */
+
+static int baudrate = 9600;
+static char *dev_name;
+void
+eb_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  TERMINAL sg;
+
+  char *p;
+
+  /* Find the first whitespace character, it separates dev_name from
+     prog_name.  */
+  if (name == 0)
+    goto erroid;
+
+  for (p = name;
+       *p != '\0' && !isspace (*p); p++)
+    ;
+  if (*p == '\0')
+erroid:
+    error ("\
+Please include the name of the device for the serial port,\n\
+the baud rate, and the name of the program to run on the remote system.");
+  dev_name = alloca (p - name + 1);
+  strncpy (dev_name, name, p - name);
+  dev_name[p - name] = '\0';
+
+  /* Skip over the whitespace after dev_name */
+  for (; isspace (*p); p++)
+    /*EMPTY*/;
+  
+  if (1 != sscanf (p, "%d ", &baudrate))
+    goto erroid;
+
+  /* Skip the number and then the spaces */
+  for (; isdigit (*p); p++)
+    /*EMPTY*/;
+  for (; isspace (*p); p++)
+    /*EMPTY*/;
+  
+  if (prog_name != NULL)
+    free (prog_name);
+  prog_name = savestring (p, strlen (p));
+
+  eb_close (0);
+
+  eb_desc = open (dev_name, O_RDWR);
+  if (eb_desc < 0)
+    perror_with_name (dev_name);
+  ioctl (eb_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+  sg.c_cc[VMIN] = 0;           /* read with timeout.  */
+  sg.c_cc[VTIME] = timeout * 10;
+  sg.c_lflag &= ~(ICANON | ECHO);
+  sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+  sg.sg_ispeed = damn_b (baudrate);
+  sg.sg_ospeed = damn_b (baudrate);
+  sg.sg_flags |= RAW | ANYP;
+  sg.sg_flags &= ~ECHO;
+#endif
+
+  ioctl (eb_desc, TIOCSETP, &sg);
+  eb_stream = fdopen (eb_desc, "r+");
+
+  push_target (&eb_ops);
+  if (from_tty)
+    printf ("Remote %s debugging %s using %s\n", target_shortname,
+           prog_name, dev_name);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+  /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+     the read.  */
+  if (siginterrupt (SIGALRM, 1) != 0)
+    perror ("eb_open: error in siginterrupt");
+#endif
+
+  /* Set up read timeout timer.  */
+  if ((void (*)) signal (SIGALRM, eb_timer) == (void (*)) -1)
+    perror ("eb_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+  log_file = fopen (LOG_FILE, "w");
+  if (log_file == NULL)
+    perror_with_name (LOG_FILE);
+#endif
+
+  /* Hello?  Are you there?  */
+  write (eb_desc, "\n", 1);
+  
+  expect_prompt ();
+}
+
+/* Close out all files and local state before this target loses control. */
+
+void
+eb_close (quitting)
+     int quitting;
+{
+
+  /* Due to a bug in Unix, fclose closes not only the stdio stream,
+     but also the file descriptor.  So we don't actually close
+     eb_desc.  */
+  if (eb_stream)
+    fclose (eb_stream);        /* This also closes eb_desc */
+  if (eb_desc >= 0)
+    /* close (eb_desc); */
+
+  /* Do not try to close eb_desc again, later in the program.  */
+  eb_stream = NULL;
+  eb_desc = -1;
+
+#if defined (LOG_FILE)
+  if (ferror (log_file))
+    printf ("Error writing log file.\n");
+  if (fclose (log_file) != 0)
+    printf ("Error closing log file.\n");
+#endif
+}
+
+/* Terminate the open connection to the remote debugger.
+   Use this when you want to detach and do something else
+   with your gdb.  */
+void
+eb_detach (from_tty)
+     int from_tty;
+{
+  pop_target();                /* calls eb_close to do the real work */
+  if (from_tty)
+    printf ("Ending remote %s debugging\n", target_shortname);
+}
+/* Tell the remote machine to resume.  */
+
+void
+eb_resume (step, sig)
+     int step, sig;
+{
+  if (step)
+    {
+      write (eb_desc, "t 1,s\n", 6);
+      /* Wait for the echo.  */
+      expect ("t 1,s\r");
+      /* Then comes a line containing the instruction we stepped to.  */
+      expect ("\n@");
+      /* Then we get the prompt.  */
+      expect_prompt ();
+
+      /* Force the next eb_wait to return a trap.  Not doing anything
+         about I/O from the target means that the user has to type
+         "continue" to see any.  This should be fixed.  */
+      need_artificial_trap = 1;
+    }
+  else
+    {
+      if (need_gi)
+       {
+         need_gi = 0;
+         write (eb_desc, "gi\n", 3);
+         
+         /* Swallow the echo of "gi".  */
+         expect ("gi\r");
+       }
+      else
+       {
+         write (eb_desc, "GR\n", 3);
+         /* Swallow the echo.  */
+         expect ("GR\r");
+       }
+    }
+}
+
+/* Wait until the remote machine stops, then return,
+   storing status in STATUS just as `wait' would.  */
+
+int
+eb_wait (status)
+     WAITTYPE *status;
+{
+  /* Strings to look for.  '?' means match any single character.  
+     Note that with the algorithm we use, the initial character
+     of the string cannot recur in the string, or we will not
+     find some cases of the string in the input.  */
+  
+  static char bpt[] = "Invalid interrupt taken - #0x50 - ";
+  /* It would be tempting to look for "\n[__exit + 0x8]\n"
+     but that requires loading symbols with "yc i" and even if
+     we did do that we don't know that the file has symbols.  */
+  static char exitmsg[] = "\n@????????I    JMPTI     GR121,LR0";
+  char *bp = bpt;
+  char *ep = exitmsg;
+
+  /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars.  */
+  char swallowed[50];
+  /* Current position in swallowed.  */
+  char *swallowed_p = swallowed;
+
+  int ch;
+  int ch_handled;
+
+  int old_timeout = timeout;
+
+  WSETEXIT ((*status), 0);
+
+  if (need_artificial_trap != 0)
+    {
+      WSETSTOP ((*status), SIGTRAP);
+      need_artificial_trap--;
+      return 0;
+    }
+
+  timeout = 0;         /* Don't time out -- user program is running. */
+  while (1)
+    {
+      ch_handled = 0;
+      ch = readchar ();
+      if (ch == *bp)
+       {
+         bp++;
+         if (*bp == '\0')
+           break;
+         ch_handled = 1;
+
+         *swallowed_p++ = ch;
+       }
+      else
+       bp = bpt;
+
+      if (ch == *ep || *ep == '?')
+       {
+         ep++;
+         if (*ep == '\0')
+           break;
+
+         if (!ch_handled)
+           *swallowed_p++ = ch;
+         ch_handled = 1;
+       }
+      else
+       ep = exitmsg;
+
+      if (!ch_handled)
+       {
+         char *p;
+
+         /* Print out any characters which have been swallowed.  */
+         for (p = swallowed; p < swallowed_p; ++p)
+           putc (*p, stdout);
+         swallowed_p = swallowed;
+         
+         putc (ch, stdout);
+       }
+    }
+  expect_prompt ();
+  if (*bp== '\0')
+    WSETSTOP ((*status), SIGTRAP);
+  else
+    WSETEXIT ((*status), 0);
+  timeout = old_timeout;
+
+  return 0;
+}
+
+/* Return the name of register number REGNO
+   in the form input and output by EBMON.
+
+   Returns a pointer to a static buffer containing the answer.  */
+static char *
+get_reg_name (regno)
+     int regno;
+{
+  static char buf[80];
+  if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+    sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
+  else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+    sprintf (buf, "LR%03d", regno - LR0_REGNUM);
+  else if (regno == Q_REGNUM)
+    strcpy (buf, "SR131");
+  else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
+    sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
+  else if (regno == ALU_REGNUM)
+    strcpy (buf, "SR132");
+  else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
+    sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
+  else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM)
+    sprintf (buf, "SR%03d", regno - VAB_REGNUM);
+  else if (regno == GR1_REGNUM)
+    strcpy (buf, "GR001");
+  return buf;
+}
+
+/* Read the remote registers into the block REGS.  */
+
+static void
+eb_fetch_registers ()
+{
+  int reg_index;
+  int regnum_index;
+  char tempbuf[10];
+  int i;
+
+#if 0
+  /* This should not be necessary, because one is supposed to read the
+     registers only when the inferior is stopped (at least with
+     ptrace() and why not make it the same for remote?).  */
+  /* ^A is the "normal character" used to make sure we are talking to EBMON
+     and not to the program being debugged.  */
+  write (eb_desc, "\001\n");
+  expect_prompt ();
+#endif
+
+  write (eb_desc, "dw gr96,gr127\n", 14);
+  for (reg_index = 96, regnum_index = GR96_REGNUM;
+       reg_index < 128;
+       reg_index += 4, regnum_index += 4)
+    {
+      sprintf (tempbuf, "GR%03d ", reg_index);
+      expect (tempbuf);
+      get_hex_regs (4, regnum_index);
+      expect ("\n");
+    }
+
+  for (i = 0; i < 128; i += 32)
+    {
+      /* The PC has a tendency to hang if we get these
+        all in one fell swoop ("dw lr0,lr127").  */
+      sprintf (tempbuf, "dw lr%d\n", i);
+      write (eb_desc, tempbuf, strlen (tempbuf));
+      for (reg_index = i, regnum_index = LR0_REGNUM + i;
+          reg_index < i + 32;
+          reg_index += 4, regnum_index += 4)
+       {
+         sprintf (tempbuf, "LR%03d ", reg_index);
+         expect (tempbuf);
+         get_hex_regs (4, regnum_index);
+         expect ("\n");
+       }
+    }
+
+  write (eb_desc, "dw sr133,sr133\n", 15);
+  expect ("SR133          ");
+  get_hex_regs (1, BP_REGNUM);
+  expect ("\n");
+
+  write (eb_desc, "dw sr134,sr134\n", 15);
+  expect ("SR134                   ");
+  get_hex_regs (1, FC_REGNUM);
+  expect ("\n");
+
+  write (eb_desc, "dw sr135,sr135\n", 15);
+  expect ("SR135                            ");
+  get_hex_regs (1, CR_REGNUM);
+  expect ("\n");
+
+  write (eb_desc, "dw sr131,sr131\n", 15);
+  expect ("SR131                            ");
+  get_hex_regs (1, Q_REGNUM);
+  expect ("\n");
+
+  write (eb_desc, "dw sr0,sr14\n", 12);
+  for (reg_index = 0, regnum_index = VAB_REGNUM;
+       regnum_index <= LRU_REGNUM;
+       regnum_index += 4, reg_index += 4)
+    {
+      sprintf (tempbuf, "SR%03d ", reg_index);
+      expect (tempbuf);
+      get_hex_regs (reg_index == 12 ? 3 : 4, regnum_index);
+      expect ("\n");
+    }
+
+  /* There doesn't seem to be any way to get these.  */
+  {
+    int val = -1;
+    supply_register (FPE_REGNUM, &val);
+    supply_register (INT_REGNUM, &val);
+    supply_register (FPS_REGNUM, &val);
+    supply_register (EXO_REGNUM, &val);
+  }
+
+  write (eb_desc, "dw gr1,gr1\n", 11);
+  expect ("GR001 ");
+  get_hex_regs (1, GR1_REGNUM);
+  expect_prompt ();
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+   Returns errno value.  */
+int
+eb_fetch_register (regno)
+     int regno;
+{
+  if (regno == -1)
+    eb_fetch_registers ();
+  else
+    {
+      char *name = get_reg_name (regno);
+      fprintf (eb_stream, "dw %s,%s\n", name, name);
+      expect (name);
+      expect (" ");
+      get_hex_regs (1, regno);
+      expect_prompt ();
+    }
+  return 0;
+}
+
+/* Store the remote registers from the contents of the block REGS.  */
+
+static void
+eb_store_registers ()
+{
+  int i, j;
+  fprintf (eb_stream, "s gr1,%x\n", read_register (GR1_REGNUM));
+  expect_prompt ();
+
+  for (j = 0; j < 32; j += 16)
+    {
+      fprintf (eb_stream, "s gr%d,", j + 96);
+      for (i = 0; i < 15; ++i)
+       fprintf (eb_stream, "%x,", read_register (GR96_REGNUM + j + i));
+      fprintf (eb_stream, "%x\n", read_register (GR96_REGNUM + j + 15));
+      expect_prompt ();
+    }
+
+  for (j = 0; j < 128; j += 16)
+    {
+      fprintf (eb_stream, "s lr%d,", j);
+      for (i = 0; i < 15; ++i)
+       fprintf (eb_stream, "%x,", read_register (LR0_REGNUM + j + i));
+      fprintf (eb_stream, "%x\n", read_register (LR0_REGNUM + j + 15));
+      expect_prompt ();
+    }
+
+  fprintf (eb_stream, "s sr133,%x,%x,%x\n", read_register (BP_REGNUM),
+          read_register (FC_REGNUM), read_register (CR_REGNUM));
+  expect_prompt ();
+  fprintf (eb_stream, "s sr131,%x\n", read_register (Q_REGNUM));
+  expect_prompt ();
+  fprintf (eb_stream, "s sr0,");
+  for (i = 0; i < 11; ++i)
+    fprintf (eb_stream, "%x,", read_register (VAB_REGNUM + i));
+  fprintf (eb_stream, "%x\n", read_register (VAB_REGNUM + 11));
+  expect_prompt ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+   Return errno value.  */
+int
+eb_store_register (regno)
+     int regno;
+{
+  if (regno == -1)
+    eb_store_registers ();
+  else
+    {
+      char *name = get_reg_name (regno);
+      fprintf (eb_stream, "s %s,%x\n", name, read_register (regno));
+      /* Setting GR1 changes the numbers of all the locals, so
+        invalidate the register cache.  Do this *after* calling
+        read_register, because we want read_register to return the
+        value that write_register has just stuffed into the registers
+        array, not the value of the register fetched from the
+        inferior.  */
+      if (regno == GR1_REGNUM)
+       registers_changed ();
+      expect_prompt ();
+    }
+  return 0;
+}
+
+/* Get ready to modify the registers array.  On machines which store
+   individual registers, this doesn't need to do anything.  On machines
+   which store all the registers in one fell swoop, this makes sure
+   that registers contains all the registers from the program being
+   debugged.  */
+
+void
+eb_prepare_to_store ()
+{
+  /* Do nothing, since we can store individual regs */
+}
+
+/* FIXME!  Merge these two.  */
+int
+eb_xfer_inferior_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  if (write)
+    return eb_write_inferior_memory (memaddr, myaddr, len);
+  else
+    return eb_write_inferior_memory (memaddr, myaddr, len);
+}
+
+void
+eb_files_info ()
+{
+  printf ("\tAttached to %s at %d baud and running program %s.\n",
+         dev_name, baudrate, prog_name);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+   to inferior's memory at MEMADDR.  Returns errno value.  */
+int
+eb_write_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int i;
+
+  for (i = 0; i < len; i++)
+    {
+      if ((i % 16) == 0)
+       fprintf (eb_stream, "sb %x,", memaddr + i);
+      if ((i % 16) == 15 || i == len - 1)
+       {
+         fprintf (eb_stream, "%x\n", ((unsigned char *)myaddr)[i]);
+         expect_prompt ();
+       }
+      else
+       fprintf (eb_stream, "%x,", ((unsigned char *)myaddr)[i]);
+    }
+  return 0;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR.  Put the result
+   at debugger address MYADDR.  Returns errno value.  */
+int
+eb_read_inferior_memory(memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int i;
+
+  /* Number of bytes read so far.  */
+  int count;
+
+  /* Starting address of this pass.  */
+  unsigned long startaddr;
+
+  /* Number of bytes to read in this pass.  */
+  int len_this_pass;
+
+  /* Note that this code works correctly if startaddr is just less
+     than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+     thing).  That is, something like
+     eb_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+     works--it never adds len to memaddr and gets 0.  */
+  /* However, something like
+     eb_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+     doesn't need to work.  Detect it and give up if there's an attempt
+     to do that.  */
+  if (((memaddr - 1) + len) < memaddr)
+    return EIO;
+  
+  startaddr = memaddr;
+  count = 0;
+  while (count < len)
+    {
+      len_this_pass = 16;
+      if ((startaddr % 16) != 0)
+       len_this_pass -= startaddr % 16;
+      if (len_this_pass > (len - count))
+       len_this_pass = (len - count);
+
+      fprintf (eb_stream, "db %x,%x\n", startaddr,
+              (startaddr - 1) + len_this_pass);
+      expect ("\n");
+
+      /* Look for 8 hex digits.  */
+      i = 0;
+      while (1)
+       {
+         if (isxdigit (readchar ()))
+           ++i;
+         else
+           {
+             expect_prompt ();
+             error ("Hex digit expected from remote system.");
+           }
+         if (i >= 8)
+           break;
+       }
+
+      expect ("  ");
+
+      for (i = 0; i < len_this_pass; i++)
+       get_hex_byte (&myaddr[count++]);
+
+      expect_prompt ();
+
+      startaddr += len_this_pass;
+    }
+  return 0;
+}
+
+/* Define the target subroutine names */
+
+struct target_ops eb_ops = {
+       "amd-eb", "Remote serial AMD EBMON target",
+       eb_open, eb_close, 
+       0, eb_detach, eb_resume, eb_wait,
+       eb_fetch_register, eb_store_register,
+       eb_prepare_to_store, 0, 0,      /* conv_to, conv_from */
+       eb_xfer_inferior_memory, eb_files_info,
+       0, 0,   /* Breakpoints */
+       0, 0, 0, 0, 0,  /* Terminal handling */
+       0,      /* FIXME, kill */
+       0, add_syms_addr_command,       /* load */
+       call_function_by_hand,
+       0, /* lookup_symbol */
+       0, /* create_inferior FIXME, eb_start here or something? */
+       0, /* mourn_inferior FIXME */
+       process_stratum, 0, /* next */
+       1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_remote_eb ()
+{
+  add_target (&eb_ops);
+}
diff --git a/gdb/remote-multi.shar b/gdb/remote-multi.shar
new file mode 100755 (executable)
index 0000000..86c9cf0
--- /dev/null
@@ -0,0 +1,1313 @@
+#!/bin/sh
+#      This is a shell archive.
+#      Run the file through sh to extract its contents.
+# shar:        Shell Archiver
+#      Run the following text with /bin/sh to create:
+#      Remote_Makefile
+#      remote_gutils.c
+#      remote_inflow.c
+#      remote_server.c
+#      remote_utils.c
+# This archive created: Fri Jun 23 17:06:55 1989
+cat << \SHAR_EOF > Remote_Makefile
+#    Makefile for the remote server for GDB, the GNU debugger.
+#    Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+# 
+# This file is part of GDB.
+# 
+# GDB 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 1, or (at your option)
+# any later version.
+# 
+# GDB 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 GDB; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+CFLAGS = -g 
+CC = cc
+
+SERVER = remote_server.o\
+                remote_inflow.o\
+                remote_utils.o\
+                remote_gutils.o 
+
+prog : $(SERVER)
+       $(CC) -g -o serve $(SERVER) 
+SHAR_EOF
+cat << \SHAR_EOF > remote_gutils.c
+/* General utility routines for the remote server for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include "defs.h"
+
+void error ();
+void fatal ();
+
+/* Chain of cleanup actions established with make_cleanup,
+   to be executed if an error happens.  */
+
+static struct cleanup *cleanup_chain;
+
+/* Nonzero means a quit has been requested.  */
+
+int quit_flag;
+
+/* Nonzero means quit immediately if Control-C is typed now,
+   rather than waiting until QUIT is executed.  */
+
+int immediate_quit;
+\f
+/* Add a new cleanup to the cleanup_chain,
+   and return the previous chain pointer
+   to be passed later to do_cleanups or discard_cleanups.
+   Args are FUNCTION to clean up with, and ARG to pass to it.  */
+
+struct cleanup *
+make_cleanup (function, arg)
+     void (*function) ();
+     int arg;
+{
+  register struct cleanup *new
+    = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+  register struct cleanup *old_chain = cleanup_chain;
+
+  new->next = cleanup_chain;
+  new->function = function;
+  new->arg = arg;
+  cleanup_chain = new;
+
+  return old_chain;
+}
+
+/* Discard cleanups and do the actions they describe
+   until we get back to the point OLD_CHAIN in the cleanup_chain.  */
+
+void
+do_cleanups (old_chain)
+     register struct cleanup *old_chain;
+{
+  register struct cleanup *ptr;
+  while ((ptr = cleanup_chain) != old_chain)
+    {
+      (*ptr->function) (ptr->arg);
+      cleanup_chain = ptr->next;
+      free (ptr);
+    }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+   until we get back to the point OLD_CHAIN in the cleanup_chain.  */
+
+void
+discard_cleanups (old_chain)
+     register struct cleanup *old_chain;
+{
+  register struct cleanup *ptr;
+  while ((ptr = cleanup_chain) != old_chain)
+    {
+      cleanup_chain = ptr->next;
+      free (ptr);
+    }
+}
+
+/* This function is useful for cleanups.
+   Do
+
+     foo = xmalloc (...);
+     old_chain = make_cleanup (free_current_contents, &foo);
+
+   to arrange to free the object thus allocated.  */
+
+void
+free_current_contents (location)
+     char **location;
+{
+  free (*location);
+}
+\f
+/* Generally useful subroutines used throughout the program.  */
+
+/* Like malloc but get error if no storage available.  */
+
+char *
+xmalloc (size)
+     long size;
+{
+  register char *val = (char *) malloc (size);
+  if (!val)
+    fatal ("virtual memory exhausted.", 0);
+  return val;
+}
+
+/* Like realloc but get error if no storage available.  */
+
+char *
+xrealloc (ptr, size)
+     char *ptr;
+     long size;
+{
+  register char *val = (char *) realloc (ptr, size);
+  if (!val)
+    fatal ("virtual memory exhausted.", 0);
+  return val;
+}
+
+/* Print the system error message for errno, and also mention STRING
+   as the file name for which the error was encountered.
+   Then return to command level.  */
+
+void
+perror_with_name (string)
+     char *string;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  extern int errno;
+  char *err;
+  char *combined;
+
+  if (errno < sys_nerr)
+    err = sys_errlist[errno];
+  else
+    err = "unknown error";
+
+  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+  strcpy (combined, string);
+  strcat (combined, ": ");
+  strcat (combined, err);
+
+  error ("%s.", combined);
+}
+
+/* Print the system error message for ERRCODE, and also mention STRING
+   as the file name for which the error was encountered.  */
+
+void
+print_sys_errmsg (string, errcode)
+     char *string;
+     int errcode;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  char *err;
+  char *combined;
+
+  if (errcode < sys_nerr)
+    err = sys_errlist[errcode];
+  else
+    err = "unknown error";
+
+  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+  strcpy (combined, string);
+  strcat (combined, ": ");
+  strcat (combined, err);
+
+  printf ("%s.\n", combined);
+}
+
+void
+quit ()
+{
+  fflush (stdout);
+  ioctl (fileno (stdout), TIOCFLUSH, 0);
+  error ("Quit");
+}
+
+/* Control C comes here */
+
+void
+request_quit ()
+{
+  quit_flag = 1;
+  if (immediate_quit)
+    quit ();
+}
+
+/* Print an error message and return to command level.
+   STRING is the error message, used as a fprintf string,
+   and ARG is passed as an argument to it.  */
+
+void
+error (string, arg1, arg2, arg3)
+     char *string;
+     int arg1, arg2, arg3;
+{
+  fflush (stdout);
+  fprintf (stderr, string, arg1, arg2, arg3);
+  fprintf (stderr, "\n");
+  /************return_to_top_level ();************/ 
+}
+
+/* Print an error message and exit reporting failure.
+   This is for a error that we cannot continue from.
+   STRING and ARG are passed to fprintf.  */
+
+void
+fatal (string, arg)
+     char *string;
+     int arg;
+{
+  fprintf (stderr, "gdb: ");
+  fprintf (stderr, string, arg);
+  fprintf (stderr, "\n");
+  exit (1);
+}
+
+/* Make a copy of the string at PTR with SIZE characters
+   (and add a null character at the end in the copy).
+   Uses malloc to get the space.  Returns the address of the copy.  */
+
+char *
+savestring (ptr, size)
+     char *ptr;
+     int size;
+{
+  register char *p = (char *) xmalloc (size + 1);
+  bcopy (ptr, p, size);
+  p[size] = 0;
+  return p;
+}
+
+char *
+concat (s1, s2, s3)
+     char *s1, *s2, *s3;
+{
+  register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+  register char *val = (char *) xmalloc (len);
+  strcpy (val, s1);
+  strcat (val, s2);
+  strcat (val, s3);
+  return val;
+}
+
+void
+print_spaces (n, file)
+     register int n;
+     register FILE *file;
+{
+  while (n-- > 0)
+    fputc (' ', file);
+}
+
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+   Takes three args which are given to printf to print the question.
+   The first, a control string, should end in "? ".
+   It should not say how to answer, because we do that.  */
+
+int
+query (ctlstr, arg1, arg2)
+     char *ctlstr;
+{
+  register int answer;
+
+  /* Automatically answer "yes" if input is not from a terminal.  */
+  /***********if (!input_from_terminal_p ())
+    return 1; *************************/ 
+
+  while (1)
+    {
+      printf (ctlstr, arg1, arg2);
+      printf ("(y or n) ");
+      fflush (stdout);
+      answer = fgetc (stdin);
+      clearerr (stdin);                /* in case of C-d */
+      if (answer != '\n')
+       while (fgetc (stdin) != '\n') clearerr (stdin);
+      if (answer >= 'a')
+       answer -= 040;
+      if (answer == 'Y')
+       return 1;
+      if (answer == 'N')
+       return 0;
+      printf ("Please answer y or n.\n");
+    }
+}
+\f
+/* Parse a C escape sequence.  STRING_PTR points to a variable
+   containing a pointer to the string to parse.  That pointer
+   is updated past the characters we use.  The value of the
+   escape sequence is returned.
+
+   A negative value means the sequence \ newline was seen,
+   which is supposed to be equivalent to nothing at all.
+
+   If \ is followed by a null character, we return a negative
+   value and leave the string pointer pointing at the null character.
+
+   If \ is followed by 000, we return 0 and leave the string pointer
+   after the zeros.  A value of 0 does not mean end of string.  */
+
+int
+parse_escape (string_ptr)
+     char **string_ptr;
+{
+  register int c = *(*string_ptr)++;
+  switch (c)
+    {
+    case 'a':
+      return '\a';
+    case 'b':
+      return '\b';
+    case 'e':
+      return 033;
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    case 'v':
+      return '\v';
+    case '\n':
+      return -2;
+    case 0:
+      (*string_ptr)--;
+      return 0;
+    case '^':
+      c = *(*string_ptr)++;
+      if (c == '\\')
+       c = parse_escape (string_ptr);
+      if (c == '?')
+       return 0177;
+      return (c & 0200) | (c & 037);
+      
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+      {
+       register int i = c - '0';
+       register int count = 0;
+       while (++count < 3)
+         {
+           if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+             {
+               i *= 8;
+               i += c - '0';
+             }
+           else
+             {
+               (*string_ptr)--;
+               break;
+             }
+         }
+       return i;
+      }
+    default:
+      return c;
+    }
+}
+\f
+void
+printchar (ch, stream)
+     unsigned char ch;
+     FILE *stream;
+{
+  register int c = ch;
+  if (c < 040 || c >= 0177)
+    {
+      if (c == '\n')
+       fprintf (stream, "\\n");
+      else if (c == '\b')
+       fprintf (stream, "\\b");
+      else if (c == '\t')
+       fprintf (stream, "\\t");
+      else if (c == '\f')
+       fprintf (stream, "\\f");
+      else if (c == '\r')
+       fprintf (stream, "\\r");
+      else if (c == 033)
+       fprintf (stream, "\\e");
+      else if (c == '\a')
+       fprintf (stream, "\\a");
+      else
+       fprintf (stream, "\\%03o", c);
+    }
+  else
+    {
+      if (c == '\\' || c == '"' || c == '\'')
+       fputc ('\\', stream);
+      fputc (c, stream);
+    }
+}
+SHAR_EOF
+cat << \SHAR_EOF > remote_inflow.c
+/* Low level interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+*/
+
+#include "defs.h"
+#include "param.h"
+#include "wait.h"
+#include "frame.h"
+#include "inferior.h"
+/***************************
+#include "initialize.h"
+****************************/ 
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/ 
+int quit_flag = 0; 
+char registers[REGISTER_BYTES]; 
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/ 
+
+#ifdef NEW_SUN_PTRACE
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#endif
+
+extern char **environ; 
+extern int errno;
+extern int inferior_pid; 
+void error(), quit(), perror_with_name();
+int query(); 
+void supply_register(), write_register(); 
+CORE_ADDR read_register(); 
+
+/* Nonzero if we are debugging an attached outside process
+   rather than an inferior.  */
+
+
+/* Start an inferior process and returns its pid.
+   ALLARGS is a vector of program-name and args.
+   ENV is the environment vector to pass.  */
+
+int
+create_inferior (allargs, env)
+     char **allargs;
+     char **env;
+{
+  int pid;
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  extern int errno;
+
+  /* exec is said to fail if the executable is open.  */
+  /****************close_exec_file ();*****************/ 
+
+  pid = vfork ();
+  if (pid < 0)
+    perror_with_name ("vfork");
+
+  if (pid == 0)
+    {
+      /* Run inferior in a separate process group.  */
+      setpgrp (getpid (), getpid ());
+
+/* Not needed on Sun, at least, and loses there
+   because it clobbers the superior.  */
+/*???      signal (SIGQUIT, SIG_DFL);
+      signal (SIGINT, SIG_DFL);  */
+
+         errno = 0; 
+      ptrace (0);
+
+      execle ("/bin/sh", "sh", "-c", allargs, 0, env);
+
+      fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
+              errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+      fflush (stderr);
+      _exit (0177);
+    }
+  return pid;
+}
+
+/* Kill the inferior process.  Make us have no inferior.  */
+
+kill_inferior ()
+{
+  if (inferior_pid == 0)
+    return;
+  ptrace (8, inferior_pid, 0, 0);
+  wait (0);
+  /*************inferior_died ();****VK**************/ 
+}
+
+/* Resume execution of the inferior process.
+   If STEP is nonzero, single-step it.
+   If SIGNAL is nonzero, give it that signal.  */
+
+unsigned char
+resume (step, signal,status)
+     int step;
+     int signal;
+        char *status; 
+{
+       int pid ; 
+       WAITTYPE w; 
+
+       errno = 0;
+    ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+    if (errno)
+               perror_with_name ("ptrace");
+       pid = wait(&w); 
+       if(pid != inferior_pid) 
+               perror_with_name ("wait"); 
+
+       if(WIFEXITED(w))
+       {
+               printf("\nchild exited with retcode = %x \n",WRETCODE(w)); 
+               *status = 'E'; 
+               return((unsigned char) WRETCODE(w));
+       } 
+       else if(!WIFSTOPPED(w))
+       {
+               printf("\nchild did terminated with signal = %x \n",WTERMSIG(w)); 
+               *status = 'T'; 
+               return((unsigned char) WTERMSIG(w)); 
+       } 
+       else 
+       {
+               printf("\nchild stopped with signal = %x \n",WSTOPSIG(w)); 
+               *status = 'S'; 
+               return((unsigned char) WSTOPSIG(w)); 
+       } 
+                
+}
+
+
+#ifdef NEW_SUN_PTRACE
+
+void
+fetch_inferior_registers ()
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+
+      ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+         /**********debugging begin **********/ 
+         print_some_registers(&inferior_registers); 
+         /**********debugging end **********/ 
+      ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+
+      bcopy (&inferior_registers, registers, 16 * 4);
+      bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+            sizeof inferior_fp_registers.fps_regs);
+      *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+      *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+      bcopy (&inferior_fp_registers.fps_control,
+            &registers[REGISTER_BYTE (FPC_REGNUM)],
+            sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+
+      bcopy (registers, &inferior_registers, 16 * 4);
+      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+            sizeof inferior_fp_registers.fps_regs);
+      inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+      inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+      bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+            &inferior_fp_registers.fps_control,
+            sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+      ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+      ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+      if (errno)
+               perror_with_name ("ptrace");
+}
+
+#endif /* not NEW_SUN_PTRACE */
+
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+   in the NEW_SUN_PTRACE case.
+   It ought to be straightforward.  But it appears that writing did
+   not write the data that I specified.  I cannot understand where
+   it got the data that it actually did write.  */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.  */
+
+read_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+
+  /* Read all the longwords */
+  for (i = 0; i < count; i++, addr += sizeof (int))
+    {
+       buffer[i] = ptrace (1, inferior_pid, addr, 0);
+    }
+
+  /* Copy appropriate bytes out of the buffer.  */
+  bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+   to inferior's memory at MEMADDR.
+   On failure (cannot write the inferior)
+   returns the value of errno.  */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+  extern int errno;
+
+  /* Fill start and end extra bytes of buffer with existing memory data.  */
+
+    buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+  if (count > 1)
+    {
+       buffer[count - 1]
+         = ptrace (1, inferior_pid,
+                   addr + (count - 1) * sizeof (int), 0);
+    }
+
+  /* Copy data to be written over corresponding part of buffer */
+
+  bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+  /* Write the entire buffer.  */
+
+  for (i = 0; i < count; i++, addr += sizeof (int))
+    {
+      errno = 0;
+       ptrace (4, inferior_pid, addr, buffer[i]);
+      if (errno)
+       return errno;
+    }
+
+  return 0;
+}
+\f
+void
+try_writing_regs_command ()
+{
+  register int i;
+  register int value;
+  extern int errno;
+
+  if (inferior_pid == 0)
+    error ("There is no inferior process now.");
+
+  fetch_inferior_registers(); 
+  for (i = 0;i<18 ; i ++)
+    {
+      QUIT;
+      errno = 0;
+      value = read_register(i); 
+      write_register ( i, value);
+      if (errno == 0)
+       {
+               printf (" Succeeded with register %d; value 0x%x (%d).\n",
+                 i, value, value);
+       }
+      else 
+               printf (" Failed with register %d.\n", i);
+    }
+}
+
+void
+initialize ()
+{
+
+  inferior_pid = 0;
+
+
+}
+
+
+/* Return the contents of register REGNO,
+   regarding it as an integer.  */
+
+CORE_ADDR
+read_register (regno)
+     int regno;
+{
+  /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  return *(int *) &registers[REGISTER_BYTE (regno)];
+}
+
+/* Store VALUE in the register number REGNO, regarded as an integer.  */
+
+void
+write_register (regno, val)
+     int regno, val;
+{
+  /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+  *(int *) &registers[REGISTER_BYTE (regno)] = val;
+
+  if (have_inferior_p ())
+    store_inferior_registers (regno);
+}
+
+
+int
+have_inferior_p ()
+{
+  return inferior_pid != 0;
+}
+
+print_some_registers(regs)
+int regs[];
+{
+   register int i;
+   for (i = 0; i < 18; i++) {
+        printf("reg[%d] = %x\n", i, regs[i]);
+        }
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_server.c
+/* Main code for remote server for GDB, the GNU Debugger.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "param.h"
+#include <stdio.h>
+
+void read_inferior_memory(), fetch_inferior_registers(); 
+unsigned char resume(); 
+void kill_inferior(); 
+void initialize(), try_writing_regs_command();  
+int create_inferior(), read_register(); 
+
+extern char registers[]; 
+int inferior_pid; 
+extern char **environ; 
+
+/* Descriptor for I/O to remote machine.  */
+int remote_desc;
+int kiodebug = 0;
+int remote_debugging; 
+
+void remote_send ();
+void putpkt ();
+void getpkt ();
+void remote_open(); 
+void write_ok(); 
+void write_enn(); 
+void convert_ascii_to_int(); 
+void convert_int_to_ascii(); 
+void prepare_resume_reply(); 
+void decode_m_packet(); 
+void decode_M_packet(); 
+
+
+main(argc,argv)
+int argc; char *argv[]; 
+{
+    char ch,status, own_buf[2000], mem_buf[2000]; 
+       int i=0;  
+       unsigned char signal;  
+       unsigned int mem_addr, len; 
+
+       initialize(); 
+    printf("\nwill open serial link\n"); 
+    remote_open("/dev/ttya",0); 
+
+       if(argc < 2) 
+       { 
+               printf("Enter name of program to be run with command line args\n"); 
+               gets(own_buf); 
+               inferior_pid = create_inferior(own_buf,environ); 
+               printf("\nProcess %s created; pid = %d\n",own_buf,inferior_pid);
+       } 
+       else 
+       { 
+               inferior_pid = create_inferior(argv[1],environ); 
+               printf("\nProcess %s created; pid = %d\n",argv[1],inferior_pid);
+       } 
+
+    do {  
+        getpkt(own_buf); 
+        printf("\nPacket received is>:%s\n",own_buf); 
+               i = 0; 
+               ch = own_buf[i++]; 
+           switch (ch) { 
+                       case 'h':       /**********This is only for tweaking the gdb+ program *******/ 
+                                               signal = resume(1,0,&status);
+                                               prepare_resume_reply(own_buf,status,signal); 
+                                               break; 
+                                               /*************end tweak*************************************/ 
+
+                       case 'g':       fetch_inferior_registers();             
+                                               convert_int_to_ascii(registers,own_buf,REGISTER_BYTES); 
+                                               break; 
+                       case 'G':       convert_ascii_to_int(&own_buf[1],registers,REGISTER_BYTES);
+                                               if(store_inferior_registers(-1)==0)  
+                                                       write_ok(own_buf); 
+                                               else  
+                                                       write_enn(own_buf); 
+                                               break; 
+                       case 'm':       decode_m_packet(&own_buf[1],&mem_addr,&len); 
+                                               read_inferior_memory(mem_addr,mem_buf,len);
+                                               convert_int_to_ascii(mem_buf,own_buf,len); 
+                                               break; 
+                       case 'M':       decode_M_packet(&own_buf[1],&mem_addr,&len,mem_buf); 
+                                               if(write_inferior_memory(mem_addr,mem_buf,len)==0)  
+                                                       write_ok(own_buf); 
+                                               else 
+                                                       write_enn(own_buf); 
+                                               break; 
+                       case 'c':       signal = resume(0,0,&status);
+                                               printf("\nSignal received is >: %0x \n",signal); 
+                                               prepare_resume_reply(own_buf,status,signal); 
+                                               break; 
+                       case 's':       signal = resume(1,0,&status);
+                                               prepare_resume_reply(own_buf,status,signal); 
+                                               break; 
+                       case 'k':       kill_inferior();
+                                               sprintf(own_buf,"q"); 
+                                       putpkt(own_buf); 
+                                               printf("\nObtained kill request...terminating\n"); 
+                                       close(remote_desc); 
+                                               exit(0); 
+                       case 't':       try_writing_regs_command();
+                                               own_buf[0] = '\0'; 
+                                               break; 
+                       default :       printf("\nUnknown option chosen by master\n"); 
+                                               write_enn(own_buf); 
+                                               break; 
+                 } 
+
+        putpkt(own_buf); 
+     }  while(1) ; 
+
+    close(remote_desc); 
+    /** now get out of here**/ 
+    printf("\nFinished reading data from serial link - Bye!\n"); 
+    exit(0);
+
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_utils.c
+/* Remote utility routines for the remote server for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "param.h"
+#include <stdio.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <a.out.h>
+#include <sys/file.h>
+#include <sgtty.h> 
+
+extern int remote_desc; 
+extern int remote_debugging; 
+extern int kiodebug; 
+
+void remote_open(); 
+void remote_send(); 
+void putpkt(); 
+void getpkt(); 
+
+void write_ok(); 
+void write_enn(); 
+void convert_ascii_to_int(); 
+void convert_int_to_ascii(); 
+void prepare_resume_reply(); 
+
+/* Open a connection to a remote debugger.
+   NAME is the filename used for communication.  */
+
+void
+remote_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  struct sgttyb sg;
+
+  remote_debugging = 0;
+
+  remote_desc = open (name, O_RDWR);
+  if (remote_desc < 0)
+    printf("\ncould not open remote device\n"); 
+
+  ioctl (remote_desc, TIOCGETP, &sg);
+  sg.sg_flags = RAW;
+  ioctl (remote_desc, TIOCSETP, &sg);
+
+  if (from_tty)
+    printf ("Remote debugging using %s\n", name);
+  remote_debugging = 1;
+}
+
+/* Convert hex digit A to a number.  */
+
+static int
+fromhex (a)
+     int a;
+{
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else
+    perror ("Reply contains invalid hex digit");
+}
+
+/* Convert number NIB to a hex digit.  */
+
+static int
+tohex (nib)
+     int nib;
+{
+  if (nib < 10)
+    return '0'+nib;
+  else
+    return 'a'+nib-10;
+}
+
+/* Send the command in BUF to the remote machine,
+   and read the reply into BUF.
+   Report an error if we get an error reply.  */
+
+void
+remote_send (buf)
+     char *buf;
+{
+  putpkt (buf);
+  getpkt (buf);
+
+  if (buf[0] == 'E')
+    perror ("Remote failure reply: %s", buf);
+}
+
+/* Send a packet to the remote machine, with error checking.
+   The data of the packet is in BUF.  */
+
+void
+putpkt (buf)
+     char *buf;
+{
+  int i;
+  unsigned char csum = 0;
+  char buf2[500];
+  char buf3[1];
+  int cnt = strlen (buf);
+  char *p;
+
+  if (kiodebug)
+    fprintf (stderr, "Sending packet: %s\n", buf);
+
+  /* Copy the packet into buffer BUF2, encapsulating it
+     and giving it a checksum.  */
+
+  p = buf2;
+  *p++ = '$';
+
+  for (i = 0; i < cnt; i++)
+    {
+      csum += buf[i];
+      *p++ = buf[i];
+    }
+  *p++ = '#';
+  *p++ = tohex ((csum >> 4) & 0xf);
+  *p++ = tohex (csum & 0xf);
+
+  /* Send it over and over until we get a positive ack.  */
+
+  do {
+    write (remote_desc, buf2, p - buf2);
+    read (remote_desc, buf3, 1);
+  } while (buf3[0] != '+');
+}
+
+static int
+readchar ()
+{
+  char buf[1];
+  while (read (remote_desc, buf, 1) != 1) ;
+  return buf[0] & 0x7f;
+}
+
+/* Read a packet from the remote machine, with error checking,
+   and store it in BUF.  */
+
+void
+getpkt (buf)
+     char *buf;
+{
+  char *bp;
+  unsigned char csum, c, c1, c2;
+  extern kiodebug;
+
+  while (1)
+    {
+         csum = 0; 
+      while ((c = readchar()) != '$');
+
+      bp = buf;
+      while (1)
+       {
+         c = readchar ();
+         if (c == '#')
+           break;
+         *bp++ = c;
+         csum += c;
+       }
+      *bp = 0;
+
+      c1 = fromhex (readchar ());
+      c2 = fromhex (readchar ());
+      if (csum == (c1 << 4) + c2)
+           break;
+
+      printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+             (c1 << 4) + c2, csum, buf);
+      write (remote_desc, "-", 1);
+    }
+
+  write (remote_desc, "+", 1);
+
+  if (kiodebug)
+    fprintf (stderr,"Packet received :%s\n", buf);
+}
+
+
+void 
+write_ok(buf)
+       char *buf; 
+{
+       buf[0] = 'O';
+       buf[1] = 'k';
+       buf[2] = '\0';
+}
+
+void 
+write_enn(buf)
+       char *buf; 
+{
+       buf[0] = 'E';
+       buf[1] = 'N';
+       buf[2] = 'N';
+       buf[3] = '\0';
+}
+
+void
+convert_int_to_ascii(from,to,n)
+char *from, *to; int n; 
+{
+       int nib ; 
+       char ch; 
+       while( n-- )
+       {
+               ch = *from++;           
+               nib = ((ch & 0xf0) >> 4)& 0x0f; 
+               *to++ = tohex(nib); 
+               nib = ch & 0x0f; 
+               *to++ = tohex(nib); 
+       } 
+       *to++ = 0; 
+}
+
+
+void
+convert_ascii_to_int(from,to,n)
+char *from, *to; int n;  
+{
+       int nib1,nib2 ; 
+       while( n-- )
+       {
+               nib1 = fromhex(*from++); 
+               nib2 = fromhex(*from++); 
+               *to++ = (((nib1 & 0x0f)<< 4)& 0xf0) | (nib2 & 0x0f); 
+       } 
+}
+
+void
+prepare_resume_reply(buf,status,signal)
+char *buf ,status; 
+unsigned char signal; 
+{
+       int nib; 
+       char ch; 
+
+       *buf++ = 'S';  
+       *buf++ = status;  
+       nib = ((signal & 0xf0) >> 4) ; 
+       *buf++ = tohex(nib); 
+       nib = signal & 0x0f; 
+       *buf++ = tohex(nib); 
+       *buf++ = 0; 
+}
+
+void 
+decode_m_packet(from,mem_addr_ptr,len_ptr)
+char *from;
+unsigned int *mem_addr_ptr, *len_ptr; 
+{
+       int i = 0, j = 0 ; 
+       char ch; 
+       *mem_addr_ptr = *len_ptr = 0; 
+       /************debugging begin************/ 
+       printf("\nIn decode_m_packet"); 
+       /************debugging end************/ 
+
+       while((ch = from[i++]) != ',') 
+       { 
+               *mem_addr_ptr = *mem_addr_ptr << 4; 
+               *mem_addr_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished mem_addr part"); 
+       /************debugging end************/ 
+
+       for(j=0; j < 4; j++) 
+       { 
+               if((ch = from[i++]) == 0)  
+                       break; 
+               *len_ptr = *len_ptr << 4; 
+               *len_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished len_ptr part"); 
+       /************debugging end************/ 
+}
+
+void 
+decode_M_packet(from,mem_addr_ptr,len_ptr,to)
+char *from, *to;
+unsigned int *mem_addr_ptr, *len_ptr; 
+{
+       int i = 0, j = 0 ; 
+       char ch; 
+       *mem_addr_ptr = *len_ptr = 0; 
+       /************debugging begin************/ 
+       printf("\nIn decode_M_packet"); 
+       /************debugging end************/ 
+
+       while((ch = from[i++]) != ',') 
+       { 
+               *mem_addr_ptr = *mem_addr_ptr << 4; 
+               *mem_addr_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished mem_addr part: memaddr = %x",*mem_addr_ptr); 
+       /************debugging end************/ 
+
+       while((ch = from[i++]) != ':') 
+       { 
+               *len_ptr = *len_ptr << 4; 
+               *len_ptr |= fromhex(ch) & 0x0f; 
+       } 
+       /************debugging begin************/ 
+       printf("\nFinished len_ptr part: len = %d",*len_ptr); 
+       /************debugging end************/ 
+
+       convert_ascii_to_int(&from[i++],to,*len_ptr); 
+
+       /************debugging begin************/ 
+       printf("\nmembuf : %x",*(int *)to); 
+       /************debugging end************/ 
+}
+
+SHAR_EOF
+#      End of shell archive
+exit 0
diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c
new file mode 100644 (file)
index 0000000..5724f42
--- /dev/null
@@ -0,0 +1,962 @@
+/* Memory-access and commands for remote NINDY process, for GDB.
+   Copyright (C) 1990-1991 Free Software Foundation, Inc.
+   Contributed by Intel Corporation.  Modified from remote.c by Chris Benenati.
+
+GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY.  No author or distributor accepts responsibility to anyone
+for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.
+Refer to the GDB General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute GDB,
+but only under the conditions described in the GDB General Public
+License.  A copy of this license is supposed to have been given to you
+along with GDB so you can know your rights and responsibilities.  It
+should be in a file named COPYING.  Among other things, the copyright
+notice and this notice must be preserved on all copies.
+
+In other words, go ahead and share GDB, but don't try to stop
+anyone else from sharing it farther.  Help stamp out software hoarding!
+*/
+
+/*
+Except for the data cache routines, this file bears little resemblence
+to remote.c.  A new (although similar) protocol has been specified, and
+portions of the code are entirely dependent on having an i80960 with a
+NINDY ROM monitor at the other end of the line.
+*/
+
+/*****************************************************************************
+ *
+ * REMOTE COMMUNICATION PROTOCOL BETWEEN GDB960 AND THE NINDY ROM MONITOR.
+ *
+ *
+ * MODES OF OPERATION
+ * ----- -- ---------
+ *     
+ * As far as NINDY is concerned, GDB is always in one of two modes: command
+ * mode or passthrough mode.
+ *
+ * In command mode (the default) pre-defined packets containing requests
+ * are sent by GDB to NINDY.  NINDY never talks except in reponse to a request.
+ *
+ * Once the the user program is started, GDB enters passthrough mode, to give
+ * the user program access to the terminal.  GDB remains in this mode until
+ * NINDY indicates that the program has stopped.
+ *
+ *
+ * PASSTHROUGH MODE
+ * ----------- ----
+ *
+ * GDB writes all input received from the keyboard directly to NINDY, and writes
+ * all characters received from NINDY directly to the monitor.
+ *
+ * Keyboard input is neither buffered nor echoed to the monitor.
+ *
+ * GDB remains in passthrough mode until NINDY sends a single ^P character,
+ * to indicate that the user process has stopped.
+ *
+ * Note:
+ *     GDB assumes NINDY performs a 'flushreg' when the user program stops.
+ *
+ *
+ * COMMAND MODE
+ * ------- ----
+ *
+ * All info (except for message ack and nak) is transferred between gdb
+ * and the remote processor in messages of the following format:
+ *
+ *             <info>#<checksum>
+ *
+ * where 
+ *     #       is a literal character
+ *
+ *     <info>  ASCII information;  all numeric information is in the
+ *             form of hex digits ('0'-'9' and lowercase 'a'-'f').
+ *
+ *     <checksum>
+ *             is a pair of ASCII hex digits representing an 8-bit
+ *             checksum formed by adding together each of the
+ *             characters in <info>.
+ *
+ * The receiver of a message always sends a single character to the sender
+ * to indicate that the checksum was good ('+') or bad ('-');  the sender
+ * re-transmits the entire message over until a '+' is received.
+ *
+ * In response to a command NINDY always sends back either data or
+ * a result code of the form "Xnn", where "nn" are hex digits and "X00"
+ * means no errors.  (Exceptions: the "s" and "c" commands don't respond.)
+ *
+ * SEE THE HEADER OF THE FILE "gdb.c" IN THE NINDY MONITOR SOURCE CODE FOR A
+ * FULL DESCRIPTION OF LEGAL COMMANDS.
+ *
+ * SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
+ * OF STOP CODES.
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <setjmp.h>
+
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "bfd.h"
+#include "ieee-float.h"
+
+#include "wait.h"
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <ctype.h>
+#include "nindy-share/ttycntl.h"
+#include "nindy-share/demux.h"
+#include "nindy-share/env.h"
+#include "nindy-share/stop.h"
+
+extern int unlink();
+extern char *getenv();
+extern char *mktemp();
+
+extern char *coffstrip();
+extern void add_syms_addr_command ();
+extern value call_function_by_hand ();
+extern void generic_mourn_inferior ();
+
+extern struct target_ops nindy_ops;
+extern jmp_buf to_top_level;
+extern FILE *instream;
+extern struct ext_format ext_format_i960[];    /* i960-tdep.c */
+
+extern char ninStopWhy ();
+
+int nindy_initial_brk; /* nonzero if want to send an initial BREAK to nindy */
+int nindy_old_protocol;        /* nonzero if want to use old protocol */
+char *nindy_ttyname;   /* name of tty to talk to nindy on, or null */
+
+#define DLE    '\020'  /* Character NINDY sends to indicate user program has
+                        * halted.  */
+#define TRUE   1
+#define FALSE  0
+
+int nindy_fd = 0;      /* Descriptor for I/O to NINDY  */
+static int have_regs = 0;      /* 1 iff regs read since i960 last halted */
+static int regs_changed = 0;   /* 1 iff regs were modified since last read */
+
+extern char *exists();
+static void dcache_flush (), dcache_poke (), dcache_init();
+static int dcache_fetch ();
+\f
+/* FIXME, we can probably use the normal terminal_inferior stuff here.
+   We have to do terminal_inferior and then set up the passthrough
+   settings initially.  Thereafter, terminal_ours and terminal_inferior
+   will automatically swap the settings around for us.  */
+
+/* Restore TTY to normal operation */
+
+static TTY_STRUCT orig_tty;    /* TTY attributes before entering passthrough */
+
+static void
+restore_tty()
+{
+       ioctl( 0, TIOCSETN, &orig_tty );
+}
+
+
+/* Recover from ^Z or ^C while remote process is running */
+
+static void (*old_ctrlc)();    /* Signal handlers before entering passthrough */
+
+#ifdef SIGTSTP
+static void (*old_ctrlz)();
+#endif
+
+static
+#ifdef USG
+void
+#endif
+cleanup()
+{
+       restore_tty();
+       signal(SIGINT, old_ctrlc);
+#ifdef SIGTSTP
+       signal(SIGTSTP, old_ctrlz);
+#endif
+       error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
+}
+\f
+/* Clean up anything that needs cleaning when losing control.  */
+
+static char *savename;
+
+static void
+nindy_close (quitting)
+     int quitting;
+{
+  if (nindy_fd)
+    close (nindy_fd);
+  nindy_fd = 0;
+
+  if (savename)
+    free (savename);
+  savename = 0;
+}
+
+/* Open a connection to a remote debugger.   
+   FIXME, there should be a way to specify the various options that are
+   now specified with gdb command-line options.  (baud_rate, old_protocol,
+   and initial_brk)  */
+void
+nindy_open (name, from_tty)
+    char *name;                /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
+    int from_tty;
+{
+
+  if (!name)
+    error_no_arg ("serial port device name");
+
+  nindy_close (0);
+
+       have_regs = regs_changed = 0;
+       dcache_init();
+
+       /* Allow user to interrupt the following -- we could hang if
+        * there's no NINDY at the other end of the remote tty.
+        */
+       immediate_quit++;
+       nindy_fd = ninConnect( name, baud_rate? baud_rate: "9600",
+                       nindy_initial_brk, !from_tty, nindy_old_protocol );
+       immediate_quit--;
+
+       if ( nindy_fd < 0 ){
+               nindy_fd = 0;
+               error( "Can't open tty '%s'", name );
+       }
+
+        savename = savestring (name, strlen (name));
+       push_target (&nindy_ops);
+       target_fetch_registers(-1);
+}
+
+/* User-initiated quit of nindy operations.  */
+
+static void
+nindy_detach (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  dont_repeat ();
+  if (name)
+    error ("Too many arguments");
+  pop_target ();
+}
+
+static void
+nindy_files_info ()
+{
+  printf("\tAttached to %s at %s bps%s%s.\n", savename,
+        baud_rate? baud_rate: "9600",
+        nindy_old_protocol? " in old protocol": "",
+         nindy_initial_brk? " with initial break": "");
+}
+\f
+/******************************************************************************
+ * remote_load:
+ *     Download an object file to the remote system by invoking the "comm960"
+ *     utility.  We look for "comm960" in $G960BIN, $G960BASE/bin, and
+ *     DEFAULT_BASE/bin/HOST/bin where
+ *             DEFAULT_BASE is defined in env.h, and
+ *             HOST must be defined on the compiler invocation line.
+ ******************************************************************************/
+
+static void
+nindy_load( filename, from_tty )
+    char *filename;
+    int from_tty;
+{
+  char *tmpfile;
+  struct cleanup *old_chain;
+  char *scratch_pathname;
+  int scratch_chan;
+
+  if (!filename)
+    filename = get_exec_file (1);
+
+  filename = tilde_expand (filename);
+  make_cleanup (free, filename);
+
+  scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+                       &scratch_pathname);
+  if (scratch_chan < 0)
+    perror_with_name (filename);
+  close (scratch_chan);                /* Slightly wasteful FIXME */
+
+  have_regs = regs_changed = 0;
+  mark_breakpoints_out();
+  inferior_pid = 0;
+  dcache_flush();
+
+  tmpfile = coffstrip(scratch_pathname);
+  if ( tmpfile ){
+         old_chain = make_cleanup(unlink,tmpfile);
+         immediate_quit++;
+         ninDownload( tmpfile, !from_tty );
+/* FIXME, don't we want this merged in here? */
+         immediate_quit--;
+         do_cleanups (old_chain);
+  }
+}
+
+
+
+/* Return the number of characters in the buffer before the first DLE character.
+ */
+
+static
+int
+non_dle( buf, n )
+    char *buf;         /* Character buffer; NOT '\0'-terminated */
+    int n;             /* Number of characters in buffer */
+{
+       int i;
+
+       for ( i = 0; i < n; i++ ){
+               if ( buf[i] == DLE ){
+                       break;
+               }
+       }
+       return i;
+}
+\f
+/* Tell the remote machine to resume.  */
+
+void
+nindy_resume (step, siggnal)
+     int step, siggnal;
+{
+       if (siggnal != 0 && siggnal != stop_signal)
+         error ("Can't send signals to remote NINDY targets.");
+
+       dcache_flush();
+       if ( regs_changed ){
+               nindy_store_registers ();
+               regs_changed = 0;
+       }
+       have_regs = 0;
+       ninGo( step );
+}
+
+/* Wait until the remote machine stops. While waiting, operate in passthrough
+ * mode; i.e., pass everything NINDY sends to stdout, and everything from
+ * stdin to NINDY.
+ *
+ * Return to caller, storing status in 'status' just as `wait' would.
+ */
+
+void
+nindy_wait( status )
+    WAITTYPE *status;
+{
+       DEMUX_DECL;     /* OS-dependent data needed by DEMUX... macros */
+       char buf[500];  /* FIXME, what is "500" here? */
+       int i, n;
+       unsigned char stop_exit;
+       unsigned char stop_code;
+       TTY_STRUCT tty;
+       long ip_value, fp_value, sp_value;      /* Reg values from stop */
+
+
+       WSETEXIT( (*status), 0 );
+
+       /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
+
+       /* Save current tty attributes, set up signals to restore them.
+        */
+       ioctl( 0, TIOCGETP, &orig_tty );
+       old_ctrlc = signal( SIGINT, cleanup );
+#ifdef SIGTSTP
+       old_ctrlz = signal( SIGTSTP, cleanup );
+#endif
+
+       /* Pass input from keyboard to NINDY as it arrives.
+        * NINDY will interpret <CR> and perform echo.
+        */
+       tty = orig_tty;
+       TTY_NINDYTERM( tty );
+       ioctl( 0, TIOCSETN, &tty );
+
+       while ( 1 ){
+               /* Go to sleep until there's something for us on either
+                * the remote port or stdin.
+                */
+
+               DEMUX_WAIT( nindy_fd );
+
+               /* Pass input through to correct place */
+
+               n = DEMUX_READ( 0, buf, sizeof(buf) );
+               if ( n ){                               /* Input on stdin */
+                       write( nindy_fd, buf, n );
+               }
+
+               n = DEMUX_READ( nindy_fd, buf, sizeof(buf) );
+               if ( n ){                               /* Input on remote */
+                       /* Write out any characters in buffer preceding DLE */
+                       i = non_dle( buf, n );
+                       if ( i > 0 ){
+                               write( 1, buf, i );
+                       }
+
+                       if ( i != n ){
+                               /* There *was* a DLE in the buffer */
+                               stop_exit = ninStopWhy( &stop_code,
+                                       &ip_value, &fp_value, &sp_value);
+                               if ( !stop_exit && (stop_code==STOP_SRQ) ){
+                                       immediate_quit++;
+                                       ninSrq();
+                                       immediate_quit--;
+                               } else {
+                                       /* Get out of loop */
+                                       supply_register (IP_REGNUM, &ip_value);
+                                       supply_register (FP_REGNUM, &fp_value);
+                                       supply_register (SP_REGNUM, &sp_value);
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       signal( SIGINT, old_ctrlc );
+#ifdef SIGTSTP
+       signal( SIGTSTP, old_ctrlz );
+#endif
+       restore_tty();
+
+       if ( stop_exit ){                       /* User program exited */
+               WSETEXIT( (*status), stop_code );
+       } else {                                /* Fault or trace */
+               switch (stop_code){
+               case STOP_GDB_BPT:
+               case TRACE_STEP:
+                       /* Make it look like a VAX trace trap */
+                       stop_code = SIGTRAP;
+                       break;
+               default:
+                       /* The target is not running Unix, and its
+                          faults/traces do not map nicely into Unix signals.
+                          Make sure they do not get confused with Unix signals
+                          by numbering them with values higher than the highest
+                          legal Unix signal.  code in i960_print_fault(),
+                          called via PRINT_RANDOM_SIGNAL, will interpret the
+                          value.  */
+                       stop_code += NSIG;
+                       break;
+               }
+               WSETSTOP( (*status), stop_code );
+       }
+}
+
+/* Read the remote registers into the block REGS.  */
+
+/* This is the block that ninRegsGet and ninRegsPut handles.  */
+struct nindy_regs {
+  char local_regs[16 * 4];
+  char global_regs[16 * 4];
+  char pcw_acw[2 * 4];
+  char ip[4];
+  char tcw[4];
+  char fp_as_double[4 * 8];
+};
+
+static int
+nindy_fetch_registers(regno)
+     int regno;
+{
+  struct nindy_regs nindy_regs;
+  int regnum, inv;
+  double dub;
+
+  immediate_quit++;
+  ninRegsGet( (char *) &nindy_regs );
+  immediate_quit--;
+
+  bcopy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
+  bcopy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
+  bcopy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
+  bcopy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
+  bcopy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
+  for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
+    dub = unpack_double (builtin_type_double,
+                        &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
+                        &inv);
+    /* dub now in host byte order */
+    double_to_ieee_extended (ext_format_i960, &dub,
+                            &registers[REGISTER_BYTE (regnum)]);
+  }
+
+  registers_fetched ();
+  return 0;
+}
+
+static void
+nindy_prepare_to_store()
+{
+  nindy_fetch_registers(-1);
+}
+
+static int
+nindy_store_registers(regno)
+     int regno;
+{
+  struct nindy_regs nindy_regs;
+  int regnum, inv;
+  double dub;
+
+  bcopy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs,  16*4);
+  bcopy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
+  bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw,     2*4);
+  bcopy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip,           1*4);
+  bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw,         1*4);
+  /* Float regs.  Only works on IEEE_FLOAT hosts.  */
+  for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
+    ieee_extended_to_double (ext_format_i960,
+                            &registers[REGISTER_BYTE (regnum)], &dub);
+    /* dub now in host byte order */
+    /* FIXME-someday, the arguments to unpack_double are backward.
+       It expects a target double and returns a host; we pass the opposite.
+       This mostly works but not quite.  */
+    dub = unpack_double (builtin_type_double, &dub, &inv);
+    /* dub now in target byte order */
+    bcopy ((char *)&dub, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
+       8);
+  }
+
+  immediate_quit++;
+  ninRegsPut( (char *) &nindy_regs );
+  immediate_quit--;
+  return 0;
+}
+
+/* Read a word from remote address ADDR and return it.
+ * This goes through the data cache.
+ */
+int
+nindy_fetch_word (addr)
+     CORE_ADDR addr;
+{
+       return dcache_fetch (addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+   This goes through the data cache.  */
+
+void
+nindy_store_word (addr, word)
+     CORE_ADDR addr;
+     int word;
+{
+       dcache_poke (addr, word);
+}
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.   Copy to inferior if
+   WRITE is nonzero.  Returns the length copied.
+
+   This is stolen almost directly from infptrace.c's child_xfer_memory,
+   which also deals with a word-oriented memory interface.  Sometime,
+   FIXME, rewrite this to not use the word-oriented routines.  */
+
+int
+nindy_xfer_inferior_memory(memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+
+  if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory data.  */
+
+      if (addr != memaddr || len < (int)sizeof (int)) {
+       /* Need part of initial word -- fetch it.  */
+        buffer[0] = nindy_fetch_word (addr);
+      }
+
+      if (count > 1)           /* FIXME, avoid if even boundary */
+       {
+         buffer[count - 1]
+           = nindy_fetch_word (addr + (count - 1) * sizeof (int));
+       }
+
+      /* Copy data to be written over corresponding part of buffer */
+
+      bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+      /* Write the entire buffer.  */
+
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         nindy_store_word (addr, buffer[i]);
+         if (errno)
+           return 0;
+       }
+    }
+  else
+    {
+      /* Read all the longwords */
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         buffer[i] = nindy_fetch_word (addr);
+         if (errno)
+           return 0;
+         QUIT;
+       }
+
+      /* Copy appropriate bytes out of the buffer.  */
+      bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+    }
+  return len;
+}
+\f
+/* The data cache records all the data read from the remote machine
+   since the last time it stopped.
+
+   Each cache block holds 16 bytes of data
+   starting at a multiple-of-16 address.  */
+
+#define DCACHE_SIZE 64         /* Number of cache blocks */
+
+struct dcache_block {
+       struct dcache_block *next, *last;
+       unsigned int addr;      /* Address for which data is recorded.  */
+       int data[4];
+};
+
+struct dcache_block dcache_free, dcache_valid;
+
+/* Free all the data cache blocks, thus discarding all cached data.  */ 
+static
+void
+dcache_flush ()
+{
+  register struct dcache_block *db;
+
+  while ((db = dcache_valid.next) != &dcache_valid)
+    {
+      remque (db);
+      insque (db, &dcache_free);
+    }
+}
+
+/*
+ * If addr is present in the dcache, return the address of the block
+ * containing it.
+ */
+static
+struct dcache_block *
+dcache_hit (addr)
+     unsigned int addr;
+{
+  register struct dcache_block *db;
+
+  if (addr & 3)
+    abort ();
+
+  /* Search all cache blocks for one that is at this address.  */
+  db = dcache_valid.next;
+  while (db != &dcache_valid)
+    {
+      if ((addr & 0xfffffff0) == db->addr)
+       return db;
+      db = db->next;
+    }
+  return NULL;
+}
+
+/*  Return the int data at address ADDR in dcache block DC.  */
+static
+int
+dcache_value (db, addr)
+     struct dcache_block *db;
+     unsigned int addr;
+{
+  if (addr & 3)
+    abort ();
+  return (db->data[(addr>>2)&3]);
+}
+
+/* Get a free cache block, put or keep it on the valid list,
+   and return its address.  The caller should store into the block
+   the address and data that it describes, then remque it from the
+   free list and insert it into the valid list.  This procedure
+   prevents errors from creeping in if a ninMemGet is interrupted
+   (which used to put garbage blocks in the valid list...).  */
+static
+struct dcache_block *
+dcache_alloc ()
+{
+  register struct dcache_block *db;
+
+  if ((db = dcache_free.next) == &dcache_free)
+    {
+      /* If we can't get one from the free list, take last valid and put
+        it on the free list.  */
+      db = dcache_valid.last;
+      remque (db);
+      insque (db, &dcache_free);
+    }
+
+  remque (db);
+  insque (db, &dcache_valid);
+  return (db);
+}
+
+/* Return the contents of the word at address ADDR in the remote machine,
+   using the data cache.  */
+static
+int
+dcache_fetch (addr)
+     CORE_ADDR addr;
+{
+  register struct dcache_block *db;
+
+  db = dcache_hit (addr);
+  if (db == 0)
+    {
+      db = dcache_alloc ();
+      immediate_quit++;
+      ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
+      immediate_quit--;
+      db->addr = addr & ~0xf;
+      remque (db);                     /* Off the free list */
+      insque (db, &dcache_valid);      /* On the valid list */
+    }
+  return (dcache_value (db, addr));
+}
+
+/* Write the word at ADDR both in the data cache and in the remote machine.  */
+static void
+dcache_poke (addr, data)
+     CORE_ADDR addr;
+     int data;
+{
+  register struct dcache_block *db;
+
+  /* First make sure the word is IN the cache.  DB is its cache block.  */
+  db = dcache_hit (addr);
+  if (db == 0)
+    {
+      db = dcache_alloc ();
+      immediate_quit++;
+      ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
+      immediate_quit--;
+      db->addr = addr & ~0xf;
+      remque (db);                     /* Off the free list */
+      insque (db, &dcache_valid);      /* On the valid list */
+    }
+
+  /* Modify the word in the cache.  */
+  db->data[(addr>>2)&3] = data;
+
+  /* Send the changed word.  */
+  immediate_quit++;
+  ninMemPut(addr, (unsigned char *)&data, 4);
+  immediate_quit--;
+}
+
+/* The cache itself. */
+struct dcache_block the_cache[DCACHE_SIZE];
+
+/* Initialize the data cache.  */
+static void
+dcache_init ()
+{
+  register i;
+  register struct dcache_block *db;
+
+  db = the_cache;
+  dcache_free.next = dcache_free.last = &dcache_free;
+  dcache_valid.next = dcache_valid.last = &dcache_valid;
+  for (i=0;i<DCACHE_SIZE;i++,db++)
+    insque (db, &dcache_free);
+}
+
+
+static void
+nindy_create_inferior (execfile, args, env)
+     char *execfile;
+     char *args;
+     char **env;
+{
+  int entry_pt;
+  int pid;
+
+  if (args && *args)
+    error ("Can't pass arguments to remote NINDY process");
+
+  if (execfile == 0 || exec_bfd == 0)
+    error ("No exec file specified");
+
+  entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+  pid = 42;
+
+#ifdef CREATE_INFERIOR_HOOK
+  CREATE_INFERIOR_HOOK (pid);
+#endif  
+
+/* The "process" (board) is already stopped awaiting our commands, and
+   the program is already downloaded.  We just set its PC and go.  */
+
+  inferior_pid = pid;          /* Needed for wait_for_inferior below */
+
+  clear_proceed_status ();
+
+#if defined (START_INFERIOR_HOOK)
+  START_INFERIOR_HOOK ();
+#endif
+
+  /* Tell wait_for_inferior that we've started a new process.  */
+  init_wait_for_inferior ();
+
+  /* Set up the "saved terminal modes" of the inferior
+     based on what modes we are starting it with.  */
+  target_terminal_init ();
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  /* remote_start(args); */
+  /* trap_expected = 0; */
+  /* insert_step_breakpoint ();  FIXME, do we need this?  */
+  proceed ((CORE_ADDR)entry_pt, -1, 0);                /* Let 'er rip... */
+}
+
+static void
+reset_command(args, from_tty)
+     char *args;
+     int from_tty;
+{
+       if ( !nindy_fd ){
+           error( "No target system to reset -- use 'target nindy' command.");
+       }
+       if ( query("Really reset the target system?",0,0) ){
+               send_break( nindy_fd );
+               tty_flush( nindy_fd );
+       }
+}
+
+void
+nindy_kill (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  return;              /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+   The program actually lives on in the remote processor's RAM, and may be
+   run again without a download.  Don't leave it full of breakpoint
+   instructions.  */
+
+void
+nindy_mourn_inferior ()
+{
+  remove_breakpoints ();
+  generic_mourn_inferior ();   /* Do all the proper things now */
+}
+\f
+/* This routine is run as a hook, just before the main command loop is
+   entered.  If gdb is configured for the i960, but has not had its
+   nindy target specified yet, this will loop prompting the user to do so.
+
+   Unlike the loop provided by Intel, we actually let the user get out
+   of this with a RETURN.  This is useful when e.g. simply examining
+   an i960 object file on the host system.  */
+
+nindy_before_main_loop ()
+{
+  char ttyname[100];
+  char *p, *p2;
+
+  setjmp(to_top_level);
+  while (current_target != &nindy_ops) { /* remote tty not specified yet */
+       if ( instream == stdin ){
+               printf("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit:  ");
+               fflush( stdout );
+       }
+       fgets( ttyname, sizeof(ttyname)-1, stdin );
+
+       /* Strip leading and trailing whitespace */
+       for ( p = ttyname; isspace(*p); p++ ){
+               ;
+       }
+       if ( *p == '\0' ){
+               return;         /* User just hit spaces or return, wants out */
+       }
+       for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
+               ;
+       }
+       *p2= '\0';
+       if ( !strcmp("quit",p) ){
+               exit(1);
+       }
+
+       nindy_open( p, 1 );
+
+       /* Now that we have a tty open for talking to the remote machine,
+          download the executable file if one was specified.  */
+       if ( !setjmp(to_top_level) && exec_bfd ) {
+             target_load (bfd_get_filename (exec_bfd), 1);
+       }
+  }
+}
+\f
+/* Define the target subroutine names */
+
+struct target_ops nindy_ops = {
+       "nindy", "Remote serial target in i960 NINDY-specific protocol",
+       nindy_open, nindy_close,
+       0, nindy_detach, nindy_resume, nindy_wait,
+       nindy_fetch_registers, nindy_store_registers,
+       nindy_prepare_to_store, 0, 0, /* conv_from, conv_to */
+       nindy_xfer_inferior_memory, nindy_files_info,
+       0, 0, /* insert_breakpoint, remove_breakpoint, */
+       0, 0, 0, 0, 0,  /* Terminal crud */
+       nindy_kill,
+       nindy_load, add_syms_addr_command,
+       call_function_by_hand,
+       0, /* lookup_symbol */
+       nindy_create_inferior,
+       nindy_mourn_inferior,
+       process_stratum, 0, /* next */
+       1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_nindy ()
+{
+  add_target (&nindy_ops);
+  add_com ("reset", class_obscure, reset_command,
+          "Send a 'break' to the remote target system.\n\
+Only useful if the target has been equipped with a circuit\n\
+to perform a hard reset when a break is detected.");
+}
diff --git a/gdb/remote-sa.m68k.shar b/gdb/remote-sa.m68k.shar
new file mode 100755 (executable)
index 0000000..aeb76e5
--- /dev/null
@@ -0,0 +1,893 @@
+# This is a shell archive.  Remove anything before this line,
+# then unpack it by saving it in a file and typing "sh file".
+#
+# Wrapped by Glenn Engel <glenne@labgre> on Mon Jun 12 15:19:20 1989
+#
+# This archive contains:
+#      remcom.c        
+#
+
+LANG=""; export LANG
+PATH=/bin:/usr/bin:$PATH; export PATH
+
+echo x - remcom.c
+cat >remcom.c <<'@EOF'
+
+/****************************************************************************
+
+               THIS SOFTWARE IS NOT COPYRIGHTED  
+   
+   HP offers the following for use in the public domain.  HP makes no
+   warranty with regard to the software or it's performance and the 
+   user accepts the software "AS IS" with all faults.
+
+   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ *  $Header$                   
+ *
+ *  $Module name: remcom.c $  
+ *  $Revision$
+ *  $Date$
+ *  $Contributor:     Lake Stevens Instrument Division$
+ *  
+ *  $Description:     low level support for gdb debugger. $
+ *
+ *  $Considerations:  only works on target hardware $
+ *
+ *  $Written by:      Glenn Engel $
+ *  $ModuleState:     Experimental $ 
+ *
+ *  $NOTES:           See Below $
+ * 
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a trap #1.
+ *  
+ *  Some explanation is probably necessary to explain how exceptions are
+ *  handled.  When an exception is encountered the 68000 pushes the current
+ *  program counter and status register onto the supervisor stack and then
+ *  transfers execution to a location specified in it's vector table.
+ *  The handlers for the exception vectors are hardwired to jmp to an address
+ *  given by the relation:  (exception - 256) * 6.  These are decending 
+ *  addresses starting from -6, -12, -18, ...  By allowing 6 bytes for
+ *  each entry, a jsr, jmp, bsr, ... can be used to enter the exception 
+ *  handler.  Using a jsr to handle an exception has an added benefit of
+ *  allowing a single handler to service several exceptions and use the
+ *  return address as the key differentiation.  The vector number can be
+ *  computed from the return address by [ exception = (addr + 1530) / 6 ].
+ *  The sole purpose of the routine _catchException is to compute the
+ *  exception number and push it on the stack in place of the return address.
+ *  The external function exceptionHandler() is
+ *  used to attach a specific handler to a specific 68k exception.
+ *  For 68020 machines, the ability to have a return address around just
+ *  so the vector can be determined is not necessary because the '020 pushes an
+ *  extra word onto the stack containing the vector offset
+ * 
+ *  Because gdb will sometimes write to the stack area to execute function
+ *  calls, this program cannot rely on using the supervisor stack so it
+ *  uses it's own stack area reserved in the int array remcomStack.  
+ * 
+ *************
+ *
+ *    The following gdb commands are supported:
+ * 
+ * command          function                               Return value
+ * 
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ * 
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ * 
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ * 
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ * 
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ * 
+ * All commands and responses are sent with a packet which includes a 
+ * checksum.  A packet consists of 
+ * 
+ * $<packet info>#<checksum>.
+ * 
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ * 
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ * 
+ * Example:
+ * 
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ * 
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+/************************************************************************
+ *
+ * external low-level support routines 
+ */
+typedef void (*ExceptionHook)(int);   /* pointer to function with int parm */
+typedef void (*Function)();           /* pointer to a function */
+
+extern putDebugChar();   /* write a single character      */
+extern getDebugChar();   /* read and return a single char */
+
+extern Function exceptionHandler();  /* assign an exception handler */
+extern ExceptionHook exceptionHook;  /* hook variable for errors/exceptions */
+
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 400
+
+static char initialized;  /* boolean flag. != 0 means we've been initialized */
+
+int     remote_debug = 0;
+/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */ 
+
+char hexchars[]="0123456789abcdef";
+
+/* there are 180 bytes of registers on a 68020 w/68881      */
+/* many of the fpa registers are 12 byte (96 bit) registers */
+#define NUMREGBYTES 180
+enum regnames {D0,D1,D2,D3,D4,D5,D6,D7, 
+               A0,A1,A2,A3,A4,A5,A6,A7, 
+               PS,PC,
+               FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
+               FPCONTROL,FPSTATUS,FPIADDR
+              };
+
+typedef struct FrameStruct
+{
+    struct FrameStruct  *previous;
+    int       exceptionPC;      /* pc value when this frame created */
+    int       exceptionVector;  /* cpu vector causing exception     */
+    short     frameSize;        /* size of cpu frame in words       */
+    short     sr;               /* for 68000, this not always sr    */
+    int       pc;
+    short     format;
+    int       fsaveHeader;
+    int       morejunk[0];        /* exception frame, fp save... */
+} Frame;
+
+#define FRAMESIZE 500
+static Frame *lastFrame;
+static int   frameStack[FRAMESIZE];
+
+/*
+ * these should not be static cuz they can be used outside this module
+ */
+int registers[NUMREGBYTES/4];
+int superStack;
+
+static int remcomStack[400];
+static int* stackPtr = &remcomStack[399];
+
+/*
+ * In many cases, the system will want to continue exception processing
+ * when a continue command is given.  
+ * oldExceptionHook is a function to invoke in this case.
+ */
+
+static ExceptionHook oldExceptionHook;
+
+/* the size of the exception stack on the 68020 varies with the type of
+ * exception.  The following table is the number of WORDS used
+ * for each exception format.
+ */
+static short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,4,4,4,4 };
+
+/************* jump buffer used for setjmp/longjmp **************************/
+jmp_buf env;
+
+/***************************  ASSEMBLY CODE MACROS *************************/
+/*                                                                        */
+
+#ifdef __HAVE_68881__
+/* do an fsave, then remember the address to begin a restore from */
+#define SAVE_FP_REGS()    asm(" fsave   a0@-");                \
+                         asm(" fmovemx fp0-fp7,_registers+72");        \
+                         asm(" fmoveml fpcr/fpsr/fpi,_registers+168"); 
+#define RESTORE_FP_REGS() asm(" fmoveml _registers+168,fpcr/fpsr/fpi"); \
+                         asm(" fmovemx _registers+72,fp0-fp7");        \
+                         asm(" frestore a0@+");
+#else
+#define SAVE_FP_REGS()
+#define RESTORE_FP_REGS()
+#endif /* __HAVE_68881__ */
+
+asm("
+.text
+.globl _return_to_super
+_return_to_super:
+        movel   _registers+60,sp /* get new stack pointer */        
+        movel   _lastFrame,a0   /* get last frame info  */              
+        bra     return_to_any
+
+.globl _return_to_user
+_return_to_user:
+        movel   _registers+60,a0 /* get usp */                          
+        movel   a0,usp           /* set usp */                         
+        movel   _superStack,sp  /* get original stack pointer */        
+
+return_to_any:
+        movel   _lastFrame,a0   /* get last frame info  */              
+        movel   a0@+,_lastFrame /* link in previous frame     */        
+        addql   #8,a0           /* skip over pc, vector#*/              
+        movew   a0@+,d0         /* get # of words in cpu frame */       
+        addw    d0,a0           /* point to end of data        */       
+        addw    d0,a0           /* point to end of data        */       
+        movel   a0,a1                                                   
+#                                                                       
+# copy the stack frame                                                  
+        subql   #1,d0                                                   
+copyUserLoop:                                                               
+        movew   a1@-,sp@-                                               
+        dbf     d0,copyUserLoop                                             
+");                                                                     
+        RESTORE_FP_REGS()                                              
+   asm("   moveml  _registers,d0-d7/a0-a6");                           
+   asm("   rte");  /* pop and go! */                                    
+
+#define DISABLE_INTERRUPTS()   asm("         oriw   #0x0700,sr");
+#define BREAKPOINT() asm("   trap #1");
+
+/* this function is called immediately when a level 7 interrupt occurs */
+/* if the previous interrupt level was 7 then we're already servicing  */
+/* this interrupt and an rte is in order to return to the debugger.    */
+/* For the 68000, the offset for sr is 6 due to the jsr return address */
+asm("
+.text
+.globl __debug_level7
+__debug_level7:
+       movew   d0,sp@-");
+#ifdef mc68020
+asm("  movew   sp@(2),d0");
+#else
+asm("  movew   sp@(6),d0");
+#endif
+asm("  andiw   #0x700,d0
+       cmpiw   #0x700,d0
+       beq     _already7
+        movew   sp@+,d0        
+        bra     __catchException
+_already7:
+       movew   sp@+,d0");
+#ifndef mc68020
+asm("  lea     sp@(4),sp");     /* pull off 68000 return address */
+#endif
+asm("  rte");
+
+extern void _catchException();
+
+#ifdef mc68020
+/* This function is called when a 68020 exception occurs.  It saves
+ * all the cpu and fpcp regs in the _registers array, creates a frame on a
+ * linked list of frames which has the cpu and fpcp stack frames needed
+ * to properly restore the context of these processors, and invokes
+ * an exception handler (remcom_handler).
+ *
+ * stack on entry:                       stack on exit:
+ *   N bytes of junk                     exception # MSWord
+ *   Exception Format Word               exception # MSWord
+ *   Program counter LSWord              
+ *   Program counter MSWord             
+ *   Status Register                    
+ *                                       
+ *                                       
+ */
+asm(" 
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+        moveml  d0-d7/a0-a6,_registers /* save registers        */
+       movel   _lastFrame,a0   /* last frame pointer */
+");
+SAVE_FP_REGS();        
+asm("
+       lea     _registers,a5   /* get address of registers     */
+        movew   sp@,d1          /* get status register          */
+        movew   d1,a5@(66)      /* save sr                     */      
+       movel   sp@(2),a4       /* save pc in a4 for later use  */
+        movel   a4,a5@(68)      /* save pc in _regisers[]              */
+
+#
+# figure out how many bytes in the stack frame
+       movew   sp@(6),d0       /* get '020 exception format    */
+        movew   d0,d2           /* make a copy of format word   */
+        andiw   #0xf000,d0      /* mask off format type         */
+        rolw    #5,d0           /* rotate into the low byte *2  */
+        lea     _exceptionSize,a1   
+        addw    d0,a1           /* index into the table         */
+       movew   a1@,d0          /* get number of words in frame */
+        movew   d0,d3           /* save it                      */
+        subw    d0,a0          /* adjust save pointer          */
+        subw    d0,a0          /* adjust save pointer(bytes)   */
+       movel   a0,a1           /* copy save pointer            */
+       subql   #1,d0           /* predecrement loop counter    */
+#
+# copy the frame
+saveFrameLoop:
+       movew   sp@+,a1@+
+       dbf     d0,saveFrameLoop
+#
+# now that the stack has been clenaed,
+# save the a7 in use at time of exception
+        movel   sp,_superStack  /* save supervisor sp           */
+        andiw   #0x2000,d1      /* were we in supervisor mode ? */
+        beq     userMode       
+        movel   a7,a5@(60)      /* save a7                  */
+        bra     a7saveDone
+userMode:  
+       movel   usp,a1          
+        movel   a1,a5@(60)      /* save user stack pointer     */
+a7saveDone:
+
+#
+# save size of frame
+        movew   d3,a0@-
+
+#
+# compute exception number
+       andl    #0xfff,d2       /* mask off vector offset       */
+       lsrw    #2,d2           /* divide by 4 to get vect num  */
+        movel   d2,a0@-         /* save it                      */
+#
+# save pc causing exception
+        movel   a4,a0@-
+#
+# save old frame link and set the new value
+       movel   _lastFrame,a1   /* last frame pointer */
+       movel   a1,a0@-         /* save pointer to prev frame   */
+        movel   a0,_lastFrame
+
+        movel   d2,sp@-                /* push exception num           */
+       movel   _exceptionHook,a0  /* get address of handler */
+        jbsr    a0@             /* and call it */
+        jmp     __returnFromException     /* now, return        */
+");
+#else /* mc68000 */
+/* This function is called when an exception occurs.  It translates the
+ * return address found on the stack into an exception vector # which
+ * is then handled by either handle_exception or a system handler.
+ * _catchException provides a front end for both.  
+ *
+ * stack on entry:                       stack on exit:
+ *   Program counter MSWord              exception # MSWord 
+ *   Program counter LSWord              exception # MSWord
+ *   Status Register                     
+ *   Return Address  MSWord              
+ *   Return Address  LSWord             
+ */
+asm("
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+        moveml d0-d7/a0-a6,_registers  /* save registers               */
+       movel   _lastFrame,a0   /* last frame pointer */
+");
+SAVE_FP_REGS();        
+asm("
+        lea     _registers,a5   /* get address of registers     */
+        movel   sp@+,d2         /* pop return address           */
+       addl    #1530,d2        /* convert return addr to       */
+       divs    #6,d2           /*  exception number            */
+       extl    d2   
+
+        moveql  #3,d3           /* assume a three word frame     */
+
+        cmpiw   #3,d2           /* bus error or address error ? */
+        bgt     normal          /* if >3 then normal error      */
+        movel   sp@+,a0@-       /* copy error info to frame buff*/
+        movel   sp@+,a0@-       /* these are never used         */
+        moveql  #7,d3           /* this is a 7 word frame       */
+     
+normal:   
+       movew   sp@+,d1         /* pop status register          */
+        movel   sp@+,a4         /* pop program counter          */
+        movew   d1,a5@(66)      /* save sr                     */      
+        movel   a4,a5@(68)      /* save pc in _regisers[]              */
+        movel   a4,a0@-         /* copy pc to frame buffer      */
+       movew   d1,a0@-         /* copy sr to frame buffer      */
+
+        movel   sp,_superStack  /* save supervisor sp          */
+
+        andiw   #0x2000,d1      /* were we in supervisor mode ? */
+        beq     userMode       
+        movel   a7,a5@(60)      /* save a7                  */
+        bra     saveDone             
+userMode:
+        movel   usp,a1         /* save user stack pointer      */
+        movel   a1,a5@(60)      /* save user stack pointer     */
+saveDone:
+
+        movew   d3,a0@-         /* push frame size in words     */
+        movel   d2,a0@-         /* push vector number           */
+        movel   a4,a0@-         /* push exception pc            */
+
+#
+# save old frame link and set the new value
+       movel   _lastFrame,a1   /* last frame pointer */
+       movel   a1,a0@-         /* save pointer to prev frame   */
+        movel   a0,_lastFrame
+
+        movel   d2,sp@-                /* push exception num           */
+       movel   _exceptionHook,a0  /* get address of handler */
+        jbsr    a0@             /* and call it */
+        jmp     __returnFromException     /* now, return        */
+");
+#endif
+
+
+/*
+ * remcomHandler is a front end for handle_exception.  It moves the
+ * stack pointer into an area reserved for debugger use in case the
+ * breakpoint happened in supervisor mode.
+ */
+asm("_remcomHandler:");
+asm("           addl    #4,sp");        /* pop off return address     */
+asm("           movel   sp@+,d0");      /* get the exception number   */
+asm("          movel   _stackPtr,sp"); /* move to remcom stack area  */
+asm("          movel   d0,sp@-");      /* push exception onto stack  */
+asm("          jbsr    _handle_exception");    /* this never returns */
+asm("           rts");                  /* return */
+
+void _returnFromException( Frame *frame )
+{
+    /* if no existing frame, dummy one up */
+    if (! frame)
+    {
+        frame = lastFrame -1;
+        frame->frameSize = 4;
+        frame->format = 0;
+        frame->fsaveHeader = 0;
+        frame->previous = lastFrame;
+    }
+
+#ifndef mc68020
+    /* a 68000 cannot use the internal info pushed onto a bus error
+     * or address error frame when doing an RTE so don't put this info
+     * onto the stack or the stack will creep every time this happens.
+     */
+    frame->frameSize=3;
+#endif
+
+    /* throw away any frames in the list after this frame */
+    lastFrame = frame;
+
+    frame->sr = registers[(int) PS];
+    frame->pc = registers[(int) PC];
+
+    if (registers[(int) PS] & 0x2000)
+    { 
+        /* return to supervisor mode... */
+        return_to_super();
+    }
+    else
+    { /* return to user mode */
+        return_to_user();
+    }
+}
+
+int hex(ch)
+char ch;
+{
+  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+  return (0);
+}
+
+
+/* scan for the sequence $<data>#<checksum>     */
+void getpacket(buffer)
+char * buffer;
+{
+  unsigned char checksum;
+  unsigned char xmitcsum;
+  int  i;
+  int  count;
+  char ch;
+  
+  do {
+    /* wait around for the start character, ignore all other characters */
+    while ((ch = getDebugChar()) != '$'); 
+    checksum = 0;
+    count = 0;
+    
+    /* now, read until a # or end of buffer is found */
+    while (count < BUFMAX) {
+      ch = getDebugChar();
+      if (ch == '#') break;
+      checksum = checksum + ch;
+      buffer[count] = ch;
+      count = count + 1;
+      }
+    buffer[count] = 0;
+
+    if (ch == '#') {
+      xmitcsum = hex(getDebugChar()) << 4;
+      xmitcsum += hex(getDebugChar());
+      if ((remote_debug ) && (checksum != xmitcsum)) {
+        fprintf(stderr,"bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
+                                                    checksum,xmitcsum,buffer);
+      }
+      
+      if (checksum != xmitcsum) putDebugChar('-');  /* failed checksum */ 
+      else {
+        putDebugChar('+');  /* successful transfer */
+        /* if a sequence char is present, reply the sequence ID */
+        if (buffer[2] == ':') {
+           putDebugChar( buffer[0] );
+           putDebugChar( buffer[1] );
+           /* remove sequence chars from buffer */
+           count = strlen(buffer);
+           for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
+        } 
+      } 
+    } 
+  } while (checksum != xmitcsum);
+  
+}
+
+/* send the packet in buffer.  The host get's one chance to read it.  
+   This routine does not wait for a positive acknowledge.  */
+
+
+void putpacket(buffer)
+char * buffer;
+{
+  unsigned char checksum;
+  int  count;
+  char ch;
+  
+  /*  $<packet info>#<checksum>. */
+  do {
+  putDebugChar('$');
+  checksum = 0;
+  count    = 0;
+  
+  while (ch=buffer[count]) {
+    if (! putDebugChar(ch)) return;
+    checksum += ch;
+    count += 1;
+  }
+  
+  putDebugChar('#');
+  putDebugChar(hexchars[checksum >> 4]);
+  putDebugChar(hexchars[checksum % 16]);
+
+  } while (1 == 0);  /* (getDebugChar() != '+'); */
+  
+}
+
+static char  inbuffer[BUFMAX];
+static char  outbuffer[BUFMAX];
+static short error;
+
+
+void debug_error(format, parm)
+char * format;
+char * parm;
+{
+  if (remote_debug) fprintf(stderr,format,parm);
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+char* mem2hex(mem, buf, count)
+char* mem;
+char* buf;
+int   count;
+{
+      int i;
+      unsigned char ch;
+      for (i=0;i<count;i++) {
+          ch = *mem++;
+          *buf++ = hexchars[ch >> 4];
+          *buf++ = hexchars[ch % 16];
+      }
+      *buf = 0; 
+      return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+char* hex2mem(buf, mem, count)
+char* buf;
+char* mem;
+int   count;
+{
+      int i;
+      unsigned char ch;
+      for (i=0;i<count;i++) {
+          ch = hex(*buf++) << 4;
+          ch = ch + hex(*buf++);
+          *mem++ = ch;
+      }
+      return(mem);
+}
+
+/* a bus error has occurred, perform a longjmp
+   to return execution and allow handling of the error */
+
+void handle_buserror()
+{
+  longjmp(env,1);
+}
+
+/* this function takes the 68000 exception number and attempts to 
+   translate this number into a unix compatible signal value */
+int computeSignal( exceptionVector )
+int exceptionVector;
+{
+  int sigval;
+  switch (exceptionVector) {
+    case 2 : sigval = 10; break; /* bus error           */
+    case 3 : sigval = 10; break; /* address error       */
+    case 4 : sigval = 4;  break; /* illegal instruction */
+    case 5 : sigval = 8;  break; /* zero divide         */
+    case 6 : sigval = 16; break; /* chk instruction     */
+    case 7 : sigval = 16; break; /* trapv instruction   */
+    case 8 : sigval = 11; break; /* privilege violation */
+    case 9 : sigval = 5;  break; /* trace trap          */
+    case 10: sigval = 4;  break; /* line 1010 emulator  */
+    case 11: sigval = 4;  break; /* line 1111 emulator  */
+    case 31: sigval = 2;  break; /* interrupt           */
+    case 33: sigval = 5;  break; /* breakpoint          */
+    case 40: sigval = 8;  break; /* floating point err  */
+    case 48: sigval = 8;  break; /* floating point err  */
+    case 49: sigval = 8;  break; /* floating point err  */
+    case 50: sigval = 8;  break; /* zero divide         */
+    case 51: sigval = 8;  break; /* underflow           */
+    case 52: sigval = 8;  break; /* operand error       */
+    case 53: sigval = 8;  break; /* overflow            */
+    case 54: sigval = 8;  break; /* NAN                 */
+    default: 
+      sigval = 7;         /* "software generated"*/
+  }
+  return (sigval);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+void handle_exception(int exceptionVector)
+{
+  int    sigval;
+  int    addr, length;
+  char * ptr;
+  int    newPC;
+  Frame  *frame;
+  
+  if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n", 
+                           exceptionVector,
+                           registers[ PS ], 
+                           registers[ PC ]);
+
+  /* reply to host that an exception has occurred */
+  sigval = computeSignal( exceptionVector );
+  sprintf(outbuffer,"S%02x",sigval);
+  putpacket(outbuffer); 
+
+  while (1==1) { 
+    error = 0;
+    outbuffer[0] = 0;
+    getpacket(inbuffer);
+    switch (inbuffer[0]) {
+      case '?' : sprintf(outbuffer,"S%02x",sigval);
+                 break; 
+      case 'd' : remote_debug = !(remote_debug);  /* toggle debug flag */
+                 break; 
+      case 'g' : /* return the value of the CPU registers */
+                mem2hex((char*) registers, outbuffer, NUMREGBYTES);
+                break;
+      case 'G' : /* set the value of the CPU registers - return OK */
+                hex2mem(&inbuffer[1], (char*) registers, NUMREGBYTES);
+                strcpy(outbuffer,"OK");
+                break;
+      
+      /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+      case 'm' : 
+               if (setjmp(env) == 0) {
+                   exceptionHandler(2,handle_buserror); 
+
+                   if (2 == sscanf(&inbuffer[1],"%x,%x",&addr,&length)) {
+                     mem2hex((char*) addr, outbuffer, length);
+                   }
+                   else {
+                     strcpy(outbuffer,"E01");
+                     debug_error("malformed read memory command: %s",inbuffer);
+                     }     
+                } 
+               else {
+                 exceptionHandler(2,_catchException);   
+                 strcpy(outbuffer,"E03");
+                 debug_error("bus error");
+                 }     
+                
+               /* restore handler for bus error */
+               exceptionHandler(2,_catchException);   
+               break;
+      
+      /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+      case 'M' : 
+               if (setjmp(env) == 0) {
+                   exceptionHandler(2,handle_buserror); 
+
+                   if (2 == sscanf(&inbuffer[1],"%x,%x:",&addr,&length)) {
+                     ptr = strchr(inbuffer,':');
+                     ptr += 1; /* point 1 past the colon */
+                     hex2mem(ptr, (char*) addr, length);
+                     strcpy(outbuffer,"OK");
+                   }
+                   else {
+                     strcpy(outbuffer,"E02");
+                     debug_error("malformed write memory command: %s",inbuffer);
+                     }     
+                } 
+               else {
+                 exceptionHandler(2,_catchException);   
+                 strcpy(outbuffer,"E03");
+                 debug_error("bus error");
+                 }     
+                break;
+     
+     /* cAA..AA    Continue at address AA..AA(optional) */
+     /* sAA..AA   Step one instruction from AA..AA(optional) */
+     case 'c' : 
+     case 's' : 
+          /* try to read optional parameter, addr unchanged if no parm */
+          if (1 == sscanf(&inbuffer[1],"%x",&registers[ PC ])); 
+          newPC = registers[ PC];
+          
+          /* clear the trace bit */
+          registers[ PS ] &= 0x7fff;
+          
+          /* set the trace bit if we're stepping */
+          if (inbuffer[0] == 's') registers[ PS ] |= 0x8000;
+          
+          /*
+           * look for newPC in the linked list of exception frames.
+           * if it is found, use the old frame it.  otherwise,
+           * fake up a dummy frame in returnFromException().
+           */
+          if (remote_debug) printf("new pc = 0x%x\n",newPC);
+          frame = lastFrame;
+          while (frame)
+          {
+              if (remote_debug)
+                  printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+                         frame,frame->exceptionPC,
+                         frame->exceptionVector);
+              if (frame->exceptionPC == newPC) break;  /* bingo! a match */
+              /*
+               * for a breakpoint instruction, the saved pc may
+               * be off by two due to re-executing the instruction
+               * replaced by the trap instruction.  Check for this.
+               */
+              if ((frame->exceptionVector == 33) &&
+                  (frame->exceptionPC == (newPC+2))) break;
+              frame = frame->previous;
+          }
+          
+          /*
+           * If we found a match for the PC AND we are not returning
+           * as a result of a breakpoint (33),
+           * trace exception (9), nmi (31), jmp to
+           * the old exception handler as if this code never ran.
+           */
+          if (frame) 
+          {
+              if ((frame->exceptionVector != 9)  && 
+                  (frame->exceptionVector != 31) && 
+                  (frame->exceptionVector != 33))
+              { 
+                  /*
+                   * invoke the previous handler.
+                   */
+                  if (oldExceptionHook)
+                      (*oldExceptionHook) (frame->exceptionVector);
+                  newPC = registers[ PC ];    /* pc may have changed  */
+                  if (newPC != frame->exceptionPC)
+                  {
+                      if (remote_debug)
+                          printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+                                 frame,frame->exceptionPC,
+                                 frame->exceptionVector);
+                      /* dispose of this frame, we're skipping it (longjump?)*/
+                      lastFrame = frame->previous;
+                      frame = (Frame *) 0;
+                  }
+              }
+          }         
+
+          _returnFromException( frame );
+
+          break;
+          
+      /* kill the program */
+      case 'k' :  /* do nothing */
+                break;
+      } /* switch */ 
+    
+    /* reply to the request */
+    putpacket(outbuffer); 
+    }
+}
+
+
+/* this function is used to set up exception handlers for tracing and 
+   breakpoints */
+void set_debug_traps()
+{
+extern void _debug_level7();
+extern void remcomHandler();
+int exception;
+
+  for (exception = 2; exception <= 23; exception++)
+      exceptionHandler(exception,_catchException);   
+
+  /* level 7 interrupt              */
+  exceptionHandler(31,_debug_level7);    
+  
+  /* breakpoint exception (trap #1) */
+  exceptionHandler(33,_catchException);
+  
+  /* floating point error (trap #8) */
+  exceptionHandler(40,_catchException);
+  
+  /* 48 to 54 are floating point coprocessor errors */
+  for (exception = 48; exception <= 54; exception++)
+      exceptionHandler(exception,_catchException);   
+
+  if (oldExceptionHook != remcomHandler)
+  {
+      oldExceptionHook = exceptionHook;
+      exceptionHook    = remcomHandler;
+  }
+  
+  initialized = 1;
+
+  lastFrame = (Frame *) &frameStack[FRAMESIZE-1];
+  lastFrame->previous = (Frame *) 0;
+}
+
+/* This function will generate a breakpoint exception.  It is used at the
+   beginning of a program to sync up with a debugger and can be used
+   otherwise as a quick means to stop program execution and "break" into
+   the debugger. */
+   
+void breakpoint()
+{
+  if (initialized) BREAKPOINT();
+}
+
+@EOF
+
+chmod 444 remcom.c
+
+exit 0
+
diff --git a/gdb/remote-vx.c b/gdb/remote-vx.c
new file mode 100644 (file)
index 0000000..63028e2
--- /dev/null
@@ -0,0 +1,1775 @@
+/* Memory-access and commands for remote VxWorks processes, for GDB.
+   Copyright (C) 1990-1991  Free Software Foundation, Inc.
+   Contributed by Wind River Systems and Cygnus Support.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h"           /* for struct complaint */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#define free bogon_free                /* Sun claims "int free()" not void */
+#include <rpc/rpc.h>
+#undef free
+#include <sys/time.h>          /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include <ptrace.h>
+#include "xdr_ptrace.h"
+#include "xdr_ld.h"
+#include "xdr_rdb.h"
+#include "dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+extern value call_function_by_hand ();
+extern void symbol_file_command ();
+extern void add_syms_addr_command ();
+extern int stop_soon_quietly;          /* for wait_for_inferior */
+
+static int net_ptrace_clnt_call ();    /* Forward decl */
+static enum clnt_stat net_clnt_call ();        /* Forward decl */
+extern struct target_ops vx_ops, vx_run_ops;   /* Forward declaration */
+
+/* Saved name of target host and called function for "info files".
+   Both malloc'd.  */
+
+static char *vx_host;
+static char *vx_running;               /* Called function */
+
+/* Nonzero means target that is being debugged remotely has a floating
+   point processor.  */
+
+static int target_has_fp;
+
+/* Default error message when the network is forking up.  */
+
+static const char rpcerr[] = "network target debugging:  rpc error";
+
+CLIENT *pClient;         /* client used in net debugging */
+static int ptraceSock = RPC_ANYSOCK;
+
+enum clnt_stat net_clnt_call();
+static void parse_args ();
+
+static struct timeval rpcTimeout = { 10, 0 };
+
+static char *skip_white_space ();
+static char *find_white_space ();
+/* Tell the VxWorks target system to download a file.
+   The load addresses of the text, data, and bss segments are
+   stored in pTextAddr, pDataAddr, and *pBssAddr (respectively).
+   Returns 0 for success, -1 for failure.  */
+
+static int
+net_load (filename, pTextAddr, pDataAddr, pBssAddr)
+    char *filename;
+    CORE_ADDR *pTextAddr;
+    CORE_ADDR *pDataAddr;
+    CORE_ADDR *pBssAddr;
+    {
+    enum clnt_stat status;
+    struct ldfile ldstruct;
+    struct timeval load_timeout;
+    bzero ((char *) &ldstruct, sizeof (ldstruct));
+
+    /* We invoke clnt_call () here directly, instead of through
+       net_clnt_call (), because we need to set a large timeout value.
+       The load on the target side can take quite a while, easily
+       more than 10 seconds.  The user can kill this call by typing
+       CTRL-C if there really is a problem with the load.  
+       
+       Do not change the tv_sec value without checking -- select() imposes
+       a limit of 10**8 on it for no good reason that I can see...  */
+
+    load_timeout.tv_sec = 99999999;   /* A large number, effectively inf. */
+    load_timeout.tv_usec = 0;
+    status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
+                       &ldstruct, load_timeout);
+
+    if (status == RPC_SUCCESS)
+      {
+        if (*ldstruct.name == NULL)    /* load failed on VxWorks side */
+          return -1;
+       *pTextAddr = ldstruct.txt_addr;
+       *pDataAddr = ldstruct.data_addr;
+       *pBssAddr = ldstruct.bss_addr;
+       return 0;
+      }
+    else
+        return -1;
+    }
+      
+/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
+
+static int
+net_break (addr, procnum)
+    int addr;
+    u_long procnum;
+    {
+    enum clnt_stat status;
+    int break_status;
+    Rptrace ptrace_in;  /* XXX This is stupid.  It doesn't need to be a ptrace
+                           structure.  How about something smaller? */
+
+    bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+    break_status = 0;
+
+    ptrace_in.addr = addr;
+    ptrace_in.pid = inferior_pid;
+
+    status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
+                           &break_status);
+
+    if (status != RPC_SUCCESS)
+       return errno;
+
+    if (break_status == -1)
+      return ENOMEM;
+    return break_status;       /* probably (FIXME) zero */
+    }
+/* returns 0 if successful, errno otherwise */
+
+int
+vx_insert_breakpoint (addr)
+    int addr;
+    {
+    return net_break (addr, VX_BREAK_ADD);
+    }
+
+/* returns 0 if successful, errno otherwise */
+
+int
+vx_remove_breakpoint (addr)
+    int addr;
+    {
+    return net_break (addr, VX_BREAK_DELETE);
+    }
+
+/* Call a function on the VxWorks target system.
+   ARGS is a vector of values of arguments (NARGS of them).
+   FUNCTION is a value, the function to be called.
+   Returns a struct value * representing what the function returned.
+   May fail to return, if a breakpoint or signal is hit
+   during the execution of the function.  */
+
+#ifdef FIXME
+/* FIXME, function calls are really fried.  GO back to manual method. */
+value
+vx_call_function (function, nargs, args)
+     value function;
+     int nargs;
+     value *args;
+{
+  register CORE_ADDR sp;
+  register int i;
+  CORE_ADDR start_sp;
+  static REGISTER_TYPE dummy[] = CALL_DUMMY;
+  REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
+  CORE_ADDR old_sp;
+  struct type *value_type;
+  unsigned char struct_return;
+  CORE_ADDR struct_addr;
+  struct inferior_status inf_status;
+  struct cleanup *old_chain;
+  CORE_ADDR funaddr;
+  int using_gcc;
+
+  save_inferior_status (&inf_status, 1);
+  old_chain = make_cleanup (restore_inferior_status, &inf_status);
+
+  /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
+     (and POP_FRAME for restoring them).  (At least on most machines)
+     they are saved on the stack in the inferior.  */
+  PUSH_DUMMY_FRAME;
+
+  old_sp = sp = read_register (SP_REGNUM);
+
+#if 1 INNER_THAN 2             /* Stack grows down */
+  sp -= sizeof dummy;
+  start_sp = sp;
+#else                          /* Stack grows up */
+  start_sp = sp;
+  sp += sizeof dummy;
+#endif
+
+  funaddr = find_function_addr (function, &value_type);
+
+  {
+    struct block *b = block_for_pc (funaddr);
+    /* If compiled without -g, assume GCC.  */
+    using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
+  }
+
+  /* Are we returning a value using a structure return or a normal
+     value return? */
+
+  struct_return = using_struct_return (function, funaddr, value_type,
+                                      using_gcc);
+
+  /* Create a call sequence customized for this function
+     and the number of arguments for it.  */
+  bcopy (dummy, dummy1, sizeof dummy);
+  FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+                 value_type, using_gcc);
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+  write_memory (start_sp, dummy1, sizeof dummy);
+
+#else /* Not on stack.  */
+#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
+  /* Convex Unix prohibits executing in the stack segment. */
+  /* Hope there is empty room at the top of the text segment. */
+  {
+    static checked = 0;
+    if (!checked)
+      for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
+       if (read_memory_integer (start_sp, 1) != 0)
+         error ("text segment full -- no place to put call");
+    checked = 1;
+    sp = old_sp;
+    start_sp = text_end - sizeof dummy;
+    write_memory (start_sp, dummy1, sizeof dummy);
+  }
+#else /* After text_end.  */
+  {
+    int errcode;
+    sp = old_sp;
+    start_sp = text_end;
+    errcode = target_write_memory (start_sp, dummy1, sizeof dummy);
+    if (errcode != 0)
+      error ("Cannot write text segment -- call_function failed");
+  }
+#endif /* After text_end.  */
+#endif /* Not on stack.  */
+
+#ifdef STACK_ALIGN
+  /* If stack grows down, we must leave a hole at the top. */
+  {
+    int len = 0;
+
+    /* Reserve space for the return structure to be written on the
+       stack, if necessary */
+
+    if (struct_return)
+      len += TYPE_LENGTH (value_type);
+    
+    for (i = nargs - 1; i >= 0; i--)
+      len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
+#ifdef CALL_DUMMY_STACK_ADJUST
+    len += CALL_DUMMY_STACK_ADJUST;
+#endif
+#if 1 INNER_THAN 2
+    sp -= STACK_ALIGN (len) - len;
+#else
+    sp += STACK_ALIGN (len) - len;
+#endif
+  }
+#endif /* STACK_ALIGN */
+
+    /* Reserve space for the return structure to be written on the
+       stack, if necessary */
+
+    if (struct_return)
+      {
+#if 1 INNER_THAN 2
+       sp -= TYPE_LENGTH (value_type);
+       struct_addr = sp;
+#else
+       struct_addr = sp;
+       sp += TYPE_LENGTH (value_type);
+#endif
+      }
+
+#if defined (REG_STRUCT_HAS_ADDR)
+  {
+    /* This is a machine like the sparc, where we need to pass a pointer
+       to the structure, not the structure itself.  */
+    if (REG_STRUCT_HAS_ADDR (using_gcc))
+      for (i = nargs - 1; i >= 0; i--)
+       if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
+         {
+           CORE_ADDR addr;
+#if !(1 INNER_THAN 2)
+           /* The stack grows up, so the address of the thing we push
+              is the stack pointer before we push it.  */
+           addr = sp;
+#endif
+           /* Push the structure.  */
+           sp = value_push (sp, args[i]);
+#if 1 INNER_THAN 2
+           /* The stack grows down, so the address of the thing we push
+              is the stack pointer after we push it.  */
+           addr = sp;
+#endif
+           /* The value we're going to pass is the address of the thing
+              we just pushed.  */
+           args[i] = value_from_long (builtin_type_long, (LONGEST) addr);
+         }
+  }
+#endif /* REG_STRUCT_HAS_ADDR.  */
+
+#ifdef PUSH_ARGUMENTS
+  PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
+#else /* !PUSH_ARGUMENTS */
+  for (i = nargs - 1; i >= 0; i--)
+    sp = value_arg_push (sp, args[i]);
+#endif /* !PUSH_ARGUMENTS */
+
+#ifdef CALL_DUMMY_STACK_ADJUST
+#if 1 INNER_THAN 2
+  sp -= CALL_DUMMY_STACK_ADJUST;
+#else
+  sp += CALL_DUMMY_STACK_ADJUST;
+#endif
+#endif /* CALL_DUMMY_STACK_ADJUST */
+
+  /* Store the address at which the structure is supposed to be
+     written.  Note that this (and the code which reserved the space
+     above) assumes that gcc was used to compile this function.  Since
+     it doesn't cost us anything but space and if the function is pcc
+     it will ignore this value, we will make that assumption.
+
+     Also note that on some machines (like the sparc) pcc uses a 
+     convention like gcc's.  */
+
+  if (struct_return)
+    STORE_STRUCT_RETURN (struct_addr, sp);
+
+  /* Write the stack pointer.  This is here because the statements above
+     might fool with it.  On SPARC, this write also stores the register
+     window into the right place in the new stack frame, which otherwise
+     wouldn't happen.  (See write_inferior_registers in sparc-xdep.c.)  */
+  write_register (SP_REGNUM, sp);
+
+  /* Figure out the value returned by the function.  */
+  {
+    char retbuf[REGISTER_BYTES];
+
+    /* Execute the stack dummy routine, calling FUNCTION.
+       When it is done, discard the empty frame
+       after storing the contents of all regs into retbuf.  */
+    run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
+
+    do_cleanups (old_chain);
+
+    return value_being_returned (value_type, retbuf, struct_return);
+  }
+}
+/* should return a value of some sort */
+value
+vx_call_function (funcAddr, nargs, args, valueType)
+    char *funcAddr;
+    int nargs;
+    value *args;
+    struct type * valueType;
+{
+    int i;
+    func_call funcInfo;
+    arg_value *argValue;
+    enum clnt_stat status;
+    register int len;
+    arg_value funcReturn;
+    value gdbValue;
+
+    argValue = (arg_value *) xmalloc (nargs * sizeof (arg_value));
+
+    bzero (argValue, nargs * sizeof (arg_value));
+    bzero (&funcReturn, sizeof (funcReturn));
+
+    for (i = nargs - 1; i >= 0; i--)
+       {
+       len = TYPE_LENGTH (VALUE_TYPE (args [i]));
+
+       switch (TYPE_CODE (VALUE_TYPE (args[i])))
+           {
+           /* XXX put other types here.  Where's CHAR, etc??? */
+
+           case TYPE_CODE_FLT:
+               argValue[i].type = T_FLOAT;
+               break;
+           case TYPE_CODE_INT:
+           case TYPE_CODE_PTR:
+           case TYPE_CODE_ENUM:
+           case TYPE_CODE_FUNC:
+               argValue[i].type = T_INT;
+               break;
+
+           case TYPE_CODE_UNDEF:
+           case TYPE_CODE_ARRAY:
+           case TYPE_CODE_STRUCT:
+           case TYPE_CODE_UNION:
+           case TYPE_CODE_VOID:
+           case TYPE_CODE_SET:
+           case TYPE_CODE_RANGE:
+           case TYPE_CODE_PASCAL_ARRAY:
+           case TYPE_CODE_MEMBER:          /* C++ */
+           case TYPE_CODE_METHOD:          /* C++ */
+           case TYPE_CODE_REF:             /* C++ */
+           default:
+               error ("No corresponding VxWorks type for %d.  CHECK IT OUT!!!\n",
+                       TYPE_CODE(VALUE_TYPE(args[i])));
+           } /* switch */
+       if (TYPE_CODE(VALUE_TYPE(args[i])) == TYPE_CODE_FUNC)
+           argValue[i].arg_value_u.v_int = VALUE_ADDRESS(args[i]);
+       else
+           bcopy (VALUE_CONTENTS (args[i]), (char *) &argValue[i].arg_value_u,
+                  len);
+       }
+
+    /* XXX what should the type of this function addr be?
+     * XXX Both in gdb and vxWorks
+     */
+    funcInfo.func_addr = (int) funcAddr;
+    funcInfo.args.args_len = nargs;
+    funcInfo.args.args_val = argValue;
+
+    status = net_clnt_call (VX_CALL_FUNC, xdr_func_call, (char *) &funcInfo,
+                           xdr_arg_value, &funcReturn);
+
+    free ((char *) argValue);
+
+    if (status == RPC_SUCCESS)
+       {
+       /* XXX this assumes that vxWorks ALWAYS returns an int, and that
+        * XXX gdb isn't expecting anything more
+        */
+
+       /*******************
+       if (funcReturn.type == T_UNKNOWN)
+           return YYYXXX...;
+       *******************/
+       gdbValue = allocate_value (valueType);
+       bcopy (&funcReturn.arg_value_u.v_int, VALUE_CONTENTS (gdbValue),
+               sizeof (int));
+        return gdbValue;
+       }
+    else 
+       error (rpcerr);
+    }
+#endif /* FIXME */
+/* Start an inferior process and sets inferior_pid to its pid.
+   EXEC_FILE is the file to run.
+   ALLARGS is a string containing the arguments to the program.
+   ENV is the environment vector to pass.
+   Returns process id.  Errors reported with error().
+   On VxWorks, we ignore exec_file.  */
+void
+vx_create_inferior (exec_file, args, env)
+     char *exec_file;
+     char *args;
+     char **env;
+{
+  enum clnt_stat status;
+  arg_array passArgs;
+  TASK_START taskStart;
+
+  bzero ((char *) &passArgs, sizeof (passArgs));
+  bzero ((char *) &taskStart, sizeof (taskStart));
+
+  /* parse arguments, put them in passArgs */
+
+  parse_args (args, &passArgs);
+
+  if (passArgs.arg_array_len == 0)
+    error ("You must specify a function name to run, and arguments if any");
+
+  status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
+                         xdr_TASK_START, &taskStart);
+
+  if ((status != RPC_SUCCESS) || (taskStart.status == -1))
+    error ("Can't create process on remote target machine");
+
+  /* Save the name of the running function */
+  vx_running = savestring (passArgs.arg_array_val[0],
+                          strlen (passArgs.arg_array_val[0]));
+
+#ifdef CREATE_INFERIOR_HOOK
+  CREATE_INFERIOR_HOOK (pid);
+#endif  
+
+  push_target (&vx_run_ops);
+  inferior_pid = taskStart.pid;
+
+#if defined (START_INFERIOR_HOOK)
+  START_INFERIOR_HOOK ();
+#endif
+
+  /* We will get a trace trap after one instruction.
+     Insert breakpoints and continue.  */
+
+  init_wait_for_inferior ();
+
+  /* Set up the "saved terminal modes" of the inferior
+     based on what modes we are starting it with.  */
+  target_terminal_init ();
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  /* remote_start(args); */
+  /* trap_expected = 0; */
+  stop_soon_quietly = 1;
+  wait_for_inferior ();                /* Get the task spawn event */
+  stop_soon_quietly = 0;
+
+  /* insert_step_breakpoint ();  FIXME, do we need this?  */
+  proceed(-1, -1, 0);
+}
+
+/* Fill ARGSTRUCT in argc/argv form with the arguments from the
+   argument string ARGSTRING.  */
+
+static void
+parse_args (arg_string, arg_struct)
+     register char *arg_string;
+     arg_array *arg_struct;
+{
+  register int arg_count = 0;  /* number of arguments */
+  register int arg_index = 0;
+  register char *p0;
+  bzero ((char *) arg_struct, sizeof (arg_array));
+  /* first count how many arguments there are */
+
+  p0 = arg_string;
+  while (*p0 != '\0')
+    {
+      if (*(p0 = skip_white_space (p0)) == '\0')
+       break;
+      p0 = find_white_space (p0);
+      arg_count++;
+    }
+
+  arg_struct->arg_array_len = arg_count;
+  arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
+                                                * sizeof (char *));
+
+  /* now copy argument strings into arg_struct.  */
+
+  while (*(arg_string = skip_white_space (arg_string)))
+    {
+      p0 = find_white_space (arg_string);
+      arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
+                                                          p0 - arg_string);
+      arg_string = p0;
+    }
+
+  arg_struct->arg_array_val[arg_count] = NULL;
+}
+
+/* Advance a string pointer across whitespace and return a pointer
+   to the first non-white character.  */
+
+static char *
+skip_white_space (p)
+     register char *p;
+{
+  while (*p == ' ' || *p == '\t')
+    p++;
+  return p;
+}
+    
+/* Search for the first unquoted whitespace character in a string.
+   Returns a pointer to the character, or to the null terminator
+   if no whitespace is found.  */
+
+static char *
+find_white_space (p)
+     register char *p;
+{
+  register int c;
+
+  while ((c = *p) != ' ' && c != '\t' && c)
+    {
+      if (c == '\'' || c == '"')
+       {
+         while (*++p != c && *p)
+           {
+             if (*p == '\\')
+               p++;
+           }
+         if (!*p)
+           break;
+       }
+      p++;
+    }
+  return p;
+}
+    
+/* Poll the VxWorks target system for an event related
+   to the debugged task.
+   Returns -1 if remote wait failed, task status otherwise.  */
+
+int
+net_wait (pEvent)
+    RDB_EVENT *pEvent;
+{
+    int pid;
+    enum clnt_stat status;
+
+    bzero ((char *) pEvent, sizeof (RDB_EVENT));
+
+    pid = inferior_pid;
+    status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, pEvent);
+
+    return (status == RPC_SUCCESS)? pEvent->status: -1;
+}
+    
+/* Suspend the remote task.
+   Returns -1 if suspend fails on target system, 0 otherwise.  */
+
+int
+net_quit ()
+{
+    int pid;
+    int quit_status;
+    enum clnt_stat status;
+
+    quit_status = 0;
+
+    /* don't let rdbTask suspend itself by passing a pid of 0 */
+
+    if ((pid = inferior_pid) == 0)
+       return -1;
+
+    status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
+                           &quit_status);
+
+    return (status == RPC_SUCCESS)? quit_status: -1;
+}
+
+/* Read a register or registers from the remote system.  */
+
+int
+vx_read_register (regno)
+     int regno;
+{
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+  /* FIXME, eventually only get the ones we need.  */
+  registers_fetched ();
+  
+  ptrace_in.pid = inferior_pid;
+  ptrace_out.info.more_data = (caddr_t) &inferior_registers;
+  status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
+  if (status)
+    error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      return -1;
+    }
+  
+#ifdef I80960
+
+      bcopy ((char *) inferior_registers.r_lreg,
+            &registers[REGISTER_BYTE (R0_REGNUM)], 16 * sizeof (int));
+      bcopy ((char *) inferior_registers.r_greg,
+            &registers[REGISTER_BYTE (G0_REGNUM)], 16 * sizeof (int));
+
+      /* Don't assume that a location in registers[] is properly aligned.  */
+
+      bcopy ((char *) &inferior_registers.r_pcw,
+            &registers[REGISTER_BYTE (PCW_REGNUM)], sizeof (int));
+      bcopy ((char *) &inferior_registers.r_acw,
+            &registers[REGISTER_BYTE (ACW_REGNUM)], sizeof (int));
+      bcopy ((char *) &inferior_registers.r_lreg[2],   /* r2 (RIP) -> IP */
+            &registers[REGISTER_BYTE (IP_REGNUM)], sizeof (int));
+      bcopy ((char *) &inferior_registers.r_tcw,
+            &registers[REGISTER_BYTE (TCW_REGNUM)], sizeof (int));
+
+      /* If the target has floating point registers, fetch them.
+        Otherwise, zero the floating point register values in
+        registers[] for good measure, even though we might not
+        need to.  */
+
+      if (target_has_fp)
+       {
+         ptrace_in.pid = inferior_pid;
+         ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
+         status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
+         if (status)
+           error (rpcerr);
+         if (ptrace_out.status == -1)
+           {
+             errno = ptrace_out.errno;
+             return -1;
+           }
+         
+         bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+                REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+       }
+      else
+       {
+         bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
+                REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+       }
+
+#else  /* not 960, thus must be 68000:  FIXME!  */
+
+  bcopy (&inferior_registers, registers, 16 * 4);
+  *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+  *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+
+  if (target_has_fp)
+    {
+      ptrace_in.pid = inferior_pid;
+      ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
+      status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
+      if (status)
+       error (rpcerr);
+      if (ptrace_out.status == -1)
+       {
+         errno = ptrace_out.errno;
+         return -1;
+       }
+      
+      bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+            sizeof inferior_fp_registers.fps_regs);
+      bcopy (&inferior_fp_registers.fps_control,
+        &registers[REGISTER_BYTE (FPC_REGNUM)],
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+    }
+  else
+    {
+      bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
+            sizeof inferior_fp_registers.fps_regs);
+      bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+    }
+#endif  /* various architectures */
+
+  return 0;
+}
+
+/* Prepare to store registers.  Since we will store all of them,
+   read out their current values now.  */
+
+void
+vx_prepare_to_store ()
+{
+  vx_read_register (-1);
+}
+
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+   /* FIXME, look at REGNO to save time here */
+
+vx_write_register (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  extern char registers[];
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+#ifdef I80960
+
+  bcopy (&registers[REGISTER_BYTE (R0_REGNUM)],
+        (char *) inferior_registers.r_lreg, 16 * sizeof (int));
+  bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
+        (char *) inferior_registers.r_greg, 16 * sizeof (int));
+
+  /* Don't assume that a location in registers[] is properly aligned.  */
+
+  bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)],
+        (char *) &inferior_registers.r_pcw, sizeof (int));
+  bcopy (&registers[REGISTER_BYTE (ACW_REGNUM)],
+        (char *) &inferior_registers.r_acw, sizeof (int));
+  bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)],
+        (char *) &inferior_registers.r_tcw, sizeof (int));
+
+#else  /* not 960 -- assume 68k -- FIXME */
+
+  bcopy (registers, &inferior_registers, 16 * 4);
+  inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+  inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+
+#endif  /* Different register sets */
+
+  ptrace_in.pid = inferior_pid;
+  ptrace_in.info.ttype     = REGS;
+  ptrace_in.info.more_data = (caddr_t) &inferior_registers;
+
+  /* XXX change second param to be a proc number */
+  status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
+  if (status)
+      error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      return -1;
+    }
+
+  /* Store floating point registers if the target has them.  */
+
+  if (target_has_fp)
+    {
+#ifdef I80960
+
+      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+            sizeof inferior_fp_registers.fps_regs);
+
+#else  /* not 960 -- assume 68k -- FIXME */
+
+      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+            sizeof inferior_fp_registers.fps_regs);
+      bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+        &inferior_fp_registers.fps_control,
+         sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+#endif  /* Different register sets */
+
+      ptrace_in.pid = inferior_pid;
+      ptrace_in.info.ttype     = FPREGS;
+      ptrace_in.info.more_data = (caddr_t) &inferior_fp_registers;
+
+      status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in, &ptrace_out);
+      if (status)
+         error (rpcerr);
+      if (ptrace_out.status == -1)
+       {
+         errno = ptrace_out.errno;
+         return -1;
+       }
+    }
+  return 0;
+}
+
+/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.  WRITE is true if writing to the
+   inferior.
+   Result is the number of bytes written or read (zero if error).  The
+   protocol allows us to return a negative count, indicating that we can't
+   handle the current address but can handle one N bytes further, but
+   vxworks doesn't give us that information.  */
+
+int
+vx_xfer_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+  C_bytes data;
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+  ptrace_in.pid = inferior_pid;                /* XXX pid unnecessary for READDATA */
+  ptrace_in.addr = (int) memaddr;      /* Where from */
+  ptrace_in.data = len;                        /* How many bytes */
+
+  if (write)
+    {
+      ptrace_in.info.ttype     = DATA;
+      ptrace_in.info.more_data = (caddr_t) &data;
+
+      data.bytes = (caddr_t) myaddr;   /* Where from */
+      data.len   = len;                        /* How many bytes (again, for XDR) */
+
+      /* XXX change second param to be a proc number */
+      status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in, &ptrace_out);
+    }
+  else
+    {
+      ptrace_out.info.more_data = (caddr_t) &data;
+      data.bytes = myaddr;             /* Where to */
+      data.len   = len;                        /* How many (again, for XDR) */
+
+      /* XXX change second param to be a proc number */
+      status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
+    }
+
+  if (status)
+      error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      return 0;                /* No bytes moved */
+    }
+  return len;          /* Moved *all* the bytes */
+}
+
+void
+vx_files_info ()
+{
+  printf ("\tAttached to host `%s'", vx_host);
+  printf (", which has %sfloating point", target_has_fp? "": "no ");
+  printf (".\n");
+}
+
+void
+vx_run_files_info ()
+{
+  printf ("\tRunning %s VxWorks process 0x%x", 
+         vx_running? "child": "attached",
+         inferior_pid);
+  if (vx_running)
+    printf (", function `%s'", vx_running);
+  printf(".\n");
+}
+
+void
+vx_resume (step, siggnal)
+     int step;
+     int siggnal;
+{
+  int status;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+
+  if (siggnal != 0 && siggnal != stop_signal)
+    error ("Cannot send signals to VxWorks processes");
+
+  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+  ptrace_in.pid = inferior_pid;
+  ptrace_in.addr = 1;  /* Target side insists on this, or it panics.  */
+
+  /* XXX change second param to be a proc number */
+  status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
+                                &ptrace_in, &ptrace_out);
+  if (status)
+      error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      perror_with_name ("Resuming remote process");
+    }
+}
+
+void
+vx_mourn_inferior ()
+{
+  pop_target ();               /* Pop back to no-child state */
+  generic_mourn_inferior ();
+}
+
+\f
+/* This function allows the addition of incrementally linked object files.  */
+
+void
+vx_load_command (arg_string, from_tty)
+     char* arg_string;
+     int from_tty;
+{
+  CORE_ADDR text_addr;
+  CORE_ADDR data_addr;
+  CORE_ADDR bss_addr;
+  
+  if (arg_string == 0)
+    error ("The load command takes a file name");
+
+  arg_string = tilde_expand (arg_string);
+  make_cleanup (free, arg_string);
+
+  dont_repeat ();
+
+  QUIT;
+  immediate_quit++;
+  if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
+    error ("Load failed on target machine");
+  immediate_quit--;
+
+  /* FIXME, for now we ignore data_addr and bss_addr.  */
+  symbol_file_add (arg_string, from_tty, text_addr, 0);
+}
+
+#ifdef FIXME  /* Not ready for prime time */
+/* Single step the target program at the source or machine level.
+   Takes an error exit if rpc fails.
+   Returns -1 if remote single-step operation fails, else 0.  */
+
+static int
+net_step ()
+{
+  enum clnt_stat status;
+  int step_status;
+  SOURCE_STEP source_step;
+
+  source_step.taskId = inferior_pid;
+
+  if (step_range_end)
+    {
+      source_step.startAddr = step_range_start;
+      source_step.endAddr = step_range_end;
+    }
+  else
+    {
+      source_step.startAddr = 0;
+      source_step.endAddr = 0;
+    }
+
+  status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
+                         xdr_int, &step_status);
+
+  if (status == RPC_SUCCESS)
+    return step_status;
+  else 
+    error (rpcerr);
+}
+#endif
+
+/* Emulate ptrace using RPC calls to the VxWorks target system.
+   Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise.  */
+
+static int
+net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
+    enum ptracereq request;
+    Rptrace *pPtraceIn;
+    Ptrace_return *pPtraceOut;
+{
+  enum clnt_stat status;
+
+  status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
+                         pPtraceOut);
+
+  if (status != RPC_SUCCESS)
+      return -1;
+
+  return 0;
+}
+
+/* Query the target for the name of the file from which VxWorks was
+   booted.  pBootFile is the address of a pointer to the buffer to
+   receive the file name; if the pointer pointed to by pBootFile is 
+   NULL, memory for the buffer will be allocated by XDR.
+   Returns -1 if rpc failed, 0 otherwise.  */
+
+int
+net_get_boot_file (pBootFile)
+     char **pBootFile;
+{
+  enum clnt_stat status;
+
+  status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
+                         xdr_wrapstring, pBootFile);
+  return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Fetch a list of loaded object modules from the VxWorks target.
+   Returns -1 if rpc failed, 0 otherwise
+   There's no way to check if the returned loadTable is correct.
+   VxWorks doesn't check it.  */
+
+int
+net_get_symbols (pLoadTable)
+     ldtabl *pLoadTable;               /* return pointer to ldtabl here */
+{
+  enum clnt_stat status;
+
+  bzero ((char *) pLoadTable, sizeof (struct ldtabl));
+
+  status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
+  return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Look up a symbol in the VxWorks target's symbol table.
+   Returns status of symbol read on target side (0=success, -1=fail)
+   Returns -1 and complain()s if rpc fails.  */
+
+struct complaint cant_contact_target =
+  {"Lost contact with VxWorks target", 0, 0};
+
+int
+vx_lookup_symbol (name, pAddr)
+     char *name;               /* symbol name */
+     CORE_ADDR *pAddr;
+{
+  enum clnt_stat status;
+  SYMBOL_ADDR symbolAddr;
+
+  *pAddr = 0;
+  bzero ((char *) &symbolAddr, sizeof (symbolAddr));
+
+  status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
+                         xdr_SYMBOL_ADDR, &symbolAddr);
+  if (status != RPC_SUCCESS) {
+      complain (&cant_contact_target, 0);
+      return -1;
+  }
+
+  *pAddr = symbolAddr.addr;
+  return symbolAddr.status;
+}
+
+/* Check to see if the VxWorks target has a floating point coprocessor.
+   Returns 1 if target has floating point processor, 0 otherwise.
+   Calls error() if rpc fails.  */
+
+int
+net_check_for_fp ()
+{
+  enum clnt_stat status;
+  bool_t fp = 0;       /* true if fp processor is present on target board */
+
+  status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
+  if (status != RPC_SUCCESS)
+      error (rpcerr);
+
+   return (int) fp;
+}
+
+/* Establish an RPC connection with the VxWorks target system.
+   Calls error () if unable to establish connection.  */
+
+void
+net_connect (host)
+     char *host;
+{
+  struct sockaddr_in destAddr;
+  struct hostent *destHost;
+
+  /* get the internet address for the given host */
+
+  if ((destHost = (struct hostent *) gethostbyname (host)) == NULL)
+      error ("Invalid hostname.  Couldn't find remote host address.");
+
+  bzero (&destAddr, sizeof (destAddr));
+
+  destAddr.sin_addr.s_addr = * (u_long *) destHost->h_addr;
+  destAddr.sin_family      = AF_INET;
+  destAddr.sin_port        = 0;        /* set to actual port that remote
+                                  ptrace is listening on.  */
+
+  /* Create a tcp client transport on which to issue
+     calls to the remote ptrace server.  */
+
+  ptraceSock = RPC_ANYSOCK;
+  pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
+  /* FIXME, here is where we deal with different version numbers of the proto */
+  
+  if (pClient == NULL)
+    {
+      clnt_pcreateerror ("\tnet_connect");
+      error ("Couldn't connect to remote target.");
+    }
+}
+\f
+/* Sleep for the specified number of milliseconds 
+ * (assumed to be less than 1000).
+ * If select () is interrupted, returns immediately;
+ * takes an error exit if select () fails for some other reason.
+ */
+
+static void
+sleep_ms (ms)
+     long ms;
+{
+  struct timeval select_timeout;
+  int status;
+
+  select_timeout.tv_sec = 0;
+  select_timeout.tv_usec = ms * 1000;
+
+  status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
+
+  if (status < 0 && errno != EINTR)
+    perror_with_name ("select");
+}
+
+/* Wait for control to return from inferior to debugger.
+   If inferior gets a signal, we may decide to start it up again
+   instead of returning.  That is why there is a loop in this function.
+   When this function actually returns it means the inferior
+   should be left stopped and GDB should read more commands.  */
+
+/* For network debugging with VxWorks.
+ * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
+ * so vx_wait() receives this information directly from
+ * VxWorks instead of trying to figure out what happenned via a wait() call.
+ */
+
+static int
+vx_wait (status)
+     int *status;
+{
+  register int pid;
+  WAITTYPE w;
+  RDB_EVENT rdbEvent;
+  int quit_failed;
+
+  do
+    {
+      /* If CTRL-C is hit during this loop,
+        suspend the inferior process.  */
+
+      quit_failed = 0;
+      if (quit_flag)
+       {
+         quit_failed = (net_quit () == -1);
+         quit_flag = 0;
+       }
+
+      /* If a net_quit () or net_wait () call has failed,
+        allow the user to break the connection with the target.
+        We can't simply error () out of this loop, since the 
+        data structures representing the state of the inferior
+        are in an inconsistent state.  */
+
+      if (quit_failed || net_wait (&rdbEvent) == -1)
+       {
+         terminal_ours ();
+         if (query ("Can't %s.  Disconnect from target system? ",
+                    (quit_failed) ? "suspend remote task"
+                                  : "get status of remote task"))
+           {
+             target_mourn_inferior();
+             error ("Use the \"target\" command to reconnect.");
+           }
+         else
+           {
+             terminal_inferior ();
+             continue;
+           }
+       }
+      
+      pid = rdbEvent.taskId;
+      if (pid == 0)
+       {
+         sleep_ms (200);       /* FIXME Don't kill the network too badly */
+       }
+      else if (pid != inferior_pid)
+       fatal ("Bad pid for debugged task: 0x%x\n", pid);
+    } while (pid == 0);
+
+  /* FIXME, eventually do more then SIGTRAP on everything...  */
+  switch (rdbEvent.eventType)
+    {
+    case EVENT_EXIT:
+      WSETEXIT (w, 0);
+      /* FIXME is it possible to distinguish between a
+        XXX   normal vs abnormal exit in VxWorks? */
+      break;
+
+    case EVENT_START:          /* Task was just started. */
+      WSETSTOP (w, SIGTRAP);
+      break;
+
+    case EVENT_STOP:
+      WSETSTOP (w, SIGTRAP);
+      /* XXX was it stopped by a signal?  act accordingly */
+      break;
+
+    case EVENT_BREAK:          /* Breakpoint was hit. */
+      WSETSTOP (w, SIGTRAP);
+      break;
+
+    case EVENT_SUSPEND:                /* Task was suspended, probably by ^C. */
+      WSETSTOP (w, SIGINT);
+      break;
+
+    case EVENT_BUS_ERR:                /* Task made evil nasty reference. */
+      WSETSTOP (w, SIGBUS);
+      break;
+
+    case EVENT_ZERO_DIV:       /* Division by zero */
+      WSETSTOP (w, SIGFPE);    /* Like Unix, call it a float exception. */
+
+    case EVENT_SIGNAL:
+      /* The target is not running Unix, and its
+        faults/traces do not map nicely into Unix signals.
+        Make sure they do not get confused with Unix signals
+        by numbering them with values higher than the highest
+        legal Unix signal.  code in the arch-dependent PRINT_RANDOM_SIGNAL
+        routine will interpret the value for wait_for_inferior.  */
+      WSETSTOP (w, rdbEvent.sigType + NSIG);
+      break;
+    } /* switch */
+  *status = *(int *)&w;                /* Grumble union wait crap Grumble */
+  return pid;
+}
+\f
+static int
+symbol_stub (arg)
+     int arg;
+{
+  char *bootFile = (char *)arg;
+  symbol_file_command (bootFile, 0);
+  return 1;
+}
+
+static int
+add_symbol_stub (arg)
+     int arg;
+{
+  struct ldfile *pLoadFile = (struct ldfile *)arg;
+
+  printf("\t%s: ", pLoadFile->name);
+  symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
+  printf ("ok\n");
+  return 1;
+}
+/* Target command for VxWorks target systems.
+
+   Used in vxgdb.  Takes the name of a remote target machine
+   running vxWorks and connects to it to initialize remote network
+   debugging.  */
+
+static void
+vx_open (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  extern int close ();
+  char *bootFile;
+  extern char *source_path;
+  struct ldtabl loadTable;
+  struct ldfile *pLoadFile;
+  int i;
+  extern CLIENT *pClient;
+
+  if (!args)
+    error_no_arg ("target machine name");
+
+  unpush_target (&vx_ops);
+  printf ("Attaching remote machine across net...\n");
+  fflush (stdout);
+
+  /* Allow the user to kill the connect attempt by typing ^C.
+     Wait until the call to target_has_fp () completes before
+     disallowing an immediate quit, since even if net_connect ()
+     is successful, the remote debug server might be hung.  */
+
+  immediate_quit++;
+
+  net_connect (args);
+  target_has_fp = net_check_for_fp ();
+  printf_filtered ("Connected to %s.\n", args);
+
+  immediate_quit--;
+
+  push_target (&vx_ops);
+
+  /* Save a copy of the target host's name.  */
+  vx_host = savestring (args, strlen (args));
+
+  /* Find out the name of the file from which the target was booted
+     and load its symbol table.  */
+
+  printf_filtered ("Looking in Unix path for all loaded modules:\n");
+  bootFile = NULL;
+  if (!net_get_boot_file (&bootFile))
+    {
+      if (*bootFile) {
+       printf_filtered ("\t%s: ", bootFile);
+       if (catch_errors (symbol_stub, (int)bootFile,
+               "Error reading symbols from boot file"))
+         puts_filtered ("ok\n");
+      } else if (from_tty)
+       printf ("VxWorks kernel symbols not loaded.\n");
+    }
+  else
+    error ("Can't retrieve boot file name from target machine.");
+
+  clnt_freeres (pClient, xdr_wrapstring, &bootFile);
+
+  if (net_get_symbols (&loadTable) != 0)
+    error ("Can't read loaded modules from target machine");
+
+  i = 0-1;
+  while (++i < loadTable.tbl_size)
+    {
+      QUIT;    /* FIXME, avoids clnt_freeres below:  mem leak */
+      pLoadFile = &loadTable.tbl_ent [i];
+#ifdef WRS_ORIG
+  {
+    register int desc;
+    struct cleanup *old_chain;
+    char *fullname = NULL;
+
+    desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
+    if (desc < 0)
+       perror_with_name (pLoadFile->name);
+    old_chain = make_cleanup (close, desc);
+    add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
+                     pLoadFile->bss_addr);
+    do_cleanups (old_chain);
+  }
+#else
+      /* Botches, FIXME:
+        (1)  Searches the PATH, not the source path.
+        (2)  data and bss are assumed to be at the usual offsets from text.  */
+      catch_errors (add_symbol_stub, (int)pLoadFile, (char *)0);
+#endif
+    }
+  printf_filtered ("Done.\n");
+
+  clnt_freeres (pClient, xdr_ldtabl, &loadTable);
+}
+\f
+/* attach_command --
+   takes a task started up outside of gdb and ``attaches'' to it.
+   This stops it cold in its tracks and allows us to start tracing it.  */
+
+static void
+vx_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  int pid;
+  char *cptr = 0;
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+  int status;
+
+  dont_repeat();
+
+  if (!args)
+    error_no_arg ("process-id to attach");
+
+  pid = strtol (args, &cptr, 0);
+  if ((cptr == args) || (*cptr != '\0'))
+    error ("Invalid process-id -- give a single number in decimal or 0xhex");
+
+  if (from_tty)
+      printf ("Attaching pid 0x%x.\n", pid);
+
+  bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
+  bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+  ptrace_in.pid = pid;
+
+  status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
+  if (status == -1)
+    error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      perror_with_name ("Attaching remote process");
+    }
+
+  /* It worked... */
+  push_target (&vx_run_ops);
+  inferior_pid = pid;
+  vx_running = 0;
+
+#if defined (START_INFERIOR_HOOK)
+  START_INFERIOR_HOOK ();
+#endif
+
+  mark_breakpoints_out ();
+
+  /* Set up the "saved terminal modes" of the inferior
+     based on what modes we are starting it with.  */
+  target_terminal_init ();
+
+  /* Install inferior's terminal modes.  */
+  target_terminal_inferior ();
+
+  /* We will get a task spawn event immediately.  */
+  init_wait_for_inferior ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  wait_for_inferior ();
+  stop_soon_quietly = 0;
+  normal_stop ();
+}
+
+
+/* detach_command --
+   takes a program previously attached to and detaches it.
+   The program resumes execution and will no longer stop
+   on signals, etc.  We better not have left any breakpoints
+   in the program or it'll die when it hits one.  For this
+   to work, it may be necessary for the process to have been
+   previously attached.  It *might* work if the program was
+   started via the normal ptrace (PTRACE_TRACEME).  */
+
+static void
+vx_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+  int signal = 0;
+  int status;
+
+  if (args)
+    error ("Argument given to VxWorks \"detach\".");
+
+  if (from_tty)
+      printf ("Detaching pid 0x%x.\n", inferior_pid);
+
+  if (args)            /* FIXME, should be possible to leave suspended */
+    signal = atoi (args);
+  
+  bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
+  bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+  ptrace_in.pid = inferior_pid;
+
+  status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
+  if (status == -1)
+    error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      perror_with_name ("Detaching VxWorks process");
+    }
+
+  inferior_pid = 0;
+  pop_target ();       /* go back to non-executing VxWorks connection */
+}
+
+/* vx_kill -- takes a running task and wipes it out.  */
+
+static void
+vx_kill (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  Rptrace ptrace_in;
+  Ptrace_return ptrace_out;
+  int status;
+
+  if (args)
+    error ("Argument given to VxWorks \"kill\".");
+
+  if (from_tty)
+      printf ("Killing pid 0x%x.\n", inferior_pid);
+
+  bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
+  bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+  ptrace_in.pid = inferior_pid;
+
+  status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
+  if (status == -1)
+    error (rpcerr);
+  if (ptrace_out.status == -1)
+    {
+      errno = ptrace_out.errno;
+      perror_with_name ("Killing VxWorks process");
+    }
+
+  /* If it gives good status, the process is *gone*, no events remain.  */
+  inferior_pid = 0;
+  pop_target ();       /* go back to non-executing VxWorks connection */
+}
+
+/* Clean up from the VxWorks process target as it goes away.  */
+
+void
+vx_proc_close (quitting)
+     int quitting;
+{
+  inferior_pid = 0;            /* No longer have a process.  */
+  if (vx_running)
+    free (vx_running);
+  vx_running = 0;
+}
+\f
+/* Cross-net conversion of floats to and from extended form.
+   (This is needed because different target machines have different
+    extended floating point formats.)  */
+
+/* Convert from an extended float to a double.
+
+   The extended float is stored as raw data pointed to by FROM.
+   Return the converted value as raw data in the double pointed to by TO.
+*/
+
+static void
+vx_convert_to_virtual (regno, from, to)
+    int regno;
+    char *from;
+    char *to;
+{
+  enum clnt_stat status;
+
+  if (REGISTER_CONVERTIBLE (regno)) 
+    {
+      if (!target_has_fp) {
+       *(double *)to = 0.0;    /* Skip the trouble if no float anyway */
+       return;
+      }
+
+      status = net_clnt_call (VX_CONV_FROM_68881, xdr_ext_fp, from,
+                             xdr_double, to);
+
+      if (status == RPC_SUCCESS)
+         return;
+      else
+         error (rpcerr);
+    }
+  else
+    bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
+}
+
+
+/* The converse:  convert from a double to an extended float.
+
+   The double is stored as raw data pointed to by FROM.
+   Return the converted value as raw data in the extended
+   float pointed to by TO.
+*/
+
+static void
+vx_convert_from_virtual (regno, from, to)
+    int regno;
+    char *from;
+    char *to;
+{
+  enum clnt_stat status;
+
+  if (REGISTER_CONVERTIBLE (regno)) 
+    {
+      if (!target_has_fp) {
+       bzero (to, REGISTER_RAW_SIZE (FP0_REGNUM));     /* Shrug */
+       return;
+      }
+
+      status = net_clnt_call (VX_CONV_TO_68881, xdr_double, from,
+                             xdr_ext_fp, to);
+      if (status == RPC_SUCCESS)
+         return;
+      else
+         error (rpcerr);
+    }
+  else
+    bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
+}
+\f
+/* Make an RPC call to the VxWorks target.
+   Returns RPC status.  */
+
+static enum clnt_stat
+net_clnt_call (procNum, inProc, in, outProc, out)
+    enum ptracereq procNum;
+    xdrproc_t inProc;
+    char *in;
+    xdrproc_t outProc;
+    char *out;
+{
+  enum clnt_stat status;
+  
+  status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
+
+  if (status != RPC_SUCCESS)
+      clnt_perrno (status);
+
+  return status;
+}
+
+/* Clean up before losing control.  */
+
+void
+vx_close (quitting)
+     int quitting;
+{
+  if (pClient)
+    clnt_destroy (pClient);    /* The net connection */
+  pClient = 0;
+
+  if (vx_host)
+    free (vx_host);            /* The hostname */
+  vx_host = 0;
+}
+
+
+/* Target ops structure for accessing memory and such over the net */
+
+struct target_ops vx_ops = {
+       "vxworks", "VxWorks target memory via RPC over TCP/IP",
+       vx_open, vx_close, vx_attach, 0, /* vx_detach, */
+       0, 0, /* resume, wait */
+       0, 0, /* read_reg, write_reg */
+       0, vx_convert_to_virtual, vx_convert_from_virtual,  /* prep_to_store, */
+       vx_xfer_memory, vx_files_info,
+       0, 0, /* insert_breakpoint, remove_breakpoint */
+       0, 0, 0, 0, 0,  /* terminal stuff */
+       0, /* vx_kill, */
+       vx_load_command, add_syms_addr_command,
+       0,  /* call_function */
+       vx_lookup_symbol,
+       vx_create_inferior, 0,  /* mourn_inferior */
+       core_stratum, 0, /* next */
+       1, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+/* Target ops structure for accessing VxWorks child processes over the net */
+
+struct target_ops vx_run_ops = {
+       "vxprocess", "VxWorks process",
+       vx_open, vx_proc_close, 0, vx_detach, /* vx_attach */
+       vx_resume, vx_wait,
+       vx_read_register, vx_write_register,
+       vx_prepare_to_store, vx_convert_to_virtual, vx_convert_from_virtual,
+       vx_xfer_memory, vx_run_files_info,
+       vx_insert_breakpoint, vx_remove_breakpoint,
+       0, 0, 0, 0, 0,  /* terminal stuff */
+       vx_kill,
+       vx_load_command, add_syms_addr_command,
+       call_function_by_hand,  /* FIXME, calling fns is maybe botched? */
+       vx_lookup_symbol,
+       0, vx_mourn_inferior,
+       process_stratum, 0, /* next */
+       0, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+                       /* all_mem is off to avoid spurious msg in "i files" */
+       OPS_MAGIC,              /* Always the last thing */
+};
+/* ==> Remember when reading at end of file, there are two "ops" structs here. */
+\f
+void
+_initialize_vx ()
+{
+  add_target (&vx_ops);
+  add_target (&vx_run_ops);
+}
diff --git a/gdb/remote.c b/gdb/remote.c
new file mode 100644 (file)
index 0000000..9ff5650
--- /dev/null
@@ -0,0 +1,829 @@
+/* Memory-access and commands for inferior process, for GDB.
+   Copyright (C) 1988-1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Remote communication protocol.
+   All values are encoded in ascii hex digits.
+
+       Request         Packet
+
+       read registers  g
+       reply           XX....X         Each byte of register data
+                                       is described by two hex digits.
+                                       Registers are in the internal order
+                                       for GDB, and the bytes in a register
+                                       are in the same order the machine uses.
+                       or ENN          for an error.
+
+       write regs      GXX..XX         Each byte of register data
+                                       is described by two hex digits.
+       reply           OK              for success
+                       ENN             for an error
+
+       read mem        mAA..AA,LLLL    AA..AA is address, LLLL is length.
+       reply           XX..XX          XX..XX is mem contents
+                       or ENN          NN is errno
+
+       write mem       MAA..AA,LLLL:XX..XX
+                                       AA..AA is address,
+                                       LLLL is number of bytes,
+                                       XX..XX is data
+       reply           OK              for success
+                       ENN             for an error
+
+       cont            cAA..AA         AA..AA is address to resume
+                                       If AA..AA is omitted,
+                                       resume at same address.
+
+       step            sAA..AA         AA..AA is address to resume
+                                       If AA..AA is omitted,
+                                       resume at same address.
+
+       last signal     ?               Reply the current reason for stopping.
+                                        This is the same reply as is generated
+                                       for step or cont : SAA where AA is the
+                                       signal number.
+
+       There is no immediate reply to step or cont.
+       The reply comes when the machine stops.
+       It is           SAA             AA is the "signal number"
+
+       kill req        k
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "terminal.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+
+extern int memory_insert_breakpoint ();
+extern int memory_remove_breakpoint ();
+extern void add_syms_addr_command ();
+extern struct value *call_function_by_hand();
+extern void start_remote ();
+
+extern struct target_ops remote_ops;   /* Forward decl */
+
+static int kiodebug;
+static int timeout = 5;
+
+#if 0
+int icache;
+#endif
+
+/* Descriptor for I/O to remote machine.  Initialize it to -1 so that
+   remote_open knows that we don't have a file open when the program
+   starts.  */
+int remote_desc = -1;
+
+#define        PBUFSIZ 400
+
+/* Maximum number of bytes to read/write at once.  The value here
+   is chosen to fill up a packet (the headers account for the 32).  */
+#define MAXBUFBYTES ((PBUFSIZ-32)/2)
+
+static void remote_send ();
+static void putpkt ();
+static void getpkt ();
+#if 0
+static void dcache_flush ();
+#endif
+
+\f
+/* Called when SIGALRM signal sent due to alarm() timeout.  */
+#ifndef HAVE_TERMIO
+void
+remote_timer ()
+{
+  if (kiodebug)
+    printf ("remote_timer called\n");
+
+  alarm (timeout);
+}
+#endif
+
+/* Initialize remote connection */
+
+void
+remote_start()
+{
+}
+
+/* Clean up connection to a remote debugger.  */
+
+void
+remote_close (quitting)
+     int quitting;
+{
+  if (remote_desc >= 0)
+    close (remote_desc);
+  remote_desc = -1;
+}
+
+/* Open a connection to a remote debugger.
+   NAME is the filename used for communication.  */
+
+void
+remote_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  TERMINAL sg;
+
+  if (name == 0)
+    error (
+"To open a remote debug connection, you need to specify what serial\n\
+device is attached to the remote system (e.g. /dev/ttya).");
+
+  remote_close (0);
+
+#if 0
+  dcache_init ();
+#endif
+
+  remote_desc = open (name, O_RDWR);
+  if (remote_desc < 0)
+    perror_with_name (name);
+
+  ioctl (remote_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+  sg.c_cc[VMIN] = 0;           /* read with timeout.  */
+  sg.c_cc[VTIME] = timeout * 10;
+  sg.c_lflag &= ~(ICANON | ECHO);
+#else
+  sg.sg_flags = RAW;
+#endif
+  ioctl (remote_desc, TIOCSETP, &sg);
+
+  if (from_tty)
+    printf ("Remote debugging using %s\n", name);
+  push_target (&remote_ops);   /* Switch to using remote target now */
+  start_remote ();             /* Initialize gdb process mechanisms */
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+  /* Cause SIGALRM's to make reads fail.  */
+  if (siginterrupt (SIGALRM, 1) != 0)
+    perror ("remote_open: error in siginterrupt");
+#endif
+
+  /* Set up read timeout timer.  */
+  if ((void (*)) signal (SIGALRM, remote_timer) == (void (*)) -1)
+    perror ("remote_open: error in signal");
+#endif
+
+  putpkt ("?");                        /* initiate a query from remote machine */
+}
+
+/* remote_detach()
+   takes a program previously attached to and detaches it.
+   We better not have left any breakpoints
+   in the program or it'll die when it hits one.
+   Close the open connection to the remote debugger.
+   Use this when you want to detach and do something else
+   with your gdb.  */
+
+static void
+remote_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (args)
+    error ("Argument given to \"detach\" when remotely debugging.");
+  
+  pop_target ();
+  if (from_tty)
+    printf ("Ending remote debugging.\n");
+}
+
+/* Convert hex digit A to a number.  */
+
+static int
+fromhex (a)
+     int a;
+{
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else
+    error ("Reply contains invalid hex digit");
+  return -1;
+}
+
+/* Convert number NIB to a hex digit.  */
+
+static int
+tohex (nib)
+     int nib;
+{
+  if (nib < 10)
+    return '0'+nib;
+  else
+    return 'a'+nib-10;
+}
+\f
+/* Tell the remote machine to resume.  */
+
+void
+remote_resume (step, siggnal)
+     int step, siggnal;
+{
+  char buf[PBUFSIZ];
+
+  if (siggnal)
+    error ("Can't send signals to a remote system.");
+
+#if 0
+  dcache_flush ();
+#endif
+
+  strcpy (buf, step ? "s": "c");
+
+  putpkt (buf);
+}
+
+/* Wait until the remote machine stops, then return,
+   storing status in STATUS just as `wait' would.  */
+
+int
+remote_wait (status)
+     WAITTYPE *status;
+{
+  unsigned char buf[PBUFSIZ];
+
+  WSETEXIT ((*status), 0);
+  getpkt (buf);
+  if (buf[0] == 'E')
+    error ("Remote failure reply: %s", buf);
+  if (buf[0] != 'S')
+    error ("Invalid remote reply: %s", buf);
+  WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))));
+}
+
+/* Read the remote registers into the block REGS.  */
+
+int
+remote_fetch_registers (regno)
+     int regno;
+{
+  char buf[PBUFSIZ];
+  int i;
+  char *p;
+  char regs[REGISTER_BYTES];
+
+  sprintf (buf, "g");
+  remote_send (buf);
+
+  /* Reply describes registers byte by byte, each byte encoded as two
+     hex characters.  Suck them all up, then supply them to the
+     register cacheing/storage mechanism.  */
+
+  p = buf;
+  for (i = 0; i < REGISTER_BYTES; i++)
+    {
+      if (p[0] == 0 || p[1] == 0)
+       error ("Remote reply is too short: %s", buf);
+      regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+      p += 2;
+    }
+  for (i = 0; i < NUM_REGS; i++)
+    supply_register (i, &regs[REGISTER_BYTE(i)]);
+  return 0;
+}
+
+/* Prepare to store registers.  Since we send them all, we have to
+   read out the ones we don't want to change first.  */
+
+void 
+remote_prepare_to_store ()
+{
+  remote_fetch_registers (-1);
+}
+
+/* Store the remote registers from the contents of the block REGISTERS. 
+   FIXME, eventually just store one register if that's all that is needed.  */
+
+int
+remote_store_registers (regno)
+     int regno;
+{
+  char buf[PBUFSIZ];
+  int i;
+  char *p;
+
+  buf[0] = 'G';
+  
+  /* Command describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  p = buf + 1;
+  for (i = 0; i < REGISTER_BYTES; i++)
+    {
+      *p++ = tohex ((registers[i] >> 4) & 0xf);
+      *p++ = tohex (registers[i] & 0xf);
+    }
+  *p = '\0';
+
+  remote_send (buf);
+  return 0;
+}
+
+#if 0
+/* Read a word from remote address ADDR and return it.
+   This goes through the data cache.  */
+
+int
+remote_fetch_word (addr)
+     CORE_ADDR addr;
+{
+  if (icache)
+    {
+      extern CORE_ADDR text_start, text_end;
+
+      if (addr >= text_start && addr < text_end)
+       {
+         int buffer;
+         xfer_core_file (addr, &buffer, sizeof (int));
+         return buffer;
+       }
+    }
+  return dcache_fetch (addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+   This goes through the data cache.  */
+
+void
+remote_store_word (addr, word)
+     CORE_ADDR addr;
+     int word;
+{
+  dcache_poke (addr, word);
+}
+#endif /* 0 */
+\f
+/* Write memory data directly to the remote machine.
+   This does not inform the data cache; the data cache uses this.
+   MEMADDR is the address in the remote memory space.
+   MYADDR is the address of the buffer in our space.
+   LEN is the number of bytes.  */
+
+void
+remote_write_bytes (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  char buf[PBUFSIZ];
+  int i;
+  char *p;
+
+  if (len > PBUFSIZ / 2 - 20)
+    abort ();
+
+  sprintf (buf, "M%x,%x:", memaddr, len);
+
+  /* Command describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  p = buf + strlen (buf);
+  for (i = 0; i < len; i++)
+    {
+      *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+      *p++ = tohex (myaddr[i] & 0xf);
+    }
+  *p = '\0';
+
+  remote_send (buf);
+}
+
+/* Read memory data directly from the remote machine.
+   This does not use the data cache; the data cache uses this.
+   MEMADDR is the address in the remote memory space.
+   MYADDR is the address of the buffer in our space.
+   LEN is the number of bytes.  */
+
+void
+remote_read_bytes (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  char buf[PBUFSIZ];
+  int i;
+  char *p;
+
+  if (len > PBUFSIZ / 2 - 1)
+    abort ();
+
+  sprintf (buf, "m%x,%x", memaddr, len);
+  remote_send (buf);
+
+  /* Reply describes registers byte by byte,
+     each byte encoded as two hex characters.  */
+
+  p = buf;
+  for (i = 0; i < len; i++)
+    {
+      if (p[0] == 0 || p[1] == 0)
+       error ("Remote reply is too short: %s", buf);
+      myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+      p += 2;
+    }
+}
+\f
+/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+   to or from debugger address MYADDR.  Write to inferior if WRITE is
+   nonzero.  Returns length of data written or read; 0 for error.  */
+
+int
+remote_xfer_inferior_memory(memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  int origlen = len;
+  int xfersize;
+  while (len > 0)
+    {
+      if (len > MAXBUFBYTES)
+       xfersize = MAXBUFBYTES;
+      else
+       xfersize = len;
+
+      if (write)
+        remote_write_bytes(memaddr, myaddr, xfersize);
+      else
+       remote_read_bytes (memaddr, myaddr, xfersize);
+      memaddr += xfersize;
+      myaddr  += xfersize;
+      len     -= xfersize;
+    }
+  return origlen; /* no error possible */
+}
+
+void
+remote_files_info ()
+{
+  printf ("remote files info missing here.  FIXME.\n");
+}
+\f
+/*
+
+A debug packet whose contents are <data>
+is encapsulated for transmission in the form:
+
+       $ <data> # CSUM1 CSUM2
+
+       <data> must be ASCII alphanumeric and cannot include characters
+       '$' or '#'
+
+       CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
+       checksum of <data>, the most significant nibble is sent first.
+       the hex digits 0-9,a-f are used.
+
+Receiver responds with:
+
+       +       - if CSUM is correct and ready for next packet
+       -       - if CSUM is incorrect
+
+*/
+
+static int
+readchar ()
+{
+  char buf;
+
+  buf = '\0';
+#ifdef HAVE_TERMIO
+  /* termio does the timeout for us.  */
+  read (remote_desc, &buf, 1);
+#else
+  alarm (timeout);
+  read (remote_desc, &buf, 1);
+  alarm (0);
+#endif
+
+  return buf & 0x7f;
+}
+
+/* Send the command in BUF to the remote machine,
+   and read the reply into BUF.
+   Report an error if we get an error reply.  */
+
+static void
+remote_send (buf)
+     char *buf;
+{
+
+  putpkt (buf);
+  getpkt (buf);
+
+  if (buf[0] == 'E')
+    error ("Remote failure reply: %s", buf);
+}
+
+/* Send a packet to the remote machine, with error checking.
+   The data of the packet is in BUF.  */
+
+static void
+putpkt (buf)
+     char *buf;
+{
+  int i;
+  unsigned char csum = 0;
+  char buf2[500];
+  int cnt = strlen (buf);
+  char ch;
+  char *p;
+
+  /* Copy the packet into buffer BUF2, encapsulating it
+     and giving it a checksum.  */
+
+  p = buf2;
+  *p++ = '$';
+
+  for (i = 0; i < cnt; i++)
+    {
+      csum += buf[i];
+      *p++ = buf[i];
+    }
+  *p++ = '#';
+  *p++ = tohex ((csum >> 4) & 0xf);
+  *p++ = tohex (csum & 0xf);
+
+  /* Send it over and over until we get a positive ack.  */
+
+  do {
+    if (kiodebug)
+      {
+       *p = '\0';
+       printf ("Sending packet: %s (%s)\n", buf2, buf);
+      }
+    write (remote_desc, buf2, p - buf2);
+
+    /* read until either a timeout occurs (\0) or '+' is read */
+    do {
+      ch = readchar ();
+    } while ((ch != '+') && (ch != '\0'));
+  } while (ch != '+');
+}
+
+/* Read a packet from the remote machine, with error checking,
+   and store it in BUF.  */
+
+static void
+getpkt (buf)
+     char *buf;
+{
+  char *bp;
+  unsigned char csum;
+  int c;
+  unsigned char c1, c2;
+
+  /* allow immediate quit while reading from device, it could be hung */
+  immediate_quit++;
+
+  while (1)
+    {
+      /* Force csum to be zero here because of possible error retry.  */
+      csum = 0;
+      
+      while ((c = readchar()) != '$');
+
+      bp = buf;
+      while (1)
+       {
+         c = readchar ();
+         if (c == '#')
+           break;
+         *bp++ = c;
+         csum += c;
+       }
+      *bp = 0;
+
+      c1 = fromhex (readchar ());
+      c2 = fromhex (readchar ());
+      if ((csum & 0xff) == (c1 << 4) + c2)
+       break;
+      printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+             (c1 << 4) + c2, csum & 0xff, buf);
+      write (remote_desc, "-", 1);
+    }
+
+  immediate_quit--;
+
+  write (remote_desc, "+", 1);
+
+  if (kiodebug)
+    fprintf (stderr,"Packet received :%s\n", buf);
+}
+\f
+/* The data cache leads to incorrect results because it doesn't know about
+   volatile variables, thus making it impossible to debug functions which
+   use hardware registers.  Therefore it is #if 0'd out.  Effect on
+   performance is some, for backtraces of functions with a few
+   arguments each.  For functions with many arguments, the stack
+   frames don't fit in the cache blocks, which makes the cache less
+   helpful.  Disabling the cache is a big performance win for fetching
+   large structures, because the cache code fetched data in 16-byte
+   chunks.  */
+#if 0
+/* The data cache records all the data read from the remote machine
+   since the last time it stopped.
+
+   Each cache block holds 16 bytes of data
+   starting at a multiple-of-16 address.  */
+
+#define DCACHE_SIZE 64         /* Number of cache blocks */
+
+struct dcache_block {
+       struct dcache_block *next, *last;
+       unsigned int addr;      /* Address for which data is recorded.  */
+       int data[4];
+};
+
+struct dcache_block dcache_free, dcache_valid;
+
+/* Free all the data cache blocks, thus discarding all cached data.  */ 
+
+static void
+dcache_flush ()
+{
+  register struct dcache_block *db;
+
+  while ((db = dcache_valid.next) != &dcache_valid)
+    {
+      remque (db);
+      insque (db, &dcache_free);
+    }
+}
+
+/*
+ * If addr is present in the dcache, return the address of the block 
+ * containing it.
+ */
+
+struct dcache_block *
+dcache_hit (addr)
+{
+  register struct dcache_block *db;
+
+  if (addr & 3)
+    abort ();
+
+  /* Search all cache blocks for one that is at this address.  */
+  db = dcache_valid.next;
+  while (db != &dcache_valid)
+    {
+      if ((addr & 0xfffffff0) == db->addr)
+       return db;
+      db = db->next;
+    }
+  return NULL;
+}
+
+/*  Return the int data at address ADDR in dcache block DC.  */
+
+int
+dcache_value (db, addr)
+     struct dcache_block *db;
+     unsigned int addr;
+{
+  if (addr & 3)
+    abort ();
+  return (db->data[(addr>>2)&3]);
+}
+
+/* Get a free cache block, put it on the valid list,
+   and return its address.  The caller should store into the block
+   the address and data that it describes.  */
+
+struct dcache_block *
+dcache_alloc ()
+{
+  register struct dcache_block *db;
+
+  if ((db = dcache_free.next) == &dcache_free)
+    /* If we can't get one from the free list, take last valid */
+    db = dcache_valid.last;
+
+  remque (db);
+  insque (db, &dcache_valid);
+  return (db);
+}
+
+/* Return the contents of the word at address ADDR in the remote machine,
+   using the data cache.  */
+
+int
+dcache_fetch (addr)
+     CORE_ADDR addr;
+{
+  register struct dcache_block *db;
+
+  db = dcache_hit (addr);
+  if (db == 0)
+    {
+      db = dcache_alloc ();
+      remote_read_bytes (addr & ~0xf, db->data, 16);
+      db->addr = addr & ~0xf;
+    }
+  return (dcache_value (db, addr));
+}
+
+/* Write the word at ADDR both in the data cache and in the remote machine.  */
+
+dcache_poke (addr, data)
+     CORE_ADDR addr;
+     int data;
+{
+  register struct dcache_block *db;
+
+  /* First make sure the word is IN the cache.  DB is its cache block.  */
+  db = dcache_hit (addr);
+  if (db == 0)
+    {
+      db = dcache_alloc ();
+      remote_read_bytes (addr & ~0xf, db->data, 16);
+      db->addr = addr & ~0xf;
+    }
+
+  /* Modify the word in the cache.  */
+  db->data[(addr>>2)&3] = data;
+
+  /* Send the changed word.  */
+  remote_write_bytes (addr, &data, 4);
+}
+
+/* Initialize the data cache.  */
+
+dcache_init ()
+{
+  register i;
+  register struct dcache_block *db;
+
+  db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) * 
+                                       DCACHE_SIZE);
+  dcache_free.next = dcache_free.last = &dcache_free;
+  dcache_valid.next = dcache_valid.last = &dcache_valid;
+  for (i=0;i<DCACHE_SIZE;i++,db++)
+    insque (db, &dcache_free);
+}
+#endif /* 0 */
+
+/* Define the target subroutine names */
+
+struct target_ops remote_ops = {
+       "remote", "Remote serial target in gdb-specific protocol",
+       remote_open, remote_close,
+       0, remote_detach, remote_resume, remote_wait,  /* attach */
+       remote_fetch_registers, remote_store_registers,
+       remote_prepare_to_store, 0, 0, /* conv_from, conv_to */
+       remote_xfer_inferior_memory, remote_files_info,
+       0, 0, /* insert_breakpoint, remove_breakpoint, */
+       0, 0, 0, 0, 0,  /* Terminal crud */
+       0, /* kill */
+       0, add_syms_addr_command,  /* load */
+       call_function_by_hand,
+       0, /* lookup_symbol */
+       0, 0, /* create_inferior FIXME, mourn_inferior FIXME */
+       process_stratum, 0, /* next */
+       1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_remote ()
+{
+  add_target (&remote_ops);
+}
diff --git a/gdb/saber.suppress b/gdb/saber.suppress
new file mode 100644 (file)
index 0000000..19fac4d
--- /dev/null
@@ -0,0 +1,411 @@
+
+
+/* Options for project */
+unsetopt ansi
+setopt auto_compile
+unsetopt auto_reload
+setopt auto_replace
+unsetopt batch_load
+unsetopt batch_run
+unsetopt cc_prog
+setopt ccargs               -g
+unsetopt create_file
+unsetopt debug_child
+unsetopt echo
+setopt edit_jobs            5
+unsetopt eight_bit
+setopt line_edit
+setopt line_meta
+setopt lint_load            2
+setopt lint_run             2
+setopt list_action
+setopt load_flags           -I. -g -I.. -I../vx-share
+unsetopt long_not_int
+unsetopt make_args
+setopt make_hfiles
+unsetopt make_offset
+unsetopt make_prog
+setopt make_symbol          #
+setopt mem_config           16384
+unsetopt mem_trace
+setopt num_proc             1
+unsetopt page_cmds
+setopt page_list            19
+unsetopt page_load
+unsetopt path
+setopt proto_path           . /s2/saber_dir30/sun4-40/proto /s2/saber_dir30/sun4-40/../common/proto
+unsetopt preprocessor
+setopt program_name         a.out
+unsetopt print_custom
+setopt print_pointer
+setopt print_string         20
+unsetopt save_memory
+setopt sbrk_size            1048576
+setopt src_err              3
+setopt src_step             1
+setopt src_stop             3
+setopt sys_load_flags       -L/lib -L/usr/lib -L/usr/local/lib -I/usr/include -Dunix -Dsun -Dsparc
+unsetopt tab_stop
+unsetopt terse_suppress
+unsetopt terse_where
+setopt unset_value          191
+unsetopt win_fork_nodup
+setopt win_no_raise
+unsetopt win_message_list
+unsetopt win_project_list
+/* Suppressions for project */
+suppress 6 in read_huge_number 
+/* Over/underflow <plus> */
+suppress 8 in read_huge_number 
+/* Over/underflow <multiply> */
+suppress 22 
+/* Pointer subtraction */
+suppress 22 in free_all_psymtabs 
+/* Pointer subtraction */
+suppress 22 in free_all_symtabs 
+/* Pointer subtraction */
+suppress 56 in print_string 
+/* Information lost <function> */
+suppress 65 "../bfd/bfd.c":379 
+/* Too many function arguments */
+suppress 65 on printf_filtered 
+/* Too many function arguments */
+suppress 65 on fprintf_filtered 
+/* Too many function arguments */
+suppress 65 on vfprintf_filtered 
+/* Too many function arguments */
+suppress 65 on query 
+/* Too many function arguments */
+suppress 65 on fatal_dump_core 
+/* Too many function arguments */
+suppress 65 on fatal 
+/* Too many function arguments */
+suppress 65 on error 
+/* Too many function arguments */
+suppress 65 on noprocess 
+/* Too many function arguments */
+suppress 65 
+/* Too many function arguments */
+suppress 66 on say 
+/* Too few function arguments */
+suppress 66 on printf_filtered 
+/* Too few function arguments */
+suppress 66 on fprintf_filtered 
+/* Too few function arguments */
+suppress 66 on vfprintf_filtered 
+/* Too few function arguments */
+suppress 66 on query 
+/* Too few function arguments */
+suppress 66 on fatal_dump_core 
+/* Too few function arguments */
+suppress 66 on fatal 
+/* Too few function arguments */
+suppress 66 on error 
+/* Too few function arguments */
+suppress 67 on printf_filtered 
+/* Signed/unsigned argument mismatch */
+suppress 67 on fprintf_filtered 
+/* Signed/unsigned argument mismatch */
+suppress 67 on vfprintf_filtered 
+/* Signed/unsigned argument mismatch */
+suppress 67 on query 
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal_dump_core 
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal 
+/* Signed/unsigned argument mismatch */
+suppress 67 on error 
+/* Signed/unsigned argument mismatch */
+suppress 67 
+/* Signed/unsigned argument mismatch */
+suppress 68 on bfd_get_section_contents 
+/* Benign argument mismatch */
+suppress 68 on _do_getblong 
+/* Benign argument mismatch */
+suppress 68 on supply_register 
+/* Benign argument mismatch */
+suppress 68 on target_write_memory 
+/* Benign argument mismatch */
+suppress 68 on write_register_bytes 
+/* Benign argument mismatch */
+suppress 68 on read_register_bytes 
+/* Benign argument mismatch */
+suppress 68 on read_memory 
+/* Benign argument mismatch */
+suppress 68 on say 
+/* Benign argument mismatch */
+suppress 68 on printf_filtered 
+/* Benign argument mismatch */
+suppress 68 on fprintf_filtered 
+/* Benign argument mismatch */
+suppress 68 on vfprintf_filtered 
+/* Benign argument mismatch */
+suppress 68 on query 
+/* Benign argument mismatch */
+suppress 68 on fatal_dump_core 
+/* Benign argument mismatch */
+suppress 68 on fatal 
+/* Benign argument mismatch */
+suppress 68 on error 
+/* Benign argument mismatch */
+suppress 68 in find_solib 
+/* Benign argument mismatch */
+suppress 68 on child_wait 
+/* Benign argument mismatch */
+suppress 68 on xrealloc 
+/* Benign argument mismatch */
+suppress 68 on myread 
+/* Benign argument mismatch */
+suppress 68 in do_cleanups 
+/* Benign argument mismatch */
+suppress 68 on make_cleanup 
+/* Benign argument mismatch */
+suppress 68 on target_read_memory 
+/* Benign argument mismatch */
+suppress 69 on printf_filtered 
+/* Serious argument mismatch */
+suppress 69 on fprintf_filtered 
+/* Serious argument mismatch */
+suppress 69 on vfprintf_filtered 
+/* Serious argument mismatch */
+suppress 69 on query 
+/* Serious argument mismatch */
+suppress 69 on fatal_dump_core 
+/* Serious argument mismatch */
+suppress 69 on fatal 
+/* Serious argument mismatch */
+suppress 69 on error 
+/* Serious argument mismatch */
+suppress 70 on printf_filtered 
+/* Passing illegal enumeration value */
+suppress 70 on fprintf_filtered 
+/* Passing illegal enumeration value */
+suppress 70 on vfprintf_filtered 
+/* Passing illegal enumeration value */
+suppress 70 on query 
+/* Passing illegal enumeration value */
+suppress 70 on fatal_dump_core 
+/* Passing illegal enumeration value */
+suppress 70 on fatal 
+/* Passing illegal enumeration value */
+suppress 70 on error 
+/* Passing illegal enumeration value */
+suppress 110 in printf_filtered 
+/* Signed/unsigned memory retrieval */
+suppress 110 in fprintf_filtered 
+/* Signed/unsigned memory retrieval */
+suppress 110 in vfprintf_filtered 
+/* Signed/unsigned memory retrieval */
+suppress 110 in query 
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal_dump_core 
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal 
+/* Signed/unsigned memory retrieval */
+suppress 110 in error 
+/* Signed/unsigned memory retrieval */
+suppress 112 in printf_filtered 
+/* Memory retrieval */
+suppress 112 in fprintf_filtered 
+/* Memory retrieval */
+suppress 112 in vfprintf_filtered 
+/* Memory retrieval */
+suppress 112 in query 
+/* Memory retrieval */
+suppress 112 in fatal_dump_core 
+/* Memory retrieval */
+suppress 112 in fatal 
+/* Memory retrieval */
+suppress 112 in error 
+/* Memory retrieval */
+suppress 112 
+/* Memory retrieval */
+suppress 112 ../symtab.c 
+/* Memory retrieval */
+suppress 112 in child_xfer_memory 
+/* Memory retrieval */
+suppress 165 in frame_saved_pc 
+/* Dereference */
+suppress 165 in get_prev_frame_info 
+/* Dereference */
+suppress 167 in get_prev_frame_info 
+/* Selection */
+suppress 167 in frame_saved_pc 
+/* Selection */
+suppress 442 in try_baudrate 
+/* Escape has null value */
+suppress 529 in read_range_type 
+/* Statement not reached */
+suppress 529 in process_one_symbol 
+/* Statement not reached */
+suppress 529 in unpack_double 
+/* Statement not reached */
+suppress 529 in wait_for_inferior 
+/* Statement not reached */
+suppress 529 in do_registers_info 
+/* Statement not reached */
+suppress 529 in value_from_register 
+/* Statement not reached */
+suppress 530 "../environ.c":69 
+/* Empty body of statement */
+suppress 530 "../remote-eb.c":333 
+/* Empty body of statement */
+suppress 530 "../remote-eb.c":331 
+/* Empty body of statement */
+suppress 530 "../remote-eb.c":324 
+/* Empty body of statement */
+suppress 530 "../dbxread.c":792 
+/* Empty body of statement */
+suppress 530 
+/* Empty body of statement */
+suppress 530 "../dbxread.c":796 
+/* Empty body of statement */
+suppress 546 in net_quit 
+/* Function exits through bottom */
+suppress 546 in net_wait 
+/* Function exits through bottom */
+suppress 546 in vx_remove_breakpoint 
+/* Function exits through bottom */
+suppress 546 in vx_insert_breakpoint 
+/* Function exits through bottom */
+suppress 546 in value_less 
+/* Function exits through bottom */
+suppress 546 in value_equal 
+/* Function exits through bottom */
+suppress 546 in unpack_long 
+/* Function exits through bottom */
+suppress 558 in read_range_type 
+/* Constant in conditional */
+suppress 558 in process_one_symbol 
+/* Constant in conditional */
+suppress 558 in read_dbx_symtab 
+/* Constant in conditional */
+suppress 558 in vx_write_register 
+/* Constant in conditional */
+suppress 558 in vx_read_register 
+/* Constant in conditional */
+suppress 558 in unpack_double 
+/* Constant in conditional */
+suppress 558 in wait_for_inferior 
+/* Constant in conditional */
+suppress 558 in do_registers_info 
+/* Constant in conditional */
+suppress 558 in value_from_register 
+/* Constant in conditional */
+suppress 560 in solib_address 
+/* Assignment within conditional */
+suppress 560 in solib_info 
+/* Assignment within conditional */
+suppress 560 in solib_add 
+/* Assignment within conditional */
+suppress 560 in read_type 
+/* Assignment within conditional */
+suppress 560 in type_print_base 
+/* Assignment within conditional */
+suppress 560 in type_print_derivation_info 
+/* Assignment within conditional */
+suppress 560 in block_depth 
+/* Assignment within conditional */
+suppress 560 in select_source_symtab 
+/* Assignment within conditional */
+suppress 560 in clear_value_history 
+/* Assignment within conditional */
+suppress 560 in clear_displays 
+/* Assignment within conditional */
+suppress 560 in initialize_main 
+/* Assignment within conditional */
+suppress 560 in echo_command 
+/* Assignment within conditional */
+suppress 560 in unset_in_environ 
+/* Assignment within conditional */
+suppress 560 in set_in_environ 
+/* Assignment within conditional */
+suppress 560 in get_in_environ 
+/* Assignment within conditional */
+suppress 560 in do_setshow_command 
+/* Assignment within conditional */
+suppress 560 in breakpoint_1 
+/* Assignment within conditional */
+suppress 590 on sig 
+/* Unused formal parameter */
+suppress 590 in nindy_create_inferior 
+/* Unused formal parameter */
+suppress 590 in add_to_section_table 
+/* Unused formal parameter */
+suppress 590 in vx_create_inferior 
+/* Unused formal parameter */
+suppress 590 in host_convert_from_virtual 
+/* Unused formal parameter */
+suppress 590 in host_convert_to_virtual 
+/* Unused formal parameter */
+suppress 590 on siggnal 
+/* Unused formal parameter */
+suppress 590 in init_sig 
+/* Unused formal parameter */
+suppress 590 in nindy_resume 
+/* Unused formal parameter */
+suppress 590 in set_history_size_command 
+/* Unused formal parameter */
+suppress 590 in not_just_help_class_command 
+/* Unused formal parameter */
+suppress 590 on regno 
+/* Unused formal parameter */
+suppress 590 on from_tty 
+/* Unused formal parameter */
+suppress 590 on args 
+/* Unused formal parameter */
+suppress 590 in process_symbol_pair 
+/* Unused formal parameter */
+suppress 591 in print_scalar_formatted 
+/* Unused automatic variable */
+suppress 592 on rcsid 
+/* Unused static */
+suppress 592 on check_break_insn_size 
+/* Unused static */
+suppress 594 in call_function_by_hand 
+/* Set but not used */
+suppress 594 in record_latest_value 
+/* Set but not used */
+suppress 594 in bpstat_stop_status 
+/* Set but not used */
+suppress 595 in coffstrip 
+/* Used before set */
+suppress 652 ../bfd.h 
+/* Declaration has no effect */
+suppress 652 /usr/include/machine/reg.h 
+/* Declaration has no effect */
+
+/* Signals caught and ignored */
+catch HUP
+catch QUIT
+catch ILL
+catch TRAP
+catch IOT
+catch EMT
+catch FPE
+catch KILL
+catch BUS
+catch SEGV
+catch SYS
+catch PIPE
+catch TERM
+catch URG
+catch STOP
+catch TSTP
+catch TTIN
+catch TTOU
+catch IO
+catch XCPU
+catch XFSZ
+catch VTALRM
+catch PROF
+catch LOST
+catch USR1
+catch USR2
+ignore INT
+ignore ALRM
+ignore CONT
+ignore CHLD
+ignore WINCH
+
+/* Status of project */
diff --git a/gdb/signals.h b/gdb/signals.h
new file mode 100644 (file)
index 0000000..a6218d9
--- /dev/null
@@ -0,0 +1,34 @@
+/* Signal handler definitions for GDB, the GNU Debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/*  This file is almost the same as including <signal.h> except that it
+    eliminates certain signal names when job control is not supported,
+    (or, on some systems, when job control is there but doesn't work
+    the way GDB expects it to work).  */
+
+#include <signal.h>
+
+#ifdef NO_JOB_CONTROL
+# undef SIGTSTP
+# undef SIGSTOP
+# undef SIGCONT
+# undef SIGTTIN
+# undef SIGTTOU
+#endif
diff --git a/gdb/signame.c b/gdb/signame.c
new file mode 100755 (executable)
index 0000000..740da40
--- /dev/null
@@ -0,0 +1,246 @@
+/* Convert between signal names and numbers.
+   Copyright (C) 1990 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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <signal.h>
+#include "signame.h"
+
+#ifdef __STDC__
+#define CONST const
+#else
+#define CONST
+#endif
+
+#ifdef SYS_SIGLIST_MISSING
+/* There is too much variation in Sys V signal numbers and names, so
+   we must initialize them at runtime.  */
+
+static CONST char undoc[] = "unknown signal";
+
+CONST char *sys_siglist[NSIG];
+#endif /* SYS_SIGLIST_MISSING */
+
+/* Table of abbreviations for signals.  Note:  A given number can
+   appear more than once with different abbreviations.  */
+typedef struct
+  {
+    int number;
+    CONST char *abbrev;
+  } num_abbrev;
+static num_abbrev sig_table[NSIG*2];
+/* Number of elements of sig_table used.  */
+static int sig_table_nelts = 0;
+
+/* Enter signal number NUMBER into the tables with ABBREV and NAME.  */
+static void
+init_sig (number, abbrev, name)
+     int number;
+     CONST char *abbrev;
+     CONST char *name;
+{
+#ifdef SYS_SIGLIST_MISSING
+  sys_siglist[number] = name;
+#endif
+  sig_table[sig_table_nelts].number = number;
+  sig_table[sig_table_nelts++].abbrev = abbrev;
+}
+
+static void init_sigs ()
+{
+#ifdef SYS_SIGLIST_MISSING
+  /* Initialize signal names.  */
+       for (i = 0; i < NSIG; i++)
+               sys_siglist[i] = undoc;
+#endif /* SYS_SIGLIST_MISSING */
+
+  /* Initialize signal names.  */
+#if defined (SIGHUP)
+  init_sig (SIGHUP, "HUP", "Hangup");
+#endif
+#if defined (SIGINT)
+  init_sig (SIGINT, "INT", "Interrupt");
+#endif
+#if defined (SIGQUIT)
+  init_sig (SIGQUIT, "QUIT", "Quit");
+#endif
+#if defined (SIGILL)
+  init_sig (SIGILL, "ILL", "Illegal Instruction");
+#endif
+#if defined (SIGTRAP)
+  init_sig (SIGTRAP, "TRAP", "Trace/breakpoint trap");
+#endif
+  /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because
+     SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't.  */
+#if defined (SIGABRT)
+  init_sig (SIGABRT, "ABRT", "Aborted");
+#endif
+#if defined (SIGIOT)
+  init_sig (SIGIOT, "IOT", "IOT trap");
+#endif
+#if defined (SIGEMT)
+  init_sig (SIGEMT, "EMT", "EMT trap");
+#endif
+#if defined (SIGFPE)
+  init_sig (SIGFPE, "FPE", "Floating point exception");
+#endif
+#if defined (SIGKILL)
+  init_sig (SIGKILL, "KILL", "Killed");
+#endif
+#if defined (SIGBUS)
+  init_sig (SIGBUS, "BUS", "Bus error");
+#endif
+#if defined (SIGSEGV)
+  init_sig (SIGSEGV, "SEGV", "Segmentation fault");
+#endif
+#if defined (SIGSYS)
+  init_sig (SIGSYS, "SYS", "Bad system call");
+#endif
+#if defined (SIGPIPE)
+  init_sig (SIGPIPE, "PIPE", "Broken pipe");
+#endif
+#if defined (SIGALRM)
+  init_sig (SIGALRM, "ALRM", "Alarm clock");
+#endif
+#if defined (SIGTERM)
+  init_sig (SIGTERM, "TERM", "Terminated");
+#endif
+#if defined (SIGUSR1)
+  init_sig (SIGUSR1, "USR1", "User defined signal 1");
+#endif
+#if defined (SIGUSR2)
+  init_sig (SIGUSR2, "USR2", "User defined signal 2");
+#endif
+  /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that
+     is what is in POSIX.1.  */
+#if defined (SIGCHLD)
+  init_sig (SIGCHLD, "CHLD", "Child exited");
+#endif
+#if defined (SIGCLD)
+  init_sig (SIGCLD, "CLD", "Child exited");
+#endif
+#if defined (SIGPWR)
+  init_sig (SIGPWR, "PWR", "Power failure");
+#endif
+#if defined (SIGTSTP)
+  init_sig (SIGTSTP, "TSTP", "Stopped");
+#endif
+#if defined (SIGTTIN)
+  init_sig (SIGTTIN, "TTIN", "Stopped (tty input)");
+#endif
+#if defined (SIGTTOU)
+  init_sig (SIGTTOU, "TTOU", "Stopped (tty output)");
+#endif
+#if defined (SIGSTOP)
+  init_sig (SIGSTOP, "STOP", "Stopped (signal)");
+#endif
+#if defined (SIGXCPU)
+  init_sig (SIGXCPU, "XCPU", "CPU time limit exceeded");
+#endif
+#if defined (SIGXFSZ)
+  init_sig (SIGXFSZ, "XFSZ", "File size limit exceeded");
+#endif
+#if defined (SIGVTALRM)
+  init_sig (SIGVTALRM, "VTALRM", "Virtual timer expired");
+#endif
+#if defined (SIGPROF)
+  init_sig (SIGPROF, "PROF", "Profiling timer expired");
+#endif
+#if defined (SIGWINCH)
+  /* "Window size changed" might be more accurate, but even if that
+     is all that it means now, perhaps in the future it will be
+     extended to cover other kinds of window changes.  */
+  init_sig (SIGWINCH, "WINCH", "Window changed");
+#endif
+#if defined (SIGCONT)
+  init_sig (SIGCONT, "CONT", "Continued");
+#endif
+#if defined (SIGURG)
+  init_sig (SIGURG, "URG", "Urgent I/O condition");
+#endif
+#if defined (SIGIO)
+  /* "I/O pending" has also been suggested.  A disadvantage is
+     that signal only happens when the process has
+     asked for it, not everytime I/O is pending.  Another disadvantage
+     is the confusion from giving it a different name than under Unix.  */
+  init_sig (SIGIO, "IO", "I/O possible");
+#endif
+#if defined (SIGWIND)
+  init_sig (SIGWIND, "WIND", "SIGWIND");
+#endif
+#if defined (SIGPHONE)
+  init_sig (SIGPHONE, "PHONE", "SIGPHONE");
+#endif
+#if defined (SIGPOLL)
+  init_sig (SIGPOLL, "POLL", "I/O possible");
+#endif
+#if defined (SIGLOST)
+  init_sig (SIGLOST, "LOST", "Resource lost");
+#endif
+}
+
+/* Return the abbreviation for signal NUMBER.  */
+char *
+sig_abbrev (number)
+     int number;
+{
+  int i;
+
+  for (i = 0; i < sig_table_nelts; i++)
+    if (sig_table[i].number == number)
+      return (char *)sig_table[i].abbrev;
+  return NULL;
+}
+
+/* Return the signal number for an ABBREV, or -1 if there is no
+   signal by that name.  */
+int
+sig_number (abbrev)
+     CONST char *abbrev;
+{
+  int i;
+
+  /* Skip over "SIG" if present.  */
+  if (abbrev[0] == 'S' && abbrev[1] == 'I' && abbrev[2] == 'G')
+    abbrev += 3;
+
+  for (i = 0; i < sig_table_nelts; i++)
+    if (abbrev[0] == sig_table[i].abbrev[0]
+       && strcmp (abbrev, sig_table[i].abbrev) == 0)
+      return sig_table[i].number;
+  return -1;
+}
+
+#if defined (SYS_SIGLIST_MISSING)
+/* Print to standard error the name of SIGNAL, preceded by MESSAGE and
+   a colon, and followed by a newline.  */
+void
+psignal (signal, message)
+     unsigned signal;
+     CONST char *message;
+{
+  if (signal <= 0 || signal >= NSIG)
+    fprintf (stderr, "%s: unknown signal", message);
+  else
+    fprintf (stderr, "%s: %s\n", message, sys_siglist[signal]);
+}
+#endif
+
+void
+_initialize_signame ()
+{
+       init_sigs ();
+}
diff --git a/gdb/signame.h b/gdb/signame.h
new file mode 100755 (executable)
index 0000000..83edfa8
--- /dev/null
@@ -0,0 +1,41 @@
+/* Convert between signal names and numbers.
+   Copyright (C) 1990 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 1, 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Names for signals from 0 to NSIG-1.  */
+extern char *sys_siglist[];
+
+#ifdef __STDC__
+/* Return the abbreviation (e.g. ABRT, FPE, etc.) for signal NUMBER.
+   Do not return this as a const char *.  The caller might want to
+   assign it to a char *.  */
+char *sig_abbrev (int number);
+
+/* Return the signal number for an ABBREV, or -1 if there is no
+   signal by that name.  */
+int sig_number (const char *abbrev);
+
+/* Print to standard error the name of SIGNAL, preceded by MESSAGE and
+   a colon, and followed by a newline.  */
+void psignal (unsigned signal, const char *message);
+
+#else
+
+char *sig_abbrev ();
+int sig_number ();
+void psignal ();
+
+#endif
diff --git a/gdb/solib.c b/gdb/solib.c
new file mode 100644 (file)
index 0000000..ab9336f
--- /dev/null
@@ -0,0 +1,245 @@
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+**     symbol definitions
+*/
+#include <sys/types.h>
+#include <string.h>
+#include <link.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "gdbcore.h"
+#include "command.h"
+
+/*
+**     local data declarations
+*/
+#define MAX_PATH_SIZE 256
+struct so_list {
+    struct link_map inferior_lm;               /* inferior link map */
+    struct link_map *inferior_lm_add;
+    long   ld_text;
+    char inferior_so_name[MAX_PATH_SIZE];      /* Shared Object Library Name */
+    struct so_list *next;                      /* Next Structure */
+    int        symbols_loaded;
+};
+
+static struct so_list *so_list_head = 0;
+
+/*=======================================================================*/
+
+/*     find_solib
+**
+**Description:
+**
+**     This module contains the routine which finds the names of any loaded
+**     "images" in the current process. The argument in must be NULL on the
+**     first call, and then the returned value must be passed in on
+**     subsequent calls. This provides the capability to "step" down the
+**     list of loaded objects. On the last object, a NULL value is returned.
+**     The arg and return value are "struct link_map" pointers, as defined
+**     in <link.h>.
+**
+**     NOTE: This only works under SunOS4.0.
+*/
+
+struct so_list *find_solib(so_list_ptr)
+struct so_list *so_list_ptr;                   /* so_list_head position ptr */
+{
+struct so_list *so_list_next = 0;
+CORE_ADDR inferior_dynamic_ptr = 0;
+struct link_map *inferior_lm = 0;
+struct link_dynamic inferior_dynamic_cpy;
+struct link_dynamic_2 inferior_ld_2_cpy;
+struct so_list *new;
+int i;
+
+     if (!so_list_ptr) {
+        if (!(so_list_next = so_list_head)) {
+            for (i = 0; i < misc_function_count; i++) {
+                if (!strcmp (misc_function_vector[i].name, "_DYNAMIC")) {
+                    inferior_dynamic_ptr = misc_function_vector[i].address;
+                    break;
+                }      
+            }          
+            if (inferior_dynamic_ptr) {
+                read_memory(inferior_dynamic_ptr, &inferior_dynamic_cpy, sizeof(struct link_dynamic));
+                if (inferior_dynamic_cpy.ld_version == 3) {
+                    read_memory((CORE_ADDR)inferior_dynamic_cpy.ld_un.ld_2,
+                                &inferior_ld_2_cpy,
+                                sizeof(struct link_dynamic_2));
+                    inferior_lm = inferior_ld_2_cpy.ld_loaded;
+                }
+            }
+        }
+     } else {
+        /*
+        ** Advance to next local abbreviated load_map structure
+        */
+        if (!(inferior_lm = so_list_ptr->inferior_lm.lm_next)) {
+            /* 
+            ** See if any were added
+            */
+            read_memory((CORE_ADDR)so_list_ptr->inferior_lm_add,
+                        &so_list_ptr->inferior_lm,
+                        sizeof(struct link_map));
+            inferior_lm = so_list_ptr->inferior_lm.lm_next;
+        }
+        so_list_next = so_list_ptr->next;
+     }
+     if ((!so_list_next) && inferior_lm) {
+        /* 
+        ** Get Next LM Structure from inferior image and build
+        ** an local abbreviated load_map structure
+        */
+        new = (struct so_list *) xmalloc(sizeof(struct so_list));
+         new->inferior_lm_add = inferior_lm;
+        read_memory((CORE_ADDR)inferior_lm,
+                    &new->inferior_lm,
+                    sizeof(struct link_map));
+
+        read_memory((CORE_ADDR)new->inferior_lm.lm_name,
+                    new->inferior_so_name,
+                    MAX_PATH_SIZE - 1);
+        new->inferior_so_name[MAX_PATH_SIZE - 1] = 0;
+        /* Zero everything after the first terminating null */
+        strncpy(new->inferior_so_name, new->inferior_so_name, MAX_PATH_SIZE);
+
+        read_memory((CORE_ADDR)new->inferior_lm.lm_ld,
+                    &inferior_dynamic_cpy,
+                    sizeof(struct link_dynamic));
+        read_memory((CORE_ADDR)inferior_dynamic_cpy.ld_un.ld_2,
+                    &inferior_ld_2_cpy,
+                    sizeof(struct link_dynamic_2));
+        new->ld_text = inferior_ld_2_cpy.ld_text;
+    
+        new->next = 0;
+        new->symbols_loaded = 0;
+        if (so_list_ptr)
+            so_list_ptr->next = new;
+        else
+            so_list_head = new;
+        so_list_next = new;
+     }
+     return(so_list_next);
+}
+/*=======================================================================*/
+
+static void solib_add(arg_string, from_tty)
+char *arg_string;
+int from_tty;
+{      
+    register struct so_list *so = 0;           /* link map state variable */
+    char *val;
+    int sz;
+
+    if (arg_string == 0)
+       re_comp (".");
+    else if (val = (char *) re_comp (arg_string)) {
+       error ("Invalid regexp: %s", val);
+    }
+    printf_filtered ("All shared libraries");
+    if (arg_string)
+      printf_filtered (" matching regular expresion \"%s\"", arg_string);
+    printf_filtered (":\n");
+    
+    dont_repeat();
+
+    while (so = find_solib(so)) {
+       if (re_exec(so->inferior_so_name)) {
+           if (so->symbols_loaded) {
+               printf("Symbols already loaded for %s\n", so->inferior_so_name);
+           } else {
+               /* File Name String Freed by processing */
+               sz = strlen(so->inferior_so_name) + 1;
+               val = (char *) xmalloc(sz);
+               bcopy(so->inferior_so_name, val, sz);
+               symbol_file_add (val, from_tty,
+                                (unsigned int)so->inferior_lm.lm_addr, 0);
+               so->symbols_loaded = 1;
+           }
+       }
+    }
+}
+/*=======================================================================*/
+
+static void solib_info()
+{
+register struct so_list *so = 0;       /* link map state variable */
+
+    while (so = find_solib(so)) {
+       if (so == so_list_head) {
+           printf("      Address Range      Symbols     Shared Object Library\n");
+       }
+       printf(" 0x%08x - 0x%08x   %s   %s\n", 
+           so->inferior_lm.lm_addr, 
+           so->inferior_lm.lm_addr + so->ld_text - 1,
+           (so->symbols_loaded ? "Yes" : "No "),
+           so->inferior_so_name);
+    }
+    if (!so_list_head) {
+       printf("No shared libraries loaded at this time.\n");   
+    }
+}
+
+/*
+** Called by Insert Breakpoint to see if Address is Shared Library Address 
+*/
+int
+solib_address(address)
+     CORE_ADDR address;
+{
+register struct so_list *so = 0;       /* link map state variable */
+
+    while (so = find_solib(so)) {
+       if ((address >= (CORE_ADDR) so->inferior_lm.lm_addr) &&
+           (address < (CORE_ADDR) so->inferior_lm.lm_addr + so->ld_text))
+         return 1;
+    }
+    return 0;
+}
+
+/*
+** Called by free_all_symtabs
+*/
+void 
+clear_solib()
+{
+struct so_list *next;
+
+  while (so_list_head) {
+    next = so_list_head->next;
+    free(so_list_head);
+    so_list_head = next;
+  }
+    
+}
+
+void
+_initialize_solib()
+{
+
+  add_com("sharedlibrary", class_files, solib_add,
+          "Load shared object library symbols for files matching REGEXP.");
+  add_info("sharedlibrary", solib_info, 
+          "Status of loaded shared object libraries");
+
+}
diff --git a/gdb/source.c b/gdb/source.c
new file mode 100644 (file)
index 0000000..ebc7041
--- /dev/null
@@ -0,0 +1,1186 @@
+/* List lines of source files for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "symtab.h"
+#include "param.h"
+#include "command.h"
+#include "frame.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "gdbcore.h"
+
+extern char *strstr();
+
+extern void set_next_address ();
+
+void mod_path ();
+
+/* Path of directories to search for source files.
+   Same format as the PATH environment variable's value.  */
+
+char *source_path;
+
+/* Symtab of default file for listing lines of.  */
+
+struct symtab *current_source_symtab;
+
+/* Default next line to list.  */
+
+int current_source_line;
+
+/* Line number of last line printed.  Default for various commands.
+   current_source_line is usually, but not always, the same as this.  */
+
+static int last_line_listed;
+
+/* First line number listed by last listing command.  */
+
+static int first_line_listed;
+
+\f
+/* Set the source file default for the "list" command, specifying a
+   symtab.  Sigh.  Behavior specification: If it is called with a
+   non-zero argument, that is the symtab to select.  If it is not,
+   first lookup "main"; if it exists, use the symtab and line it
+   defines.  If not, take the last symtab in the symtab_list (if it
+   exists) or the last symtab in the psymtab_list (if *it* exists).  If
+   none of this works, report an error.   */
+
+void
+select_source_symtab (s)
+     register struct symtab *s;
+{
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  struct partial_symtab *ps;
+  struct partial_symtab *cs_pst = 0;
+  
+  if (s)
+    {
+      current_source_symtab = s;
+      current_source_line = 1;
+      return;
+    }
+
+  /* Make the default place to list be the function `main'
+     if one exists.  */
+  if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0, NULL))
+    {
+      sals = decode_line_spec ("main", 1);
+      sal = sals.sals[0];
+      free (sals.sals);
+      current_source_symtab = sal.symtab;
+      current_source_line = max (sal.line - (lines_to_list () - 1), 1);
+      return;
+    }
+  
+  /* All right; find the last file in the symtab list (ignoring .h's).  */
+
+  if (s = symtab_list)
+    {
+      do
+       {
+         char *name = s->filename;
+         int len = strlen (name);
+         if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
+           current_source_symtab = s;
+         s = s->next;
+       }
+      while (s);
+      current_source_line = 1;
+    }
+  else if (partial_symtab_list)
+    {
+      ps = partial_symtab_list;
+      while (ps)
+       {
+         char *name = ps->filename;
+         int len = strlen (name);
+         if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
+           cs_pst = ps;
+         ps = ps->next;
+       }
+      if (cs_pst)
+       if (cs_pst->readin)
+         fatal ("Internal: select_source_symtab: readin pst found and no symtabs.");
+       else
+         current_source_symtab = PSYMTAB_TO_SYMTAB (cs_pst);
+      else
+       current_source_symtab = 0;
+      current_source_line = 1;
+    }
+}
+\f
+static void
+directories_info ()
+{
+  printf ("Source directories searched: %s\n", source_path);
+}
+
+/* Forget what we learned about line positions in source files,
+   and which directories contain them;
+   must check again now since files may be found in
+   a different directory now.  */
+
+void
+forget_cached_source_info ()
+{
+  register struct symtab *s;
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      if (s->line_charpos != 0)
+       {
+         free (s->line_charpos);
+         s->line_charpos = 0;
+       }
+      if (s->fullname != 0)
+       {
+         free (s->fullname);
+         s->fullname = 0;
+       }
+    }
+}
+
+void
+init_source_path ()
+{
+  source_path = savestring ("$cdir:$cwd", /* strlen of it */ 10);
+  forget_cached_source_info ();
+}
+
+/* Add zero or more directories to the front of the source path.  */
+void
+directory_command (dirname, from_tty)
+     char *dirname;
+     int from_tty;
+{
+  dont_repeat ();
+  /* FIXME, this goes to "delete dir"... */
+  if (dirname == 0)
+    {
+      if (query ("Reinitialize source path to empty? ", ""))
+       {
+         free (source_path);
+         init_source_path ();
+       }
+    }
+  else
+    mod_path (dirname, from_tty, &source_path);
+  if (from_tty)
+    directories_info ();
+  forget_cached_source_info ();
+}
+
+/* Add zero or more directories to the front of an arbitrary path.  */
+
+void
+mod_path (dirname, from_tty, which_path)
+     char *dirname;
+     int from_tty;
+     char **which_path;
+{
+  char *old = *which_path;
+  int prefix = 0;
+
+  if (dirname == 0)
+    return;
+
+  dirname = strsave (dirname);
+  make_cleanup (free, dirname);
+
+  do
+    {
+      extern char *index ();
+      char *name = dirname;
+      register char *p;
+      struct stat st;
+
+      {
+       char *colon = index (name, ':');
+       char *space = index (name, ' ');
+       char *tab = index (name, '\t');
+       if (colon == 0 && space == 0 && tab ==  0)
+         p = dirname = name + strlen (name);
+       else
+         {
+           p = 0;
+           if (colon != 0 && (p == 0 || colon < p))
+             p = colon;
+           if (space != 0 && (p == 0 || space < p))
+             p = space;
+           if (tab != 0 && (p == 0 || tab < p))
+             p = tab;
+           dirname = p + 1;
+           while (*dirname == ':' || *dirname == ' ' || *dirname == '\t')
+             ++dirname;
+         }
+      }
+
+      if (p[-1] == '/')
+       /* Sigh. "foo/" => "foo" */
+       --p;
+      *p = '\0';
+
+      while (p[-1] == '.')
+       {
+         if (p - name == 1)
+           {
+             /* "." => getwd ().  */
+             name = current_directory;
+             goto append;
+           }
+         else if (p[-2] == '/')
+           {
+             if (p - name == 2)
+               {
+                 /* "/." => "/".  */
+                 *--p = '\0';
+                 goto append;
+               }
+             else
+               {
+                 /* "...foo/." => "...foo".  */
+                 p -= 2;
+                 *p = '\0';
+                 continue;
+               }
+           }
+         else
+           break;
+       }
+
+      if (name[0] == '~')
+       name = tilde_expand (name);
+      else if (name[0] != '/' && name[0] != '$')
+       name = concat (current_directory, "/", name);
+      else
+       name = savestring (name, p - name);
+      make_cleanup (free, name);
+
+      /* Unless it's a variable, check existence.  */
+      if (name[0] != '$') {
+       if (stat (name, &st) < 0)
+         perror_with_name (name);
+       if ((st.st_mode & S_IFMT) != S_IFDIR)
+         error ("%s is not a directory.", name);
+      }
+
+    append:
+      {
+       register unsigned int len = strlen (name);
+
+       p = *which_path;
+       while (1)
+         {
+           if (!strncmp (p, name, len)
+               && (p[len] == '\0' || p[len] == ':'))
+             {
+               /* Found it in the search path, remove old copy */
+               if (p > *which_path)
+                 p--;                  /* Back over leading colon */
+               if (prefix > p - *which_path)
+                 goto skip_dup;        /* Same dir twice in one cmd */
+               strcpy (p, &p[len+1]);  /* Copy from next \0 or  : */
+             }
+           p = index (p, ':');
+           if (p != 0)
+             ++p;
+           else
+             break;
+         }
+       if (p == 0)
+         {
+           /* If we have already tacked on a name(s) in this command,                     be sure they stay on the front as we tack on some more.  */
+           if (prefix)
+             {
+               char *temp, c;
+
+               c = old[prefix];
+               old[prefix] = '\0';
+               temp = concat (old, ":", name);
+               old[prefix] = c;
+               *which_path = concat (temp, "", &old[prefix]);
+               prefix = strlen (temp);
+               free (temp);
+             }
+           else
+             {
+               *which_path = concat (name, (old[0]? ":" : old), old);
+               prefix = strlen (name);
+             }
+           free (old);
+           old = *which_path;
+         }
+      }
+  skip_dup: ;
+    } while (*dirname != '\0');
+}
+
+
+static void
+source_info ()
+{
+  register struct symtab *s = current_source_symtab;
+
+  if (!s)
+    {
+      printf("No current source file.\n");
+      return;
+    }
+  printf ("Current source file is %s\n", s->filename);
+  if (s->dirname)
+    printf ("Compilation directory is %s\n", s->dirname);
+  if (s->fullname)
+    printf ("Located in %s\n", s->fullname);
+  if (s->nlines)
+    printf ("Contains %d lines\n", s->nlines);
+
+  switch (s->language) {
+  case language_c:
+    printf("Written in the C language.\n");
+  /* Add more cases here when -Wswitch complains... */
+  case language_unknown:
+    break;
+  }
+}
+
+
+\f
+/* Open a file named STRING, searching path PATH (dir names sep by colons)
+   using mode MODE and protection bits PROT in the calls to open.
+   If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
+   (ie pretend the first element of PATH is ".")
+   If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
+   the actual file opened (this string will always start with a "/".  We
+   have to take special pains to avoid doubling the "/" between the directory
+   and the file, sigh!  Emacs gets confuzzed by this when we print the
+   source file name!!! 
+
+   If a file is found, return the descriptor.
+   Otherwise, return -1, with errno set for the last name we tried to open.  */
+
+/*  >>>> This should only allow files of certain types,
+    >>>>  eg executable, non-directory */
+int
+openp (path, try_cwd_first, string, mode, prot, filename_opened)
+     char *path;
+     int try_cwd_first;
+     char *string;
+     int mode;
+     int prot;
+     char **filename_opened;
+{
+  register int fd;
+  register char *filename;
+  register char *p, *p1;
+  register int len;
+  int alloclen;
+
+  if (!path)
+    path = ".";
+
+  /* ./foo => foo */
+  while (string[0] == '.' && string[1] == '/')
+    string += 2;
+
+  if (try_cwd_first || string[0] == '/')
+    {
+      filename = string;
+      fd = open (filename, mode, prot);
+      if (fd >= 0 || string[0] == '/')
+       goto done;
+    }
+
+  alloclen = strlen (path) + strlen (string) + 2;
+  filename = (char *) alloca (alloclen);
+  fd = -1;
+  for (p = path; p; p = p1 ? p1 + 1 : 0)
+    {
+      p1 = (char *) index (p, ':');
+      if (p1)
+       len = p1 - p;
+      else
+       len = strlen (p);
+
+      if (len == 4 && p[0] == '$' && p[1] == 'c'
+                  && p[2] == 'w' && p[3] == 'd') {
+       /* Name is $cwd -- insert current directory name instead.  */
+       int newlen;
+
+       /* First, realloc the filename buffer if too short. */
+       len = strlen (current_directory);
+       newlen = len + strlen (string) + 2;
+       if (newlen > alloclen) {
+         alloclen = newlen;
+         filename = (char *) alloca (alloclen);
+       }
+       strcpy (filename, current_directory);
+      } else {
+       /* Normal file name in path -- just use it.  */
+       strncpy (filename, p, len);
+       filename[len] = 0;
+      }
+
+      /* Beware the // my son, the Emacs barfs, the botch that catch... */
+      while (len > 1 && filename[len-1] == '/')
+       filename[--len] = 0;
+      strcat (filename+len, "/");
+      strcat (filename, string);
+
+      fd = open (filename, mode, prot);
+      if (fd >= 0) break;
+    }
+
+ done:
+  if (filename_opened)
+    if (fd < 0)
+      *filename_opened = (char *) 0;
+    else if (filename[0] == '/')
+      *filename_opened = savestring (filename, strlen (filename));
+    else
+      {
+       /* Beware the // my son, the Emacs barfs, the botch that catch... */
+          
+       *filename_opened = concat (current_directory, 
+          '/' == current_directory[strlen(current_directory)-1]? "": "/",
+                                  filename);
+      }
+
+  return fd;
+}
+
+/* Open a source file given a symtab S.  Returns a file descriptor
+   or negative number for error.  */
+int
+open_source_file (s)
+     struct symtab *s;
+{
+  char *path = source_path;
+  char *p;
+  int result;
+
+  /* Quick way out if we already know its full name */
+  if (s->fullname) 
+    {
+      result = open (s->fullname, O_RDONLY);
+      if (result >= 0)
+        return result;
+      /* Didn't work -- free old one, try again. */
+      free (s->fullname);
+      s->fullname = NULL;
+    }
+
+  if (s->dirname != NULL)
+    {
+      /* Replace a path entry of  $cdir  with the compilation directory name */
+#define        cdir_len        5
+      p = strstr (source_path, "$cdir");
+      if (p && (p == path || p[-1] == ':')
+           && (p[cdir_len] == ':' || p[cdir_len] == '\0')) {
+       int len;
+
+       path = (char *)
+              alloca (strlen (source_path) + 1 + strlen (s->dirname) + 1);
+       len = p - source_path;
+       strncpy (path, source_path, len);               /* Before $cdir */
+       strcpy (path + len, s->dirname);                /* new stuff */
+       strcat (path + len, source_path + len + cdir_len); /* After $cdir */
+      }
+    }
+
+  return openp (path, 0, s->filename, O_RDONLY, 0, &s->fullname);
+}
+
+\f
+/* Create and initialize the table S->line_charpos that records
+   the positions of the lines in the source file, which is assumed
+   to be open on descriptor DESC.
+   All set S->nlines to the number of such lines.  */
+
+static void
+find_source_lines (s, desc)
+     struct symtab *s;
+     int desc;
+{
+  struct stat st;
+  register char *data, *p, *end;
+  int nlines = 0;
+  int lines_allocated = 1000;
+  int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
+
+  if (fstat (desc, &st) < 0)
+    perror_with_name (s->filename);
+  if (exec_bfd && bfd_get_mtime(exec_bfd) < st.st_mtime)
+    printf ("Source file is more recent than executable.\n");
+
+#if defined (BROKEN_LARGE_ALLOCA)
+  data = (char *) xmalloc (st.st_size);
+  make_cleanup (free, data);
+#else
+  data = (char *) alloca (st.st_size);
+#endif
+  if (myread (desc, data, st.st_size) < 0)
+    perror_with_name (s->filename);
+  end = data + st.st_size;
+  p = data;
+  line_charpos[0] = 0;
+  nlines = 1;
+  while (p != end)
+    {
+      if (*p++ == '\n'
+         /* A newline at the end does not start a new line.  */
+         && p != end)
+       {
+         if (nlines == lines_allocated)
+           {
+             lines_allocated *= 2;
+             line_charpos = (int *) xrealloc (line_charpos,
+                                              sizeof (int) * lines_allocated);
+           }
+         line_charpos[nlines++] = p - data;
+       }
+    }
+  s->nlines = nlines;
+  s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
+}
+
+/* Return the character position of a line LINE in symtab S.
+   Return 0 if anything is invalid.  */
+
+int
+source_line_charpos (s, line)
+     struct symtab *s;
+     int line;
+{
+  if (!s) return 0;
+  if (!s->line_charpos || line <= 0) return 0;
+  if (line > s->nlines)
+    line = s->nlines;
+  return s->line_charpos[line - 1];
+}
+
+/* Return the line number of character position POS in symtab S.  */
+
+int
+source_charpos_line (s, chr)
+    register struct symtab *s;
+    register int chr;
+{
+  register int line = 0;
+  register int *lnp;
+    
+  if (s == 0 || s->line_charpos == 0) return 0;
+  lnp = s->line_charpos;
+  /* Files are usually short, so sequential search is Ok */
+  while (line < s->nlines  && *lnp <= chr)
+    {
+      line++;
+      lnp++;
+    }
+  if (line >= s->nlines)
+    line = s->nlines;
+  return line;
+}
+\f
+/* Get full pathname and line number positions for a symtab.
+   Return nonzero if line numbers may have changed.
+   Set *FULLNAME to actual name of the file as found by `openp',
+   or to 0 if the file is not found.  */
+
+int
+get_filename_and_charpos (s, fullname)
+     struct symtab *s;
+     char **fullname;
+{
+  register int desc, linenums_changed = 0;
+  
+  desc = open_source_file (s);
+  if (desc < 0)
+    {
+      if (fullname)
+       *fullname = NULL;
+      return 0;
+    }  
+  if (fullname)
+    *fullname = s->fullname;
+  if (s->line_charpos == 0) linenums_changed = 1;
+  if (linenums_changed) find_source_lines (s, desc);
+  close (desc);
+  return linenums_changed;
+}
+
+/* Print text describing the full name of the source file S
+   and the line number LINE and its corresponding character position.
+   The text starts with two Ctrl-z so that the Emacs-GDB interface
+   can easily find it.
+
+   MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
+
+   Return 1 if successful, 0 if could not find the file.  */
+
+int
+identify_source_line (s, line, mid_statement)
+     struct symtab *s;
+     int line;
+     int mid_statement;
+{
+  if (s->line_charpos == 0)
+    get_filename_and_charpos (s, (char **)NULL);
+  if (s->fullname == 0)
+    return 0;
+  printf ("\032\032%s:%d:%d:%s:0x%x\n", s->fullname,
+         line, s->line_charpos[line - 1],
+         mid_statement ? "middle" : "beg",
+         get_frame_pc (get_current_frame()));
+  current_source_line = line;
+  first_line_listed = line;
+  last_line_listed = line;
+  current_source_symtab = s;
+  return 1;
+}
+\f
+/* Print source lines from the file of symtab S,
+   starting with line number LINE and stopping before line number STOPLINE.  */
+
+void
+print_source_lines (s, line, stopline, noerror)
+     struct symtab *s;
+     int line, stopline;
+     int noerror;
+{
+  register int c;
+  register int desc;
+  register FILE *stream;
+  int nlines = stopline - line;
+
+  /* Regardless of whether we can open the file, set current_source_symtab. */
+  current_source_symtab = s;
+  current_source_line = line;
+  first_line_listed = line;
+
+  desc = open_source_file (s);
+  if (desc < 0)
+    {
+      if (! noerror) {
+       char *name = alloca (strlen (s->filename) + 100);
+       sprintf (name, "%s:%d", s->filename, line);
+        print_sys_errmsg (name, errno);
+      }
+      return;
+    }
+
+  if (s->line_charpos == 0)
+    find_source_lines (s, desc);
+
+  if (line < 1 || line > s->nlines)
+    {
+      close (desc);
+      error ("Line number %d out of range; %s has %d lines.",
+            line, s->filename, s->nlines);
+    }
+
+  if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
+    {
+      close (desc);
+      perror_with_name (s->filename);
+    }
+
+  stream = fdopen (desc, "r");
+  clearerr (stream);
+
+  while (nlines-- > 0)
+    {
+      c = fgetc (stream);
+      if (c == EOF) break;
+      last_line_listed = current_source_line;
+      printf_filtered ("%d\t", current_source_line++);
+      do
+       {
+         if (c < 040 && c != '\t' && c != '\n')
+             printf_filtered ("^%c", c + 0100);
+         else if (c == 0177)
+           printf_filtered ("^?");
+         else
+           printf_filtered ("%c", c);
+       } while (c != '\n' && (c = fgetc (stream)) >= 0);
+    }
+
+  fclose (stream);
+}
+\f
+
+
+/* 
+  C++
+  Print a list of files and line numbers which a user may choose from
+  in order to list a function which was specified ambiguously
+  (as with `list classname::overloadedfuncname', for example).
+  The vector in SALS provides the filenames and line numbers.
+  */
+static void
+ambiguous_line_spec (sals)
+     struct symtabs_and_lines *sals;
+{
+  int i;
+
+  for (i = 0; i < sals->nelts; ++i)
+    printf("file: \"%s\", line number: %d\n",
+          sals->sals[i].symtab->filename, sals->sals[i].line);
+}
+
+
+static void
+list_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtabs_and_lines sals, sals_end;
+  struct symtab_and_line sal, sal_end;
+  struct symbol *sym;
+  char *arg1;
+  int no_end = 1;
+  int dummy_end = 0;
+  int dummy_beg = 0;
+  int linenum_beg = 0;
+  char *p;
+
+  if (symtab_list == 0 && partial_symtab_list == 0)
+    error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
+
+  /* Pull in a current source symtab if necessary */
+  if (current_source_symtab == 0 &&
+      (arg == 0 || arg[0] == '+' || arg[0] == '-'))
+    select_source_symtab (0);
+
+  /* "l" or "l +" lists next ten lines.  */
+
+  if (arg == 0 || !strcmp (arg, "+"))
+    {
+      if (current_source_symtab == 0)
+       error ("No default source file yet.  Do \"help list\".");
+      print_source_lines (current_source_symtab, current_source_line,
+                         current_source_line + lines_to_list (), 0);
+      return;
+    }
+
+  /* "l -" lists previous ten lines, the ones before the ten just listed.  */
+  if (!strcmp (arg, "-"))
+    {
+      if (current_source_symtab == 0)
+       error ("No default source file yet.  Do \"help list\".");
+      print_source_lines (current_source_symtab,
+                         max (first_line_listed - lines_to_list (), 1),
+                         first_line_listed, 0);
+      return;
+    }
+
+  /* Now if there is only one argument, decode it in SAL
+     and set NO_END.
+     If there are two arguments, decode them in SAL and SAL_END
+     and clear NO_END; however, if one of the arguments is blank,
+     set DUMMY_BEG or DUMMY_END to record that fact.  */
+
+  arg1 = arg;
+  if (*arg1 == ',')
+    dummy_beg = 1;
+  else
+    {
+      sals = decode_line_1 (&arg1, 0, 0, 0);
+
+      if (! sals.nelts) return;  /*  C++  */
+      if (sals.nelts > 1)
+       {
+         ambiguous_line_spec (&sals);
+         free (sals.sals);
+         return;
+       }
+
+      sal = sals.sals[0];
+      free (sals.sals);
+    }
+
+  /* Record whether the BEG arg is all digits.  */
+
+  for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
+  linenum_beg = (p == arg1);
+
+  while (*arg1 == ' ' || *arg1 == '\t')
+    arg1++;
+  if (*arg1 == ',')
+    {
+      no_end = 0;
+      arg1++;
+      while (*arg1 == ' ' || *arg1 == '\t')
+       arg1++;
+      if (*arg1 == 0)
+       dummy_end = 1;
+      else
+       {
+         if (dummy_beg)
+           sals_end = decode_line_1 (&arg1, 0, 0, 0);
+         else
+           sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
+         if (sals_end.nelts == 0) 
+           return;
+         if (sals_end.nelts > 1)
+           {
+             ambiguous_line_spec (&sals_end);
+             free (sals_end.sals);
+             return;
+           }
+         sal_end = sals_end.sals[0];
+         free (sals_end.sals);
+       }
+    }
+
+  if (*arg1)
+    error ("Junk at end of line specification.");
+
+  if (!no_end && !dummy_beg && !dummy_end
+      && sal.symtab != sal_end.symtab)
+    error ("Specified start and end are in different files.");
+  if (dummy_beg && dummy_end)
+    error ("Two empty args do not say what lines to list.");
+  /* if line was specified by address,
+     first print exactly which line, and which file.
+     In this case, sal.symtab == 0 means address is outside
+     of all known source files, not that user failed to give a filename.  */
+  if (*arg == '*')
+    {
+      if (sal.symtab == 0)
+       error ("No source file for address 0x%x.", sal.pc);
+      sym = find_pc_function (sal.pc);
+      if (sym)
+       printf ("0x%x is in %s (%s, line %d).\n",
+               sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
+      else
+       printf ("0x%x is in %s, line %d.\n",
+               sal.pc, sal.symtab->filename, sal.line);
+    }
+
+  /* If line was not specified by just a line number,
+     and it does not imply a symtab, it must be an undebuggable symbol
+     which means no source code.  */
+
+  if (! linenum_beg && sal.symtab == 0)
+    error ("No line number known for %s.", arg);
+
+  /* If this command is repeated with RET,
+     turn it into the no-arg variant.  */
+
+  if (from_tty)
+    *arg = 0;
+
+  if (dummy_beg && sal_end.symtab == 0)
+    error ("No default source file yet.  Do \"help list\".");
+  if (dummy_beg)
+    print_source_lines (sal_end.symtab,
+                       max (sal_end.line - (lines_to_list () - 1), 1),
+                       sal_end.line + 1, 0);
+  else if (sal.symtab == 0)
+    error ("No default source file yet.  Do \"help list\".");
+  else if (no_end)
+    print_source_lines (sal.symtab,
+                       max (sal.line - (lines_to_list () / 2), 1),
+                       sal.line + 5, 0);
+  else
+    print_source_lines (sal.symtab, sal.line,
+                       (dummy_end
+                        ? sal.line + lines_to_list ()
+                        : sal_end.line + 1),
+                       0);
+}
+\f
+/* Print info on range of pc's in a specified line.  */
+
+static void
+line_info (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  CORE_ADDR start_pc, end_pc;
+  int i;
+
+  if (arg == 0)
+    {
+      sal.symtab = current_source_symtab;
+      sal.line = last_line_listed;
+      sals.nelts = 1;
+      sals.sals = (struct symtab_and_line *)
+       xmalloc (sizeof (struct symtab_and_line));
+      sals.sals[0] = sal;
+    }
+  else
+    {
+      sals = decode_line_spec_1 (arg, 0);
+      
+      /* If this command is repeated with RET,
+        turn it into the no-arg variant.  */
+      if (from_tty)
+       *arg = 0;
+    }
+
+  /* C++  More than one line may have been specified, as when the user
+     specifies an overloaded function name. Print info on them all. */
+  for (i = 0; i < sals.nelts; i++)
+    {
+      sal = sals.sals[i];
+      
+      if (sal.symtab == 0)
+       error ("No source file specified.");
+
+      if (sal.line > 0
+         && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
+       {
+         if (start_pc == end_pc)
+           printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n",
+                   sal.line, sal.symtab->filename, start_pc);
+         else
+           printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n",
+                   sal.line, sal.symtab->filename, start_pc, end_pc);
+         /* x/i should display this line's code.  */
+         set_next_address (start_pc);
+         /* Repeating "info line" should do the following line.  */
+         last_line_listed = sal.line + 1;
+       }
+      else
+       printf ("Line number %d is out of range for \"%s\".\n",
+               sal.line, sal.symtab->filename);
+    }
+}
+\f
+/* Commands to search the source file for a regexp.  */
+
+static void
+forward_search_command (regex, from_tty)
+     char *regex;
+     int from_tty;
+{
+  register int c;
+  register int desc;
+  register FILE *stream;
+  int line = last_line_listed + 1;
+  char *msg;
+
+  msg = (char *) re_comp (regex);
+  if (msg)
+    error (msg);
+
+  if (current_source_symtab == 0)
+    select_source_symtab (0);
+
+  /* Search from last_line_listed+1 in current_source_symtab */
+
+  desc = open_source_file (current_source_symtab);
+  if (desc < 0)
+    perror_with_name (current_source_symtab->filename);
+
+  if (current_source_symtab->line_charpos == 0)
+    find_source_lines (current_source_symtab, desc);
+
+  if (line < 1 || line > current_source_symtab->nlines)
+    {
+      close (desc);
+      error ("Expression not found");
+    }
+
+  if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
+    {
+      close (desc);
+      perror_with_name (current_source_symtab->filename);
+    }
+
+  stream = fdopen (desc, "r");
+  clearerr (stream);
+  while (1) {
+    char buf[4096];            /* Should be reasonable??? */
+    register char *p = buf;
+
+    c = fgetc (stream);
+    if (c == EOF)
+      break;
+    do {
+      *p++ = c;
+    } while (c != '\n' && (c = fgetc (stream)) >= 0);
+
+    /* we now have a source line in buf, null terminate and match */
+    *p = 0;
+    if (re_exec (buf) > 0)
+      {
+       /* Match! */
+       fclose (stream);
+       print_source_lines (current_source_symtab,
+                          line, line+1, 0);
+       current_source_line = max (line - lines_to_list () / 2, 1);
+       return;
+      }
+    line++;
+  }
+
+  printf ("Expression not found\n");
+  fclose (stream);
+}
+
+static void
+reverse_search_command (regex, from_tty)
+     char *regex;
+     int from_tty;
+{
+  register int c;
+  register int desc;
+  register FILE *stream;
+  int line = last_line_listed - 1;
+  char *msg;
+
+  msg = (char *) re_comp (regex);
+  if (msg)
+    error (msg);
+
+  if (current_source_symtab == 0)
+    select_source_symtab (0);
+
+  /* Search from last_line_listed-1 in current_source_symtab */
+
+  desc = open_source_file (current_source_symtab);
+  if (desc < 0)
+    perror_with_name (current_source_symtab->filename);
+
+  if (current_source_symtab->line_charpos == 0)
+    find_source_lines (current_source_symtab, desc);
+
+  if (line < 1 || line > current_source_symtab->nlines)
+    {
+      close (desc);
+      error ("Expression not found");
+    }
+
+  if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
+    {
+      close (desc);
+      perror_with_name (current_source_symtab->filename);
+    }
+
+  stream = fdopen (desc, "r");
+  clearerr (stream);
+  while (line > 1)
+    {
+      char buf[4096];          /* Should be reasonable??? */
+      register char *p = buf;
+
+      c = fgetc (stream);
+      if (c == EOF)
+       break;
+      do {
+       *p++ = c;
+      } while (c != '\n' && (c = fgetc (stream)) >= 0);
+
+      /* We now have a source line in buf; null terminate and match.  */
+      *p = 0;
+      if (re_exec (buf) > 0)
+       {
+         /* Match! */
+         fclose (stream);
+         print_source_lines (current_source_symtab,
+                             line, line+1, 0);
+         current_source_line = max (line - lines_to_list () / 2, 1);
+         return;
+       }
+      line--;
+      if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
+       {
+         fclose (stream);
+         perror_with_name (current_source_symtab->filename);
+       }
+    }
+
+  printf ("Expression not found\n");
+  fclose (stream);
+  return;
+}
+\f
+void
+_initialize_source ()
+{
+  current_source_symtab = 0;
+  init_source_path ();
+
+  add_com ("directory", class_files, directory_command,
+          "Add directory DIR to beginning of search path for source files.\n\
+Forget cached info on source file locations and line positions.\n\
+DIR can also be $cwd for the current working directory, or $cdir for the\n\
+directory in which the source file was compiled into object code.\n\
+With no argument, reset the search path to $cdir:$cwd, the default.");
+
+  add_info ("directories", directories_info,
+           "Current search path for finding source files.\n\
+$cwd in the path means the current working directory.\n\
+$cdir in the path means the compilation directory of the source file.");
+
+  add_info ("source", source_info,
+           "Information about the current source file.");
+
+  add_info ("line", line_info,
+           "Core addresses of the code for a source line.\n\
+Line can be specified as\n\
+  LINENUM, to list around that line in current file,\n\
+  FILE:LINENUM, to list around that line in that file,\n\
+  FUNCTION, to list around beginning of that function,\n\
+  FILE:FUNCTION, to distinguish among like-named static functions.\n\
+Default is to describe the last source line that was listed.\n\n\
+This sets the default address for \"x\" to the line's first instruction\n\
+so that \"x/i\" suffices to start examining the machine code.\n\
+The address is also stored as the value of \"$_\".");
+
+  add_com ("forward-search", class_files, forward_search_command,
+          "Search for regular expression (see regex(3)) from last line listed.");
+  add_com_alias ("search", "forward-search", class_files, 0);
+
+  add_com ("reverse-search", class_files, reverse_search_command,
+          "Search backward for regular expression (see regex(3)) from last line listed.");
+
+  add_com ("list", class_files, list_command,
+          "List specified function or line.\n\
+With no argument, lists ten more lines after or around previous listing.\n\
+\"list -\" lists the ten lines before a previous ten-line listing.\n\
+One argument specifies a line, and ten lines are listed around that line.\n\
+Two arguments with comma between specify starting and ending lines to list.\n\
+Lines can be specified in these ways:\n\
+  LINENUM, to list around that line in current file,\n\
+  FILE:LINENUM, to list around that line in that file,\n\
+  FUNCTION, to list around beginning of that function,\n\
+  FILE:FUNCTION, to distinguish among like-named static functions.\n\
+  *ADDRESS, to list around the line containing that address.\n\
+With two args if one is empty it stands for ten lines away from the other arg.");
+  add_com_alias ("l", "list", class_files, 0);
+}
+
diff --git a/gdb/sparc-opcode.h b/gdb/sparc-opcode.h
new file mode 100755 (executable)
index 0000000..473ab6f
--- /dev/null
@@ -0,0 +1,641 @@
+/* Table of opcodes for the sparc.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB 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 1, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+struct sparc_opcode
+{
+    const char *name;
+    unsigned long int match;   /* Bits that must be set.  */
+    unsigned long int lose;    /* Bits that must not be set.  */
+    const char *args;
+    char flags;
+};
+
+#define        F_DELAYED       1       /* Delayed branch */
+#define        F_ALIAS         2       /* Alias for a "real" instruction */
+
+/*
+   All sparc opcodes are 32 bits, except for the `set' instruction (really
+   a macro), which is 64 bits.  It is handled as a special case.
+
+   The match component is a mask saying which bits must match a
+   particular opcode in order for an instruction to be an instance
+   of that opcode.
+
+   The args component is a string containing one character
+   for each operand of the instruction.
+
+Kinds of operands:
+   #    Number used by optimizer.  It is ignored.
+   1    rs1 register.
+   2    rs2 register.
+   d    rd register.
+   e    frs1 floating point register.
+   f    frs2 floating point register.
+   g    frsd floating point register.
+   b    crs1 coprocessor register
+   c    crs2 coprocessor register
+   D    crsd coprocessor register
+   h    22 high bits.
+   i    13 bit Immediate.
+   l    22 bit PC relative immediate.
+   L    30 bit PC relative immediate.
+   a    Annul.  The annul bit is set.
+   A    Alternate address space.  Stored as 8 bits.
+   C    Coprocessor state register.
+   F    floating point state register.
+   p    Processor state register.
+   q    Floating point queue.
+   r    Single register that is both rs1 and rsd.
+   Q    Coprocessor queue.
+   S    Special case.
+   t    Trap base register.
+   w    Window invalid mask register.
+   y    Y register.
+
+*/
+
+/* The order of the opcodes in this table is significant:
+   
+   * The assembler requires that all instances of the same mnemonic must be
+   consecutive.  If they aren't, the assembler will bomb at runtime.
+
+   * The disassembler should not care about the order of the opcodes.  */
+
+static struct sparc_opcode sparc_opcodes[] =
+{
+
+{ "ldd",        0xc1980000, 0x0060201f, "[1],D", 0 }, /* ldd [rs1+%g0],d */
+{ "ldd",        0xc1982000, 0x00601fff, "[1],D", 0 }, /* ldd [rs1+0],d */
+{ "ldd",        0xc1982000, 0x00600000, "[1+i],D", 0 },
+{ "ldd",        0xc1982000, 0x00600000, "[i+1],D", 0 },
+{ "ldd",        0xc1980000, 0x00602000, "[1+2],D", 0 },
+{ "ldd",        0xc1180000, 0x00e0201f, "[1],g", 0 }, /* ldd [rs1+%g0],d */
+{ "ldd",        0xc1182000, 0x00e01fff, "[1],g", 0 }, /* ldd [rs1+0],d */
+{ "ldd",        0xc1182000, 0x00e00000, "[1+i],g", 0 },
+{ "ldd",        0xc1182000, 0x00e00000, "[i+1],g", 0 },
+{ "ldd",        0xc1180000, 0x00e02000, "[1+2],g", 0 },
+{ "ldd",       0xc0180000, 0x01e0201f, "[1],d", 0 }, /* ldd [rs1+%g0],d */
+{ "ldd",        0xc0182000, 0x01e01fff, "[1],d", 0 }, /* ldd [rs1+0],d */
+{ "ldd",       0xc0182000, 0x01e00000, "[1+i],d", 0 },
+{ "ldd",       0xc0182000, 0x01e00000, "[i+1],d", 0 },
+{ "ldd",       0xc0180000, 0x01e02000, "[1+2],d", 0 },
+{ "ld",         0xc1880000, 0x0070201f, "[1],C", 0 }, /* ld [rs1+%g0],d */
+{ "ld",         0xc1882000, 0x00701fff, "[1],C", 0 }, /* ld [rs1+0],d */
+{ "ld",         0xc1882000, 0x00700000, "[1+i],C", 0 },
+{ "ld",         0xc1882000, 0x00700000, "[i+1],C", 0 },
+{ "ld",         0xc1880000, 0x00702000, "[1+2],C", 0 },
+{ "ld",         0xc1800000, 0x0078201f, "[1],D", 0 }, /* ld [rs1+%g0],d */
+{ "ld",         0xc1802000, 0x00781fff, "[1],D", 0 }, /* ld [rs1+0],d */
+{ "ld",         0xc1802000, 0x00780000, "[1+i],D", 0 },
+{ "ld",         0xc1802000, 0x00780000, "[i+1],D", 0 },
+{ "ld",         0xc1800000, 0x00782000, "[1+2],D", 0 },
+{ "ld",         0xc1080000, 0x00f0201f, "[1],F", 0 }, /* ld [rs1+%g0],d */
+{ "ld",         0xc1082000, 0x00f01fff, "[1],F", 0 }, /* ld [rs1+0],d */
+{ "ld",         0xc1082000, 0x00f00000, "[1+i],F", 0 },
+{ "ld",         0xc1082000, 0x00f00000, "[i+1],F", 0 },
+{ "ld",         0xc1080000, 0x00f02000, "[1+2],F", 0 },
+{ "ld",         0xc1000000, 0x00f8201f, "[1],g", 0 }, /* ld [rs1+%g0],d */
+{ "ld",         0xc1002000, 0x00f81fff, "[1],g", 0 }, /* ld [rs1+0],d */
+{ "ld",         0xc1002000, 0x00f80000, "[1+i],g", 0 },
+{ "ld",         0xc1002000, 0x00f80000, "[i+1],g", 0 },
+{ "ld",         0xc1000000, 0x00f82000, "[1+2],g", 0 },
+{ "ld",                0xc0000000, 0x01f8201f, "[1],d", 0 }, /* ld [rs1+%g0],d */
+{ "ld",                0xc0002000, 0x01f81fff, "[1],d", 0 }, /* ld [rs1+0],d */
+{ "ld",                0xc0002000, 0x01f80000, "[1+i],d", 0 },
+{ "ld",                0xc0002000, 0x01f80000, "[i+1],d", 0 },
+{ "ld",                0xc0000000, 0x01f82000, "[1+2],d", 0 },
+{ "ldstuba",    0xc0d80000, 0x0100201f, "[1]A,d", 0 }, /* ldstuba [rs1+%g0],d */
+{ "ldstuba",   0xc0d80000, 0x01002000, "[1+2]A,d", 0 },
+{ "ldsha",      0xc0d00000, 0x0128201f, "[1]A,d", 0 }, /* ldsha [rs1+%g0],d */
+{ "ldsha",     0xc0d00000, 0x01282000, "[1+2]A,d", 0 },
+{ "ldsba",      0xc0c80000, 0x0130201f, "[1]A,d", 0 }, /* ldsba [rs1+%g0],d */
+{ "ldsba",     0xc0c80000, 0x01302000, "[1+2]A,d", 0 },
+{ "ldda",       0xc0980000, 0x0160201f, "[1]A,d", 0 }, /* ldda [rs1+%g0],d */
+{ "ldda",      0xc0980000, 0x01602000, "[1+2]A,d", 0 },
+{ "lduha",      0xc0900000, 0x0168201f, "[1]A,d", 0 }, /* lduha [rs1+%g0],d */
+{ "lduha",     0xc0900000, 0x01682000, "[1+2]A,d", 0 },
+{ "ldstub",     0xc0680000, 0x0190201f, "[1],d", 0 }, /* ldstub [rs1+%g0],d */
+{ "ldstub",    0xc0682000, 0x01900000, "[1+i],d", 0 },
+{ "ldstub",    0xc0682000, 0x01900000, "[i+1],d", 0 },
+{ "ldstub",    0xc0680000, 0x01902000, "[1+2],d", 0 },
+{ "lda",        0xc0800000, 0x0178201f, "[1]A,d", 0 }, /* lda [rs1+%g0],d */
+{ "lda",       0xc0800000, 0x01782000, "[1+2]A,d", 0 },
+{ "ldsh",       0xc0500000, 0x0000000d, "[1],d", 0 }, /* ldsh [rs1+%g0],d */
+{ "ldsh",       0xc0502000, 0x01a81fff, "[1],d", 0 }, /* ldsh [rs1+0],d */
+{ "ldsh",      0xc0502000, 0x01a80000, "[1+i],d", 0 },
+{ "ldsh",      0xc0502000, 0x01a80000, "[i+1],d", 0 },
+{ "ldsh",      0xc0500000, 0x01a82000, "[1+2],d", 0 },
+{ "ldsb",       0xc0480000, 0x01b0201f, "[1],d", 0 }, /* ldsb [rs1+%g0],d */
+{ "ldsb",      0xc0482000, 0x01b01fff, "[1],d", 0 }, /* ldsb [rs1+0],d */
+{ "ldsb",      0xc0482000, 0x01b00000, "[1+i],d", 0 },
+{ "ldsb",      0xc0482000, 0x01b00000, "[i+1],d", 0 },
+{ "ldsb",      0xc0480000, 0x01b02000, "[1+2],d", 0 },
+{ "ldub",       0xc0080000, 0x01f0201f, "[1],d", 0 }, /* ldub [rs1+%g0],d */
+{ "ldub",       0xc0082000, 0x01f01fff, "[1],d", 0 }, /* ldub [rs1+0],d */
+{ "ldub",      0xc0082000, 0x01f00000, "[1+i],d", 0 },
+{ "ldub",      0xc0082000, 0x01f00000, "[i+1],d", 0 },
+{ "ldub",      0xc0080000, 0x01f02000, "[1+2],d", 0 },
+{ "lduba",      0xc0880000, 0x0170201f, "[1]A,d", 0 }, /* lduba [rs1+%g0],d */
+{ "lduba",     0xc0880000, 0x01702000, "[1+2]A,d", 0 },
+{ "lduh",      0xc0102000, 0x01e80000, "[1+i],d", 0 },
+{ "lduh",      0xc0102000, 0x01e80000, "[i+1],d", 0 },
+{ "lduh",      0xc0100000, 0x01e8201f, "[1],d", 0 }, /* lduh [rs1+%g0],d */
+{ "lduh",      0xc0102000, 0x01e81fff, "[1],d", 0 }, /* lduh [rs1+0],d */
+{ "lduh",      0xc0100000, 0x01e82000, "[1+2],d", 0 },
+
+{ "st",                0xc0200000, 0x01d8201f, "d,[1]", 0 }, /* st d,[rs1+%g0] */
+{ "st",                0xc0202000, 0x01d81fff, "d,[1]", 0 }, /* st d,[rs1+0] */
+{ "st",                0xc0202000, 0x01d80000, "d,[1+i]", 0 },
+{ "st",                0xc0202000, 0x01d80000, "d,[i+1]", 0 },
+{ "st",                0xc0200000, 0x01d82000, "d,[1+2]", 0 },
+{ "st",                0xc1200000, 0x00d8201f, "g,[1]", 0 }, /* st d[rs1+%g0] */
+{ "st",                0xc1202000, 0x00d81fff, "g,[1]", 0 }, /* st d,[rs1+0] */
+{ "st",                0xc1202000, 0x00d80000, "g,[1+i]", 0 },
+{ "st",                0xc1202000, 0x00d80000, "g,[i+1]", 0 },
+{ "st",                0xc1200000, 0x00d82000, "g,[1+2]", 0 },
+{ "st",                0xc1280000, 0x00d0201f, "F,[1]", 0 }, /* st %fsr,[rs1+%g0] */
+{ "st",                0xc1282000, 0x00d01fff, "F,[1]", 0 }, /* st %fsr,[rs1+0] */
+{ "st",                0xc1282000, 0x00d00000, "F,[1+i]", 0 },
+{ "st",                0xc1282000, 0x00d00000, "F,[i+1]", 0 },
+{ "st",                0xc1280000, 0x00d02000, "F,[1+2]", 0 },
+{ "st",                0xc1a00000, 0x0058201f, "D,[1]", 0 }, /* st d,[rs1+%g0] */
+{ "st",                0xc1a02000, 0x00581fff, "D,[1]", 0 }, /* st d,[rs1+0] */
+{ "st",                0xc1a02000, 0x00580000, "D,[1+i]", 0 },
+{ "st",                0xc1a02000, 0x00580000, "D,[i+1]", 0 },
+{ "st",                0xc1a00000, 0x00582000, "D,[1+2]", 0 },
+{ "st",                0xc1a80000, 0x0050201f, "C,[1]", 0 }, /* st d,[rs1+%g0] */
+{ "st",                0xc1a82000, 0x00501fff, "C,[1]", 0 }, /* st d,[rs1+0] */
+{ "st",                0xc1a82000, 0x00500000, "C,[1+i]", 0 },
+{ "st",                0xc1a82000, 0x00500000, "C,[i+1]", 0 },
+{ "st",                0xc1a80000, 0x00502000, "C,[1+2]", 0 },
+{ "sta",        0xc0a00000, 0x0108201f, "d,[1]A", 0 }, /* sta d,[rs1+%g0] */
+{ "sta",       0xc0a00000, 0x01082000, "d,[1+2]A", 0 },
+
+{ "stb",        0xc0280000, 0x01d0201f, "d,[1]", 0 }, /* stb d,[rs1+%g0] */
+{ "stb",       0xc0282000, 0x01d01fff, "d,[1]", 0 }, /* stb d,[rs1+0] */
+{ "stb",       0xc0282000, 0x01d00000, "d,[1+i]", 0 },
+{ "stb",       0xc0282000, 0x01d00000, "d,[i+1]", 0 },
+{ "stb",       0xc0280000, 0x01d02000, "d,[1+2]", 0 },
+{ "stba",       0xc0a80000, 0x01002000, "d,[1+2]A", 0 },
+{ "stba",      0xc0a80000, 0x0100201f, "d,[1]A", 0 }, /* stba d,[rs1+%g0] */
+
+{ "std",        0xc0380000, 0x01c0201f, "d,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std",       0xc0382000, 0x01c01fff, "d,[1]", 0 }, /* std d,[rs1+0] */
+{ "std",       0xc0382000, 0x01c00000, "d,[1+i]", 0 },
+{ "std",       0xc0382000, 0x01c00000, "d,[i+1]", 0 },
+{ "std",       0xc0380000, 0x01c02000, "d,[1+2]", 0 },
+{ "std",       0xc1380000, 0x00c0201f, "g,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std",        0xc1382000, 0x00c01fff, "g,[1]", 0 }, /* std d,[rs1+0] */
+{ "std",       0xc1382000, 0x00c00000, "g,[1+i]", 0 },
+{ "std",       0xc1382000, 0x00c00000, "g,[i+1]", 0 },
+{ "std",       0xc1380000, 0x00c02000, "g,[1+2]", 0 },
+{ "std",        0xc1300000, 0x00c8201f, "q,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std",       0xc1302000, 0x00c81fff, "q,[1]", 0 }, /* std d,[rs1+0] */
+{ "std",       0xc1302000, 0x00c80000, "q,[1+i]", 0 },
+{ "std",       0xc1302000, 0x00c80000, "q,[i+1]", 0 },
+{ "std",       0xc1300000, 0x00c82000, "q,[1+2]", 0 },
+{ "std",       0xc1b80000, 0x0040201f, "D,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std",       0xc1b82000, 0x00401fff, "D,[1]", 0 }, /* std d,[rs1+0] */
+{ "std",       0xc1b82000, 0x00400000, "D,[1+i]", 0 },
+{ "std",       0xc1b82000, 0x00400000, "D,[i+1]", 0 },
+{ "std",       0xc1b80000, 0x00402000, "D,[1+2]", 0 },
+{ "std",       0xc1b00000, 0x0048201f, "Q,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std",       0xc1b02000, 0x00481fff, "Q,[1]", 0 }, /* std d,[rs1+0] */
+{ "std",       0xc1b02000, 0x00480000, "Q,[1+i]", 0 },
+{ "std",       0xc1b02000, 0x00480000, "Q,[i+1]", 0 },
+{ "std",       0xc1b00000, 0x00482000, "Q,[1+2]", 0 },
+{ "stda",       0xc0b80000, 0x01402000, "d,[1+2]A", 0 },
+{ "stda",      0xc0b80000, 0x0140201f, "d,[1]A", 0 }, /* stda d,[rs1+%g0] */
+
+{ "sth",        0xc0300000, 0x01c8201f, "d,[1]", 0 }, /* sth d,[rs1+%g0] */
+{ "sth",       0xc0302000, 0x01c81fff, "d,[1]", 0 }, /* sth d,[rs1+0] */
+{ "sth",       0xc0300000, 0x01c82000, "d,[1+2]", 0 },
+{ "sth",       0xc0302000, 0x01c80000, "d,[1+i]", 0 },
+{ "sth",       0xc0302000, 0x01c80000, "d,[i+1]", 0 },
+{ "stha",       0xc0b00000, 0x0148201f, "d,[1]A", 0 }, /* stha d,[rs1+%g0] */
+{ "stha",      0xc0b00000, 0x01482000, "d,[1+2]A", 0 },
+
+{ "swap",       0xc0780000, 0x0180201f, "[1],d", 0 }, /* swap [rs1+%g0],d */
+{ "swap",       0xc0782000, 0x01801fff, "[1],d", 0 }, /* swap [rs1+0],d */
+{ "swap",       0xc0782000, 0x01800000, "[1+i],d", 0 },
+{ "swap",       0xc0782000, 0x01800000, "[i+1],d", 0 },
+{ "swap",       0xc0780000, 0x01802000, "[1+2],d", 0 },
+{ "swapa",      0xc0f80000, 0x01002000, "[1+2]A,d", 0 },
+{ "swapa",      0xc0f80000, 0x0100201f, "[1]A,d", 0 }, /* swapa [rs1+%g0],d */
+
+{ "restore",    0x81e80000, 0x7e17e01f, "", 0 }, /* restore %g0,%g0,%g0 */
+{ "restore",    0x81e82000, 0x7e14dfff, "", 0 }, /* restore %g0,0,%g0 */
+{ "restore",   0x81e82000, 0x00000000, "1,i,d", 0 },
+{ "restore",   0x81e80000, 0x00000000, "1,2,d", 0 },
+{ "rett",       0x81c82000, 0x40300000, "1+i", F_DELAYED },
+{ "rett",       0x81c82000, 0x40300000, "i+1", F_DELAYED },
+{ "rett",      0x81c80000, 0x40302000, "1+2", F_DELAYED },
+{ "rett",      0x81c82000, 0x40301fff, "1", F_DELAYED}, /* rett X,0 */
+{ "rett",      0x81c80000, 0x4030201f, "1", F_DELAYED}, /* rett X,%g0 */
+{ "save",       0x81e02000, 0x40180000, "1,i,d", 0 },
+{ "save",      0x81e00000, 0x40180000, "1,2,d", 0 },
+
+{ "ret",       0x81c7e008, 0x00001ff7, "", F_DELAYED }, /* jmpl %i7+8,%g0 */
+{ "retl",       0x81c3e008, 0x00001ff7, "", F_DELAYED }, /* jmpl %o7+8,%g0 */
+
+{ "jmpl",       0x81c00000, 0x4038201f, "1,d", F_DELAYED }, /* jmpl rs1+%g0,d */
+{ "jmpl",      0x81c02000, 0x4037c000, "i,d", F_DELAYED }, /* jmpl %g0+i,d */
+{ "jmpl",      0x81c02000, 0x40380000, "1+i,d", F_DELAYED },
+{ "jmpl",      0x81c02000, 0x40380000, "i+1,d", F_DELAYED },
+{ "jmpl",      0x81c00000, 0x40382000, "1+2,d", F_DELAYED },
+{ "wr",         0x81982000, 0x40600000, "1,i,t", 0 },
+{ "wr",         0x81980000, 0x40600000, "1,2,t", 0 },
+{ "wr",         0x81902000, 0x40680000, "1,i,w", 0 },
+{ "wr",         0x81900000, 0x40680000, "1,2,w", 0 },
+{ "wr",         0x81882000, 0x40700000, "1,i,p", 0 },
+{ "wr",         0x81880000, 0x40700000, "1,2,p", 0 },
+{ "wr",         0x81802000, 0x40780000, "1,i,y", 0 },
+{ "wr",         0x81800000, 0x40780000, "1,2,y", 0 },
+
+{ "rd",        0x81580000, 0x40a00000, "t,d", 0 },
+{ "rd",        0x81500000, 0x40a80000, "w,d", 0 },
+{ "rd",        0x81480000, 0x40b00000, "p,d", 0 },
+{ "rd",         0x81400000, 0x40b80000, "y,d", 0 },
+
+{ "sra",       0x81382000, 0x00000000, "1,i,d", 0 },
+{ "sra",       0x81380000, 0x00000000, "1,2,d", 0 },
+{ "srl",        0x81302000, 0x40c80000, "1,i,d", 0 },
+{ "srl",       0x81300000, 0x40c80000, "1,2,d", 0 },
+{ "sll",        0x81282000, 0x40d00000, "1,i,d", 0 },
+{ "sll",       0x81280000, 0x40d00000, "1,2,d", 0 },
+
+{ "mulscc",     0x81202000, 0x40d80000, "1,i,d", 0 },
+{ "mulscc",    0x81200000, 0x40d80000, "1,2,d", 0 },
+
+{ "clr",        0x80100000, 0x4e87e01f, "d", F_ALIAS }, /* or %g0,%g0,d */
+{ "clr",        0x80102000, 0x41efdfff, "d", F_ALIAS }, /* or %g0,0,d   */
+{ "clr",       0xc0200000, 0x3fd8001f, "[1]", F_ALIAS }, /* st %g0,[rs1+%g0] */
+{ "clr",       0xc0202000, 0x3fd81fff, "[1]", F_ALIAS }, /* st %g0,[rs1+0] */
+{ "clr",       0xc0202000, 0x3fd80000, "[1+i]", F_ALIAS },
+{ "clr",       0xc0202000, 0x3fd80000, "[i+1]", F_ALIAS },
+{ "clr",       0xc0200000, 0x3fd80000, "[1+2]", F_ALIAS },
+
+{ "clrb",       0xc0280000, 0x3fd0001f, "[1]", F_ALIAS },/* stb %g0,[rs1+%g0] */
+{ "clrb",      0xc0282000, 0x3fd00000, "[1+i]", F_ALIAS },
+{ "clrb",      0xc0282000, 0x3fd00000, "[i+1]", F_ALIAS },
+{ "clrb",      0xc0280000, 0x3fd00000, "[1+2]", F_ALIAS },
+
+{ "clrh",       0xc0300000, 0x3fc8001f, "[1]", F_ALIAS },/* sth %g0,[rs1+%g0] */
+{ "clrh",      0xc0300000, 0x3fc80000, "[1+2]", F_ALIAS },
+{ "clrh",      0xc0302000, 0x3fc80000, "[1+i]", F_ALIAS },
+{ "clrh",      0xc0302000, 0x3fc80000, "[i+1]", F_ALIAS },
+
+{ "orncc",      0x80b02000, 0x04048000, "1,i,d", 0 },
+{ "orncc",     0x80b00000, 0x04048000, "1,2,d", 0 },
+
+{ "tst",        0x80900000, 0x7f6fe000, "2", 0 }, /* orcc %g0, rs2, %g0 */
+{ "tst",        0x80900000, 0x7f68201f, "1", 0 }, /* orcc rs1, %g0, %g0 */
+{ "tst",        0x80902000, 0x7f681fff, "1", 0 }, /* orcc rs1, 0, %g0 */
+  
+{ "orcc",       0x80902000, 0x41680000, "1,i,d", 0 },
+{ "orcc",      0x80902000, 0x41680000, "i,1,d", 0 },
+{ "orcc",      0x80900000, 0x41680000, "1,2,d", 0 },
+{ "orn",        0x80302000, 0x41c80000, "1,i,d", 0 },
+{ "orn",       0x80300000, 0x41c80000, "1,2,d", 0 },
+
+{ "mov",        0x81800000, 0x4078201f, "1,y", F_ALIAS }, /* wr rs1,%g0,%y */
+{ "mov",        0x81802000, 0x40781fff, "1,y", F_ALIAS }, /* wr rs1,0,%y */
+{ "mov",        0x81802000, 0x40780000, "i,y", F_ALIAS },
+{ "mov",        0x81400000, 0x40b80000, "y,d", F_ALIAS }, /* rd %y,d */
+{ "mov",        0x81980000, 0x4060201f, "1,t", F_ALIAS }, /* wr rs1,%g0,%tbr */
+{ "mov",        0x81982000, 0x40601fff, "1,t", F_ALIAS }, /* wr rs1,0,%tbr */
+{ "mov",        0x81982000, 0x40600000, "i,t", F_ALIAS },
+{ "mov",        0x81580000, 0x40a00000, "t,d", F_ALIAS }, /* rd %tbr,d */
+{ "mov",        0x81900000, 0x4068201f, "1,w", F_ALIAS }, /* wr rs1,%g0,%wim */
+{ "mov",        0x81902000, 0x40681fff, "1,w", F_ALIAS }, /* wr rs1,0,%wim */
+{ "mov",        0x81902000, 0x40680000, "i,w", F_ALIAS },
+{ "mov",        0x81500000, 0x40a80000, "w,d", F_ALIAS }, /* rd %wim,d */
+{ "mov",        0x81880000, 0x4070201f, "1,p", F_ALIAS }, /* wr rs1,%g0,%psr */
+{ "mov",        0x81882000, 0x40701fff, "1,p", F_ALIAS }, /* wr rs1,0,%psr */
+{ "mov",        0x81882000, 0x40700000, "i,p", F_ALIAS },
+{ "mov",        0x81480000, 0x40b00000, "p,d", F_ALIAS }, /* rd %psr,d */
+
+{ "mov",        0x80102000, 0x41efc000, "i,d", 0 }, /* or %g0,i,d   */
+{ "mov",        0x80100000, 0x41efe000, "2,d", 0 }, /* or %g0,rs2,d */
+{ "mov",        0x80102000, 0x41e81fff, "1,d", 0 }, /* or rs1,0,d */
+{ "mov",        0x80100000, 0x41e8201f, "1,d", 0 }, /* or rs1,%g0,d   */
+
+{ "or",                0x80102000, 0x40800000, "1,i,d", 0 },
+{ "or",                0x80102000, 0x40800000, "i,1,d", 0 },
+{ "or",                0x80100000, 0x40800000, "1,2,d", 0 },
+
+{ "bset",      0x80102000, 0x40800000, "i,r", F_ALIAS },/* or rd,i,rd */
+{ "bset",      0x80100000, 0x40800000, "2,r", F_ALIAS },/* or rd,rs2,rd */
+
+{ "andncc",     0x80a82000, 0x41500000, "1,i,d", 0 },
+{ "andncc",    0x80a80000, 0x41500000, "1,2,d", 0 },
+{ "andn",       0x80282000, 0x41d00000, "1,i,d", 0 },
+{ "andn",      0x80280000, 0x41d00000, "1,2,d", 0 },
+
+{ "bclr",      0x80282000, 0x41d00000, "i,r", F_ALIAS },/* andn rd,i,rd */
+{ "bclr",      0x80280000, 0x41d00000, "2,r", F_ALIAS },/* andn rd,rs2,rd */
+
+{ "cmp",        0x80a02000, 0x7d580000, "1,i", 0 },     /* subcc rs1,i,%g0 */
+{ "cmp",       0x80a00000, 0x7d580000, "1,2", 0 },     /* subcc rs1,rs2,%g0 */
+
+{ "subcc",      0x80a02000, 0x41580000, "1,i,d", 0 },
+{ "subcc",     0x80a00000, 0x41580000, "1,2,d", 0 },
+{ "sub",       0x80202000, 0x41d80000, "1,i,d", 0 },
+{ "sub",       0x80200000, 0x41d80000, "1,2,d", 0 },
+{ "subx",      0x80602000, 0x41980000, "1,i,d", 0 },
+{ "subx",      0x80600000, 0x41980000, "1,2,d", 0 },
+{ "subxcc",     0x80e02000, 0x41180000, "1,i,d", 0 },
+{ "subxcc",    0x80e00000, 0x41180000, "1,2,d", 0 },
+
+{ "andcc",      0x80882000, 0x41700000, "1,i,d", 0 },
+{ "andcc",     0x80882000, 0x41700000, "i,1,d", 0 },
+{ "andcc",     0x80880000, 0x41700000, "1,2,d", 0 },
+{ "and",        0x80082000, 0x41f00000, "1,i,d", 0 },
+{ "and",       0x80082000, 0x41f00000, "i,1,d", 0 },
+{ "and",       0x80080000, 0x41f00000, "1,2,d", 0 },
+
+{ "inc",       0x80002001, 0x41f81ffe, "r", F_ALIAS }, /* add rs1,1,rsd */
+{ "inccc",     0x80802001, 0x41781ffe, "r", F_ALIAS }, /* addcc rd,1,rd */
+{ "dec",        0x80202001, 0x41d81ffe, "r", F_ALIAS },        /* sub rd,1,rd */
+{ "deccc",     0x80a02001, 0x41581ffe, "r", F_ALIAS }, /* subcc rd,1,rd */
+
+{ "btst",      0x80882000, 0x41700000, "i,1", F_ALIAS },/* andcc rs1,i,%g0 */
+{ "btst",      0x80880000, 0x41700000, "1,2", F_ALIAS },/* andcc rs1,rs2,%0 */
+
+{ "neg",       0x80200000, 0x41d80000, "r", F_ALIAS }, /* sub %0,rd,rd */
+{ "neg",       0x80200000, 0x41d80000, "2,d", F_ALIAS }, /* sub %0,rs2,rd */
+
+{ "addxcc",     0x80c02000, 0x41380000, "1,i,d", 0 },
+{ "addxcc",     0x80c02000, 0x41380000, "i,1,d", 0 },
+{ "addxcc",     0x80c00000, 0x41380000, "1,2,d", 0 },
+{ "addcc",      0x80802000, 0x41780000, "1,i,d", 0 },
+{ "addcc",      0x80802000, 0x41780000, "i,1,d", 0 },
+{ "addcc",      0x80800000, 0x41780000, "1,2,d", 0 },
+{ "addx",       0x80402000, 0x41b80000, "1,i,d", 0 },
+{ "addx",      0x80402000, 0x41b80000, "i,1,d", 0 },
+{ "addx",      0x80400000, 0x41b80000, "1,2,d", 0 },
+{ "add",        0x80002000, 0x41f80000, "1,i,d", 0 },
+{ "add",       0x80002000, 0x41f80000, "i,1,d", 0 },
+{ "add",       0x80000000, 0x41f80000, "1,2,d", 0 },
+
+{ "call",       0x9fc00000, 0x4038201f, "1", F_DELAYED }, /* jmpl rs1+%g0, %o7 */
+{ "call",      0x9fc00000, 0x4038201f, "1,#", F_DELAYED },
+{ "call",      0x40000000, 0x80000000, "L", F_DELAYED },
+{ "call",      0x40000000, 0x80000000, "L,#", F_DELAYED },
+
+{ "jmp",        0x81c00000, 0x7e38201f, "1", F_DELAYED }, /* jmpl rs1+%g0,%g0 */
+{ "jmp",        0x81c02000, 0x7e3fc000, "i", F_DELAYED }, /* jmpl %g0+i,%g0 */
+{ "jmp",        0x81c00000, 0x7e382000, "1+2", F_DELAYED }, /* jmpl rs1+rs2,%g0 */
+{ "jmp",        0x81c02000, 0x7e380000, "1+i", F_DELAYED }, /* jmpl rs1+i,%g0 */
+{ "jmp",        0x81c02000, 0x7e380000, "i+1", F_DELAYED }, /* jmpl i+rs1,%g0 */
+
+{ "nop",       0x01000000, 0xfeffffff, "", 0 }, /* sethi 0, %g0 */
+
+{ "set",        0x01000000, 0xc0c00000, "Sh,d", F_ALIAS },
+
+{ "sethi",      0x01000000, 0xc0c00000, "h,d", 0 },
+
+{ "taddcctv",   0x81102000, 0x40e00000, "1,i,d", 0 },
+{ "taddcctv",   0x81100000, 0x40e00000, "1,2,d", 0 },
+{ "taddcc",     0x81002000, 0x40f80000, "1,i,d", 0 },
+{ "taddcc",     0x81000000, 0x40f80000, "1,2,d", 0 },
+
+/* Conditional instructions.
+
+   Because this part of the table was such a mess earlier, I have
+   macrofied it so that all the branches and traps are generated from
+   a single-line description of each condition value.  */
+
+#define ANNUL  0x20000000
+#define        IMMED  0x00002000
+#define        RS1_G0 0x0007C000
+#define        RS2_G0 0x0000001F
+
+/* Define two branches -- one annulled, one without */
+#define br(opcode, mask, lose, flags)  \
+ { opcode, mask+ANNUL, lose, ",al", flags },   \
+ { opcode, mask      , lose, "l",   flags }
+
+/* Define four traps: reg+reg, reg + immediate, immediate alone, reg alone. */
+#define tr(opcode, mask, lose, flags) \
+ {opcode, mask+IMMED, lose+RS1_G0      , "i", flags },  /* %g0 + imm */ \
+ {opcode, mask+IMMED, lose             , "1+i", flags }, /* rs1 + imm */ \
+ {opcode, mask      , lose+IMMED       , "1+2", flags }, /* rs1 + rs2 */ \
+ {opcode, mask      , lose+IMMED+RS2_G0, "1", flags }    /* rs1 + %g0 */
+
+/* Define both branches and traps based on condition mask */
+#ifdef __STDC__
+#define cond(bop, top, mask, flags)    \
+  br(#bop,  0x00800000+(mask << 25), 0xC1400000, F_DELAYED|flags), \
+  tr(#top,  0x81d00000+(mask << 25), 0x40280000, flags)
+#else
+#define cond(bop, top, mask, flags)    \
+  br("bop", 0x00800000+(mask << 25), 0xC1400000, F_DELAYED|flags), \
+  tr("top", 0x81d00000+(mask << 25), 0x40280000, flags)
+#endif
+
+/* Define all the conditions, all the branches, all the traps.  */
+cond (bvc,     tvc,  0xF, 0),
+cond (bvs,     tvs,  0x7, 0),
+cond (bpos,    tpos, 0xE, 0),
+cond (bneg,    tneg, 0x6, 0),
+cond (bcc,     tcc,  0xD, 0),
+cond (bcs,     tcs,  0x5, 0),
+cond (blu,     tlu,  0x5, F_ALIAS),    /* for cs */
+cond (bgeu,    tgeu, 0xD, F_ALIAS),    /* for cc */
+cond (bgu,     tgu,  0xC, 0),
+cond (bleu,    tleu, 0x4, 0),
+cond (bge,     tge,  0xB, 0),
+cond (bl,      tl,   0x3, 0),
+cond (bg,      tg,   0xA, 0),
+cond (ble,     tle,  0x2, 0),
+cond (be,      te,   0x1, 0),
+cond (bz,      tz,   0x1, F_ALIAS),    /* for e */
+cond (bne,     tne,  0x9, 0),
+cond (bnz,     tnz,  0x9, F_ALIAS),    /* for ne */
+cond (b,       t,    0x8, 0),
+cond (ba,      ta,   0x8, F_ALIAS),    /* for nothing */
+cond (bn,      tn,   0x0, 0),
+
+#undef cond
+#undef br
+#undef tr
+
+{ "tsubcc",     0x81080000, 0x40f00000, "1,2,d", 0 },
+{ "tsubcc",     0x81082000, 0x40f00000, "1,i,d", 0 },
+{ "tsubcctv",   0x80580000, 0x40a00000, "1,2,d", 0 },
+{ "tsubcctv",   0x80582000, 0x40a00000, "1,i,d", 0 },
+
+{ "unimp",      0x00000000, 0xFFFFFFFF, "l", 0 },
+
+{ "iflush",     0x81d80000, 0x40202000, "1+2", 0 },
+{ "iflush",     0x81d82000, 0x40200000, "1+i", 0 },
+
+{ "xnorcc",     0x80b80000, 0x41400000, "1,2,d", 0 },
+{ "xnorcc",    0x80b82000, 0x41400000, "1,i,d", 0 },
+{ "xnorcc",    0x80b82000, 0x41400000, "i,1,d", 0 },
+{ "xorcc",      0x80980000, 0x41600000, "1,2,d", 0 },
+{ "xorcc",     0x80982000, 0x41600000, "1,i,d", 0 },
+{ "xorcc",     0x80982000, 0x41600000, "i,1,d", 0 },
+{ "xnor",       0x80380000, 0x41c00000, "1,2,d", 0 },
+{ "xnor",      0x80382000, 0x41c00000, "1,i,d", 0 },
+{ "xnor",      0x80382000, 0x41c00000, "i,1,d", 0 },
+{ "xor",        0x80180000, 0x41e00000, "1,2,d", 0 },
+{ "xor",       0x80182000, 0x41e00000, "1,i,d", 0 },
+{ "xor",       0x80182000, 0x41e00000, "i,1,d", 0 },
+
+{ "not",        0x80380000, 0x41c00000, "r", F_ALIAS }, /* xnor rd,%0,rd */
+{ "not",        0x80380000, 0x41c00000, "1,d", F_ALIAS }, /* xnor rs1,%0,rd */
+
+{ "btog",      0x80180000, 0x41e02000, "2,r", F_ALIAS }, /* xor rd,rs2,rd */
+{ "btog",      0x80182000, 0x41e00000, "i,r", F_ALIAS }, /* xor rd,i,rd */
+
+{ "fpop1",      0x81a00000, 0x40580000, "[1+2],d", 0 },
+{ "fpop2",      0x81a80000, 0x40500000, "[1+2],d", 0 },
+
+/* Someday somebody should give these the same treatment as the branches
+   above.  FIXME someday.  */
+
+{ "fb",         0x31800000, 0xc0400000, ",al", F_DELAYED },
+{ "fb",         0x11800000, 0xc0400000, "l", F_DELAYED },
+{ "fba",        0x31800000, 0xc0400000, ",al", F_DELAYED|F_ALIAS },
+{ "fba",        0x11800000, 0xc0400000, "l", F_DELAYED|F_ALIAS },
+{ "fbn",        0x21800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbn",        0x01800000, 0xc0400000, "l", F_DELAYED },
+{ "fbu",        0x2f800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbu",        0x0f800000, 0xc0400000, "l", F_DELAYED },
+{ "fbg",        0x2d800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbg",        0x0d800000, 0xc0400000, "l", F_DELAYED },
+{ "fbug",       0x2b800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbug",       0x0b800000, 0xc0400000, "l", F_DELAYED },
+{ "fbl",        0x29800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbl",        0x09800000, 0xc0400000, "l", F_DELAYED },
+{ "fbul",       0x27800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbul",       0x07800000, 0xc0400000, "l", F_DELAYED },
+{ "fblg",       0x25800000, 0xc0400000, ",al", F_DELAYED },
+{ "fblg",       0x05800000, 0xc0400000, "l", F_DELAYED },
+{ "fbne",       0x23800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbne",       0x03800000, 0xc0400000, "l", F_DELAYED },
+{ "fbe",        0x33800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbe",        0x13800000, 0xc0400000, "l", F_DELAYED },
+{ "fbue",       0x35800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbue",       0x15800000, 0xc0400000, "l", F_DELAYED },
+{ "fbge",       0x37800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbge",       0x17800000, 0xc0400000, "l", F_DELAYED },
+{ "fbuge",      0x39800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbuge",      0x19800000, 0xc0400000, "l", F_DELAYED },
+{ "fble",       0x3b800000, 0xc0400000, ",al", F_DELAYED },
+{ "fble",       0x1b800000, 0xc0400000, "l", F_DELAYED },
+{ "fbule",      0x3d800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbule",      0x1d800000, 0xc0400000, "l", F_DELAYED },
+{ "fbo",        0x3f800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbo",        0x1f800000, 0xc0400000, "l", F_DELAYED },
+
+{ "cba",        0x31c00000, 0xce000000, ",al", F_DELAYED },
+{ "cba",        0x11c00000, 0xce000000, "l", F_DELAYED },
+{ "cbn",        0x21c00000, 0xde000000, ",al", F_DELAYED },
+{ "cbn",        0x01c00000, 0xde000000, "l", F_DELAYED },
+{ "cb3",        0x2fc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb3",        0x0fc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb2",        0x2dc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb2",        0x0dc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb23",       0x2bc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb23",       0x0bc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb1",        0x29c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb1",        0x09c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb13",       0x27c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb13",       0x07c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb12",       0x25c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb12",       0x05c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb123",      0x23c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb123",      0x03c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb0",        0x33c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb0",        0x13c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb03",       0x35c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb03",       0x15c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb02",       0x37c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb02",       0x17c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb023",      0x39c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb023",      0x19c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb01",       0x3bc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb01",       0x1bc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb013",      0x3dc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb013",      0x1dc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb012",      0x3fc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb012",      0x1fc00000, 0xc0000000, "l", F_DELAYED },
+
+{ "fstoi",      0x81a01a20, 0x400025c0, "f,g", 0 },
+{ "fdtoi",      0x81a01a40, 0x400025a0, "f,g", 0 },
+{ "fxtoi",      0x81a01a60, 0x40002580, "f,g", 0 },
+
+{ "fitox",      0x81a01980, 0x40002660, "f,g", 0 },
+{ "fitod",      0x81a01900, 0x400026e0, "f,g", 0 },
+{ "fitos",      0x81a01880, 0x40002660, "f,g", 0 },
+
+{ "fstod",      0x81a01920, 0x400026c0, "f,g", 0 },
+{ "fstox",      0x81a019a0, 0x40002640, "f,g", 0 },
+{ "fdtos",      0x81a018c0, 0x40002720, "f,g", 0 },
+{ "fdtox",      0x81a019c0, 0x40002620, "f,g", 0 },
+{ "fxtos",      0x81a018e0, 0x40002700, "f,g", 0 },
+{ "fxtod",      0x81a01960, 0x40002680, "f,g", 0 },
+
+{ "fdivx",      0x81a009e0, 0x40083600, "e,f,g", 0 },
+{ "fdivd",      0x81a009c0, 0x40003620, "e,f,g", 0 },
+{ "fdivs",      0x81a009a0, 0x40003640, "e,f,g", 0 },
+
+{ "fmuls",      0x81a00920, 0x400036c0, "e,f,g", 0 },
+{ "fmuld",      0x81a00940, 0x400036a0, "e,f,g", 0 },
+{ "fmulx",      0x81a00960, 0x40003680, "e,f,g", 0 },
+
+{ "fsqrts",     0x81a00520, 0x40003ac0, "f,g", 0 },
+{ "fsqrtd",     0x81a00540, 0x40003aa8, "f,g", 0 },
+{ "fsqrtx",     0x81a00560, 0x40003a80, "f,g", 0 },
+
+{ "fabss",      0x81a00120, 0x40003ec0, "f,g", 0 },
+{ "fnegs",      0x81a000a0, 0x40003f40, "f,g", 0 },
+{ "fmovs",      0x81a00020, 0x40003fc0, "f,g", 0 },
+
+{ "fsubx",      0x81a008e0, 0x40003700, "e,f,g", 0 },
+{ "fsubd",      0x81a008c0, 0x40003720, "e,f,g", 0 },
+{ "fsubs",      0x81a008a0, 0x40003740, "e,f,g", 0 },
+
+{ "faddx",      0x81a00860, 0x40003780, "e,f,g", 0 },
+{ "faddd",      0x81a00840, 0x400037a0, "e,f,g", 0 },
+{ "fadds",      0x81a00820, 0x400037c0, "e,f,g", 0 },
+
+{ "fcmpex",     0x81a80ae0, 0x40003500, "e,f", 0 },
+{ "fcmped",     0x81a80ac0, 0x40003520, "e,f", 0 },
+{ "fcmpes",     0x81a80aa0, 0x40003540, "e,f", 0 },
+{ "fcmpx",      0x81a80a60, 0x40003580, "e,f", 0 },
+{ "fcmpd",      0x81a80a40, 0x400035a0, "e,f", 0 },
+{ "fcmps",      0x81a80a20, 0x400035c0, "e,f", 0 },
+
+{ "cpop1",      0x81b00000, 0x40480000, "[1+2],d", 0 },
+{ "cpop2",      0x81b80000, 0x40400000, "[1+2],d", 0 },
+};
+
+#define NUMOPCODES ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]))
+
diff --git a/gdb/sparc-pinsn.c b/gdb/sparc-pinsn.c
new file mode 100644 (file)
index 0000000..39d62af
--- /dev/null
@@ -0,0 +1,465 @@
+/* Disassembler for the sparc.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB, the GNU disassembler.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "sparc-opcode.h"
+#include "gdbcore.h"
+#include "string.h"
+#include "target.h"
+
+extern void qsort ();
+
+
+extern char *reg_names[];
+#define        freg_names      (&reg_names[4 * 8])
+
+union sparc_insn
+  {
+    unsigned long int code;
+    struct
+      {
+       unsigned int OP:2;
+#define        op      ldst.OP
+       unsigned int RD:5;
+#define        rd      ldst.RD
+       unsigned int op3:6;
+       unsigned int RS1:5;
+#define        rs1     ldst.RS1
+       unsigned int i:1;
+       unsigned int ASI:8;
+#define        asi     ldst.ASI
+       unsigned int RS2:5;
+#define        rs2     ldst.RS2
+#define        shcnt   rs2
+      } ldst;
+    struct
+      {
+       unsigned int OP:2, RD:5, op3:6, RS1:5, i:1;
+       unsigned int IMM13:13;
+#define        imm13   IMM13.IMM13
+      } IMM13;
+    struct
+      {
+       unsigned int OP:2;
+       unsigned int a:1;
+       unsigned int cond:4;
+       unsigned int op2:3;
+       unsigned int DISP22:22;
+#define        disp22  branch.DISP22
+      } branch;
+#define        imm22   disp22
+    struct
+      {
+       unsigned int OP:2;
+       unsigned int DISP30:30;
+#define        disp30  call.DISP30
+      } call;
+  };
+
+/* Nonzero if INSN is the opcode for a delayed branch.  */
+static int
+is_delayed_branch (insn)
+     union sparc_insn insn;
+{
+  unsigned int i;
+
+  for (i = 0; i < NUMOPCODES; ++i)
+    {
+      const struct sparc_opcode *opcode = &sparc_opcodes[i];
+      if ((opcode->match & insn.code) == opcode->match
+         && (opcode->lose & insn.code) == 0)
+       return (opcode->flags & F_DELAYED);
+    }
+  return 0;
+}
+
+static int opcodes_sorted = 0;
+
+/* Print one instruction from MEMADDR on STREAM.  */
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  union sparc_insn insn;
+
+  register unsigned int i;
+
+  if (!opcodes_sorted)
+    {
+      static int compare_opcodes ();
+      qsort ((char *) sparc_opcodes, NUMOPCODES,
+            sizeof (sparc_opcodes[0]), compare_opcodes);
+      opcodes_sorted = 1;
+    }
+
+  read_memory (memaddr, &insn, sizeof (insn));
+
+  for (i = 0; i < NUMOPCODES; ++i)
+    {
+      const struct sparc_opcode *opcode = &sparc_opcodes[i];
+      if ((opcode->match & insn.code) == opcode->match
+         && (opcode->lose & insn.code) == 0)
+       {
+         /* Nonzero means that we have found an instruction which has
+            the effect of adding or or'ing the imm13 field to rs1.  */
+         int imm_added_to_rs1 = 0;
+
+         /* Nonzero means that we have found a plus sign in the args
+            field of the opcode table.  */
+         int found_plus = 0;
+         
+         /* Do we have an 'or' instruction where rs1 is the same
+            as rsd, and which has the i bit set?  */
+         if (opcode->match == 0x80102000
+             && insn.rs1 == insn.rd)
+           imm_added_to_rs1 = 1;
+
+         if (insn.rs1 != insn.rd
+             && strchr (opcode->args, 'r') != 0)
+             /* Can't do simple format if source and dest are different.  */
+             continue;
+
+         fputs_filtered (opcode->name, stream);
+
+         {
+           register const char *s;
+
+           if (opcode->args[0] != ',')
+             fputs_filtered (" ", stream);
+           for (s = opcode->args; *s != '\0'; ++s)
+             {
+               if (*s == ',')
+                 {
+                   fputs_filtered (",", stream);
+                   ++s;
+                   if (*s == 'a')
+                     {
+                       fputs_filtered ("a", stream);
+                       ++s;
+                     }
+                   fputs_filtered (" ", stream);
+                 }
+
+               switch (*s)
+                 {
+                 case '+':
+                   found_plus = 1;
+
+                   /* note fall-through */
+                 default:
+                   fprintf_filtered (stream, "%c", *s);
+                   break;
+
+                 case '#':
+                   fputs_filtered ("0", stream);
+                   break;
+
+#define        reg(n)  fprintf_filtered (stream, "%%%s", reg_names[n])
+                 case '1':
+                 case 'r':
+                   reg (insn.rs1);
+                   break;
+
+                 case '2':
+                   reg (insn.rs2);
+                   break;
+
+                 case 'd':
+                   reg (insn.rd);
+                   break;
+#undef reg
+
+#define        freg(n) fprintf_filtered (stream, "%%%s", freg_names[n])
+                 case 'e':
+                   freg (insn.rs1);
+                   break;
+
+                 case 'f':
+                   freg (insn.rs2);
+                   break;
+
+                 case 'g':
+                   freg (insn.rd);
+                   break;
+#undef freg
+
+#define        creg(n) fprintf_filtered (stream, "%%c%u", (unsigned int) (n))
+                 case 'b':
+                   creg (insn.rs1);
+                   break;
+
+                 case 'c':
+                   creg (insn.rs2);
+                   break;
+
+                 case 'D':
+                   creg (insn.rd);
+                   break;
+#undef creg
+
+                 case 'h':
+                   fprintf_filtered (stream, "%%hi(%#x)",
+                                     (int) insn.imm22 << 10);
+                   break;
+
+                 case 'i':
+                   {
+                     /* We cannot trust the compiler to sign-extend
+                        when extracting the bitfield, hence the shifts.  */
+                     int imm = ((int) insn.imm13 << 19) >> 19;
+
+                     /* Check to see whether we have a 1+i, and take
+                        note of that fact.
+
+                        Note: because of the way we sort the table,
+                        we will be matching 1+i rather than i+1,
+                        so it is OK to assume that i is after +,
+                        not before it.  */
+                     if (found_plus)
+                       imm_added_to_rs1 = 1;
+                     
+                     if (imm <= 9)
+                       fprintf_filtered (stream, "%d", imm);
+                     else
+                       fprintf_filtered (stream, "%#x", imm);
+                   }
+                   break;
+
+                 case 'L':
+                   print_address ((CORE_ADDR) memaddr + insn.disp30 * 4,
+                                  stream);
+                   break;
+
+                 case 'l':
+                   if ((insn.code >> 22) == 0)
+                     /* Special case for `unimp'.  Don't try to turn
+                        it's operand into a function offset.  */
+                     fprintf_filtered (stream, "%#x",
+                                       (int) (((int) insn.disp22 << 10) >> 10));
+                   else
+                     /* We cannot trust the compiler to sign-extend
+                        when extracting the bitfield, hence the shifts.  */
+                     print_address ((CORE_ADDR)
+                                    (memaddr
+                                     + (((int) insn.disp22 << 10) >> 10) * 4),
+                                    stream);
+                   break;
+
+                 case 'A':
+                   fprintf_filtered (stream, "(%d)", (int) insn.asi);
+                   break;
+
+                 case 'C':
+                   fputs_filtered ("%csr", stream);
+                   break;
+
+                 case 'F':
+                   fputs_filtered ("%fsr", stream);
+                   break;
+
+                 case 'p':
+                   fputs_filtered ("%psr", stream);
+                   break;
+
+                 case 'q':
+                   fputs_filtered ("%fq", stream);
+                   break;
+
+                 case 'Q':
+                   fputs_filtered ("%cq", stream);
+                   break;
+
+                 case 't':
+                   fputs_filtered ("%tbr", stream);
+                   break;
+
+                 case 'w':
+                   fputs_filtered ("%wim", stream);
+                   break;
+
+                 case 'y':
+                   fputs_filtered ("%y", stream);
+                   break;
+                 }
+             }
+         }
+
+         /* If we are adding or or'ing something to rs1, then
+            check to see whether the previous instruction was
+            a sethi to the same register as in the sethi.
+            If so, attempt to print the result of the add or
+            or (in this context add and or do the same thing)
+            and its symbolic value.  */
+         if (imm_added_to_rs1)
+           {
+             union sparc_insn prev_insn;
+             int errcode;
+
+             errcode = target_read_memory (memaddr - 4,
+                                    (char *)&prev_insn, sizeof (prev_insn));
+
+             if (errcode == 0)
+               {
+                 /* If it is a delayed branch, we need to look at the
+                    instruction before the delayed branch.  This handles
+                    sequences such as
+
+                    sethi %o1, %hi(_foo), %o1
+                    call _printf
+                    or %o1, %lo(_foo), %o1
+                    */
+
+                 if (is_delayed_branch (prev_insn))
+                   errcode = target_read_memory
+                     (memaddr - 8, (char *)&prev_insn, sizeof (prev_insn));
+               }
+
+             /* If there was a problem reading memory, then assume
+                the previous instruction was not sethi.  */
+             if (errcode == 0)
+               {
+                 /* Is it sethi to the same register?  */
+                 if ((prev_insn.code & 0xc1c00000) == 0x01000000
+                     && prev_insn.rd == insn.rs1)
+                   {
+                     fprintf_filtered (stream, "\t! ");
+                     /* We cannot trust the compiler to sign-extend
+                        when extracting the bitfield, hence the shifts.  */
+                     print_address (((int) prev_insn.imm22 << 10)
+                                    | (insn.imm13 << 19) >> 19, stream);
+                   }
+               }
+           }
+
+         return sizeof (insn);
+       }
+    }
+
+  printf_filtered ("%#8x", insn.code);
+  return sizeof (insn);
+}
+
+
+/* Compare opcodes A and B.  */
+
+static int
+compare_opcodes (a, b)
+     char *a, *b;
+{
+  struct sparc_opcode *op0 = (struct sparc_opcode *) a;
+  struct sparc_opcode *op1 = (struct sparc_opcode *) b;
+  unsigned long int match0 = op0->match, match1 = op1->match;
+  unsigned long int lose0 = op0->lose, lose1 = op1->lose;
+  register unsigned int i;
+
+  /* If a bit is set in both match and lose, there is something
+     wrong with the opcode table.  */
+  if (match0 & lose0)
+    {
+      fprintf (stderr, "Internal error:  bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+              op0->name, match0, lose0);
+      op0->lose &= ~op0->match;
+      lose0 = op0->lose;
+    }
+
+  if (match1 & lose1)
+    {
+      fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+              op1->name, match1, lose1);
+      op1->lose &= ~op1->match;
+      lose1 = op1->lose;
+    }
+
+  /* Because the bits that are variable in one opcode are constant in
+     another, it is important to order the opcodes in the right order.  */
+  for (i = 0; i < 32; ++i)
+    {
+      unsigned long int x = 1 << i;
+      int x0 = (match0 & x) != 0;
+      int x1 = (match1 & x) != 0;
+
+      if (x0 != x1)
+       return x1 - x0;
+    }
+
+  for (i = 0; i < 32; ++i)
+    {
+      unsigned long int x = 1 << i;
+      int x0 = (lose0 & x) != 0;
+      int x1 = (lose1 & x) != 0;
+
+      if (x0 != x1)
+       return x1 - x0;
+    }
+
+  /* They are functionally equal.  So as long as the opcode table is
+     valid, we can put whichever one first we want, on aesthetic grounds.  */
+
+  /* Our first aesthetic ground is that aliases defer to real insns.  */
+  {
+    int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
+    if (alias_diff != 0)
+      /* Put the one that isn't an alias first.  */
+      return alias_diff;
+  }
+
+  /* Except for the above aliases, two "identical" instructions had
+     better have the same opcode.  This is a sanity check on the table.  */
+  if (0 != strcmp (op0->name, op1->name))
+      fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
+       op0->name, op1->name);
+
+  /* Fewer arguments are preferred.  */
+  {
+    int length_diff = strlen (op0->args) - strlen (op1->args);
+    if (length_diff != 0)
+      /* Put the one with fewer arguments first.  */
+      return length_diff;
+  }
+
+  /* Put 1+i before i+1.  */
+  {
+    char *p0 = (char *) strchr(op0->args, '+');
+    char *p1 = (char *) strchr(op1->args, '+');
+
+    if (p0 && p1)
+      {
+       /* There is a plus in both operands.  Note that a plus
+          sign cannot be the first character in args,
+          so the following [-1]'s are valid.  */
+       if (p0[-1] == 'i' && p1[1] == 'i')
+         /* op0 is i+1 and op1 is 1+i, so op1 goes first.  */
+         return 1;
+       if (p0[1] == 'i' && p1[-1] == 'i')
+         /* op0 is 1+i and op1 is i+1, so op0 goes first.  */
+         return -1;
+      }
+  }
+
+  /* They are, as far as we can tell, identical.
+     Since qsort may have rearranged the table partially, there is
+     no way to tell which one was first in the opcode table as
+     written, so just say there are equal.  */
+  return 0;
+}
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
new file mode 100644 (file)
index 0000000..e0fb8ba
--- /dev/null
@@ -0,0 +1,586 @@
+/* Machine-dependent code which would otherwise be in inflow.c and core.c,
+   for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+   This code is for the sparc cpu.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "signame.h"
+#include "target.h"
+#include "ieee-float.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/core.h>
+
+#include "gdbcore.h"
+
+/* From infrun.c */
+extern int stop_after_trap;
+
+typedef enum
+{
+  Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
+} branch_type;
+
+/* Simulate single-step ptrace call for sun4.  Code written by Gary
+   Beihl (beihl@mcc.com).  */
+
+/* npc4 and next_pc describe the situation at the time that the
+   step-breakpoint was set, not necessary the current value of NPC_REGNUM.  */
+static CORE_ADDR next_pc, npc4, target;
+static int brknpc4, brktrg;
+typedef char binsn_quantum[BREAKPOINT_MAX];
+static binsn_quantum break_mem[3];
+
+/* Non-zero if we just simulated a single-step ptrace call.  This is
+   needed because we cannot remove the breakpoints in the inferior
+   process until after the `wait' in `wait_for_inferior'.  Used for
+   sun4. */
+
+int one_stepped;
+
+void
+single_step (signal)
+     int signal;
+{
+  branch_type br, isannulled();
+  CORE_ADDR pc;
+  long pc_instruction;
+
+  if (!one_stepped)
+    {
+      /* Always set breakpoint for NPC.  */
+      next_pc = read_register (NPC_REGNUM);
+      npc4 = next_pc + 4; /* branch not taken */
+
+      target_insert_breakpoint (next_pc, break_mem[0]);
+      /* printf ("set break at %x\n",next_pc); */
+
+      pc = read_register (PC_REGNUM);
+      pc_instruction = read_memory_integer (pc, sizeof(pc_instruction));
+      br = isannulled (pc_instruction, pc, &target);
+      brknpc4 = brktrg = 0;
+
+      if (br == bicca)
+       {
+         /* Conditional annulled branch will either end up at
+            npc (if taken) or at npc+4 (if not taken).
+            Trap npc+4.  */
+         brknpc4 = 1;
+         target_insert_breakpoint (npc4, break_mem[1]);
+       }
+      else if (br == baa && target != next_pc)
+       {
+         /* Unconditional annulled branch will always end up at
+            the target.  */
+         brktrg = 1;
+         target_insert_breakpoint (target, break_mem[2]);
+       }
+
+      /* Let it go */
+      ptrace (7, inferior_pid, 1, signal);
+      one_stepped = 1;
+      return;
+    }
+  else
+    {
+      /* Remove breakpoints */
+      target_remove_breakpoint (next_pc, break_mem[0]);
+
+      if (brknpc4)
+       target_remove_breakpoint (npc4, break_mem[1]);
+
+      if (brktrg)
+       target_remove_breakpoint (target, break_mem[2]);
+
+      one_stepped = 0;
+    }
+}
+\f
+/*
+ * Find the pc saved in frame FRAME.  
+ */
+CORE_ADDR
+frame_saved_pc (frame)
+     FRAME frame;
+{
+  CORE_ADDR prev_pc;
+
+  /* If it's at the bottom, the return value's stored in i7/rp */
+  if (get_current_frame () == frame)
+    prev_pc = GET_RWINDOW_REG (read_register (SP_REGNUM), rw_in[7]);
+  else
+    /* Wouldn't this always work?  This would allow this routine to
+       be completely a macro.  */
+    prev_pc = GET_RWINDOW_REG (frame->bottom, rw_in[7]);
+  
+  return PC_ADJUST (prev_pc);
+}
+
+/*
+ * Since an individual frame in the frame cache is defined by two
+ * arguments (a frame pointer and a stack pointer), we need two
+ * arguments to get info for an arbitrary stack frame.  This routine
+ * takes two arguments and makes the cached frames look as if these
+ * two arguments defined a frame on the cache.  This allows the rest
+ * of info frame to extract the important arguments without
+ * difficulty. 
+ */
+FRAME
+setup_arbitrary_frame (frame, stack)
+     FRAME_ADDR frame, stack;
+{
+  FRAME fid = create_new_frame (frame, 0);
+
+  if (!fid)
+    fatal ("internal: create_new_frame returned invalid frame id");
+  
+  fid->bottom = stack;
+
+  return fid;
+}
+
+/* This code was written by Gary Beihl (beihl@mcc.com).
+   It was modified by Michael Tiemann (tiemann@corto.inria.fr).  */
+
+/*
+ * This routine appears to be passed a size by which to increase the
+ * stack.  It then executes a save instruction in the inferior to
+ * increase the stack by this amount.  Only the register window system
+ * should be affected by this; the program counter & etc. will not be.
+ *
+ * This instructions used for this purpose are:
+ *
+ *     sethi %hi(0x0),g1                    *
+ *     add g1,0x1ee0,g1                     *
+ *     save sp,g1,sp                        
+ *     sethi %hi(0x0),g1                    *
+ *     add g1,0x1ee0,g1                     *
+ *     t g0,0x1,o0
+ *     sethi %hi(0x0),g0                    (nop)
+ *
+ *  I presume that these set g1 to be the negative of the size, do a
+ * save (putting the stack pointer at sp - size) and restore the
+ * original contents of g1.  A * indicates that the actual value of
+ * the instruction is modified below.
+ */
+static int save_insn_opcodes[] = {
+  0x03000000, 0x82007ee0, 0x9de38001, 0x03000000,
+  0x82007ee0, 0x91d02001, 0x01000000 };
+
+/* Neither do_save_insn or do_restore_insn save stack configuration
+   (current_frame, etc),
+   since the stack is in an indeterminate state through the call to
+   each of them.  That responsibility of the routine which calls them.  */
+
+static void
+do_save_insn (size)
+     int size;
+{
+  int g1 = read_register (G1_REGNUM);
+  CORE_ADDR sp = read_register (SP_REGNUM);
+  CORE_ADDR pc = read_register (PC_REGNUM);
+  CORE_ADDR npc = read_register (NPC_REGNUM);
+  CORE_ADDR fake_pc = sp - sizeof (save_insn_opcodes);
+  struct inferior_status inf_status;
+
+  save_inferior_status (&inf_status, 0); /* Don't restore stack info */
+  /*
+   * See above.
+   */
+  save_insn_opcodes[0] = 0x03000000 | ((-size >> 10) & 0x3fffff);
+  save_insn_opcodes[1] = 0x82006000 | (-size & 0x3ff);
+  save_insn_opcodes[3] = 0x03000000 | ((g1 >> 10) & 0x3fffff);
+  save_insn_opcodes[4] = 0x82006000 | (g1 & 0x3ff);
+  write_memory (fake_pc, (char *)save_insn_opcodes, sizeof (save_insn_opcodes));
+
+  clear_proceed_status ();
+  stop_after_trap = 1;
+  proceed (fake_pc, 0, 0);
+
+  write_register (PC_REGNUM, pc);
+  write_register (NPC_REGNUM, npc);
+  restore_inferior_status (&inf_status);
+}
+
+/*
+ * This routine takes a program counter value.  It restores the
+ * register window system to the frame above the current one.
+ * THIS ROUTINE CLOBBERS PC AND NPC IN THE TARGET!
+ */
+
+/*    The following insns translate to:
+       restore %g0,%g0,%g0
+       t %g0,1
+       sethi %hi(0),%g0        */
+
+static int restore_insn_opcodes[] = { 0x81e80000, 0x91d02001, 0x01000000 };
+
+static void
+do_restore_insn ()
+{
+  CORE_ADDR sp = read_register (SP_REGNUM);
+  CORE_ADDR fake_pc = sp - sizeof (restore_insn_opcodes);
+  struct inferior_status inf_status;
+
+  save_inferior_status (&inf_status, 0); /* Don't restore stack info */
+
+  write_memory (fake_pc, (char *)restore_insn_opcodes,
+               sizeof (restore_insn_opcodes));
+
+  clear_proceed_status ();
+  stop_after_trap = 1;
+  proceed (fake_pc, 0, 0);
+
+  restore_inferior_status (&inf_status);
+}
+
+/* This routine should be more specific in it's actions; making sure
+   that it uses the same register in the initial prologue section.
+   Also, FIXME-SOON, it should recognize leaf functions as ones without
+   a SAVE in the prologue, and pass that info back to the caller so the
+   PC and arguments can be properly located.  */
+CORE_ADDR 
+skip_prologue (pc)
+     CORE_ADDR pc;
+{
+  union
+    {
+      unsigned long int code;
+      struct
+       {
+         unsigned int op:2;
+         unsigned int rd:5;
+         unsigned int op2:3;
+         unsigned int imm22:22;
+       } sethi;
+      struct
+       {
+         unsigned int op:2;
+         unsigned int rd:5;
+         unsigned int op3:6;
+         unsigned int rs1:5;
+         unsigned int i:1;
+         unsigned int simm13:13;
+       } add;
+      int i;
+    } x;
+  int dest = -1;
+
+  x.i = read_memory_integer (pc, 4);
+
+  /* Recognize the `sethi' insn and record its destination.  */
+  if (x.sethi.op == 0 && x.sethi.op2 == 4)
+    {
+      dest = x.sethi.rd;
+      pc += 4;
+      x.i = read_memory_integer (pc, 4);
+    }
+
+  /* Recognize an add immediate value to register to either %g1 or
+     the destination register recorded above.  Actually, this might
+     well recognize several different arithmetic operations.  */
+  if (x.add.op == 2 && x.add.i && (x.add.rd == 1 || x.add.rd == dest))
+    {
+      pc += 4;
+      x.i = read_memory_integer (pc, 4);
+    }
+
+  /* This recognizes any SAVE insn.  But why do the XOR and then
+     the compare?  That's identical to comparing against 60 (as long
+     as there isn't any sign extension).  */
+  if (x.add.op == 2 && (x.add.op3 ^ 32) == 28)
+    {
+      pc += 4;
+      x.i = read_memory_integer (pc, 4);
+    }
+
+  /* Now we need to recognize stores into the frame from the input
+     registers.  This recognizes all non alternate stores of input
+     register, into a location offset from the frame pointer.  */
+  while (x.add.op == 3
+        && (x.add.op3 & 0x3c) == 4 /* Store, non-alternate.  */
+        && (x.add.rd & 0x18) == 0x18 /* Input register.  */
+        && x.add.i             /* Immediate mode.  */
+        && x.add.rs1 == 30     /* Off of frame pointer.  */
+        /* Into reserved stack space.  */
+        && x.add.simm13 >= 0x44
+        && x.add.simm13 < 0x5b)
+    {
+      pc += 4;
+      x.i = read_memory_integer (pc, 4);
+    }
+  return pc;
+}
+
+/* Check instruction at ADDR to see if it is an annulled branch.
+   All other instructions will go to NPC or will trap.
+   Set *TARGET if we find a canidate branch; set to zero if not. */
+   
+branch_type
+isannulled (instruction, addr, target)
+     long instruction;
+     CORE_ADDR addr, *target;
+{
+  branch_type val = not_branch;
+  long int offset;             /* Must be signed for sign-extend.  */
+  union
+    {
+      unsigned long int code;
+      struct
+       {
+         unsigned int op:2;
+         unsigned int a:1;
+         unsigned int cond:4;
+         unsigned int op2:3;
+         unsigned int disp22:22;
+       } b;
+    } insn;
+
+  *target = 0;
+  insn.code = instruction;
+
+  if (insn.b.op == 0
+      && (insn.b.op2 == 2 || insn.b.op2 == 6 || insn.b.op2 == 7))
+    {
+      if (insn.b.cond == 8)
+       val = insn.b.a ? baa : ba;
+      else
+       val = insn.b.a ? bicca : bicc;
+      offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
+      *target = addr + offset;
+    }
+
+  return val;
+}
+
+/* sparc_frame_find_saved_regs ()
+
+   Stores, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.
+
+   Note that on register window machines, we are currently making the
+   assumption that window registers are being saved somewhere in the
+   frame in which they are being used.  If they are stored in an
+   inferior frame, find_saved_register will break.
+
+   On the Sun 4, the only time all registers are saved is when
+   a dummy frame is involved.  Otherwise, the only saved registers
+   are the LOCAL and IN registers which are saved as a result
+   of the "save/restore" opcodes.  This condition is determined
+   by address rather than by value.
+
+   The "pc" is not stored in a frame on the SPARC.  (What is stored
+   is a return address minus 8.)  sparc_pop_frame knows how to
+   deal with that.  Other routines might or might not.
+
+   See tm-sparc.h (PUSH_FRAME and friends) for CRITICAL information
+   about how this works.  */
+
+void
+sparc_frame_find_saved_regs (fi, saved_regs_addr)
+     struct frame_info *fi;
+     struct frame_saved_regs *saved_regs_addr;
+{
+  register int regnum;
+  FRAME_ADDR frame = read_register (FP_REGNUM);
+  FRAME fid = FRAME_INFO_ID (fi);
+
+  if (!fid)
+    fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS");
+
+  bzero (saved_regs_addr, sizeof (*saved_regs_addr));
+
+  /* Old test.
+  if (fi->pc >= frame - CALL_DUMMY_LENGTH - 0x140
+      && fi->pc <= frame) */
+
+  if (fi->pc >= (fi->bottom ? fi->bottom :
+                  read_register (SP_REGNUM))
+      && fi->pc <= FRAME_FP(fi))
+    {
+      /* Dummy frame.  All but the window regs are in there somewhere. */
+      for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
+       saved_regs_addr->regs[regnum] =
+         frame + (regnum - G0_REGNUM) * 4 - 0xa0;
+      for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
+       saved_regs_addr->regs[regnum] =
+         frame + (regnum - I0_REGNUM) * 4 - 0xc0;
+      for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++)
+       saved_regs_addr->regs[regnum] =
+         frame + (regnum - FP0_REGNUM) * 4 - 0x80;
+      for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
+       saved_regs_addr->regs[regnum] =
+         frame + (regnum - Y_REGNUM) * 4 - 0xe0;
+      frame = fi->bottom ?
+       fi->bottom : read_register (SP_REGNUM);
+    }
+  else
+    {
+      /* Normal frame.  Just Local and In registers */
+      frame = fi->bottom ?
+       fi->bottom : read_register (SP_REGNUM);
+      for (regnum = L0_REGNUM; regnum < L0_REGNUM+16; regnum++)
+       saved_regs_addr->regs[regnum] = frame + (regnum-L0_REGNUM) * 4;
+    }
+  if (fi->next)
+    {
+      /* Pull off either the next frame pointer or the stack pointer */
+      FRAME_ADDR next_next_frame =
+       (fi->next->bottom ?
+        fi->next->bottom :
+        read_register (SP_REGNUM));
+      for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++)
+       saved_regs_addr->regs[regnum] = next_next_frame + regnum * 4;
+    }
+  /* Otherwise, whatever we would get from ptrace(GETREGS) is accurate */
+  saved_regs_addr->regs[SP_REGNUM] = FRAME_FP (fi);
+}
+
+/* Push an empty stack frame, and record in it the current PC, regs, etc.
+
+   Note that the write's are of registers in the context of the newly
+   pushed frame.  Thus the the fp*'s, the g*'s, the i*'s, and
+   the randoms, of the new frame, are being saved.  The locals and outs
+   are new; they don't need to be saved. The i's and l's of
+   the last frame were saved by the do_save_insn in the register
+   file (now on the stack, since a context switch happended imm after).
+
+   The return pointer register %i7 does not have
+   the pc saved into it (return from this frame will be accomplished
+   by a POP_FRAME).  In fact, we must leave it unclobbered, since we
+   must preserve it in the calling routine except across call instructions.  */
+
+/* Definitely see tm-sparc.h for more doc of the frame format here.  */
+
+void
+sparc_push_dummy_frame ()
+{
+  CORE_ADDR fp;
+  char register_temp[REGISTER_BYTES];
+
+  do_save_insn (0x140); /* FIXME where does this value come from? */
+  fp = read_register (FP_REGNUM);
+
+  read_register_bytes (REGISTER_BYTE (FP0_REGNUM), register_temp, 32 * 4);
+  write_memory (fp - 0x80, register_temp, 32 * 4);
+
+  read_register_bytes (REGISTER_BYTE (G0_REGNUM), register_temp, 8 * 4);
+  write_memory (fp - 0xa0, register_temp, 8 * 4);
+
+  read_register_bytes (REGISTER_BYTE (I0_REGNUM), register_temp, 8 * 4);
+  write_memory (fp - 0xc0, register_temp, 8 * 4);
+
+  /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
+  read_register_bytes (REGISTER_BYTE (Y_REGNUM), register_temp, 8 * 4);
+  write_memory (fp - 0xe0, register_temp, 8 * 4);
+}
+
+/* Discard from the stack the innermost frame, restoring all saved registers.
+
+   Note that the values stored in fsr by get_frame_saved_regs are *in
+   the context of the called frame*.  What this means is that the i
+   regs of fsr must be restored into the o regs of the (calling) frame that
+   we pop into.  We don't care about the output regs of the calling frame,
+   since unless it's a dummy frame, it won't have any output regs in it.
+
+   We never have to bother with %l (local) regs, since the called routine's
+   locals get tossed, and the calling routine's locals are already saved
+   on its stack.  */
+
+/* Definitely see tm-sparc.h for more doc of the frame format here.  */
+
+void
+sparc_pop_frame ()
+{
+  register FRAME frame = get_current_frame ();
+  register CORE_ADDR pc;
+  struct frame_saved_regs fsr;
+  struct frame_info *fi;
+  char raw_buffer[REGISTER_BYTES];
+
+  fi = get_frame_info (frame);
+  get_frame_saved_regs (fi, &fsr);
+  do_restore_insn ();
+  if (fsr.regs[FP0_REGNUM])
+    {
+      read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4);
+      write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer, 32 * 4);
+    }
+  if (fsr.regs[G1_REGNUM])
+    {
+      read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * 4);
+      write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer, 7 * 4);
+    }
+  if (fsr.regs[I0_REGNUM])
+    {
+      read_memory (fsr.regs[I0_REGNUM], raw_buffer, 8 * 4);
+      write_register_bytes (REGISTER_BYTE (O0_REGNUM), raw_buffer, 8 * 4);
+    }
+  if (fsr.regs[PS_REGNUM])
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
+  if (fsr.regs[Y_REGNUM])
+    write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], 4));
+  if (fsr.regs[PC_REGNUM])
+    {
+      /* Explicitly specified PC (and maybe NPC) -- just restore them. */
+      write_register (PC_REGNUM, read_memory_integer (fsr.regs[PC_REGNUM], 4));
+      if (fsr.regs[NPC_REGNUM])
+       write_register (NPC_REGNUM,
+                       read_memory_integer (fsr.regs[NPC_REGNUM], 4));
+    }
+  else if (fsr.regs[I7_REGNUM])
+    {
+      /* Return address in %i7 -- adjust it, then restore PC and NPC from it */
+      pc = PC_ADJUST (read_memory_integer (fsr.regs[I7_REGNUM], 4));
+      write_register (PC_REGNUM,  pc);
+      write_register (NPC_REGNUM, pc + 4);
+    }
+  flush_cached_frames ();
+  set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                       read_pc ()));
+}
+
+/* Structure of SPARC extended floating point numbers.
+   This information is not currently used by GDB, since no current SPARC
+   implementations support extended float.  */
+
+const struct ext_format ext_format_sparc[] = {
+/* tot sbyte smask expbyte manbyte */
+ { 16, 0,    0x80, 0,1,           4,8  },              /* sparc */
+};
diff --git a/gdb/sparc-xdep.c b/gdb/sparc-xdep.c
new file mode 100644 (file)
index 0000000..89fcb8d
--- /dev/null
@@ -0,0 +1,298 @@
+/* Machine-dependent code which would otherwise be in inflow.c and core.c,
+   for GDB, the GNU debugger, for SPARC host systems.
+
+   Copyright (C) 1986, 1987, 1989, 1990  Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "tm-sparc.h"
+#include "param-no-tm.h"
+#include "inferior.h"
+#include "target.h"
+
+#include <sys/param.h>
+#include <sys/file.h>          /* For L_SET */
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include "gdbcore.h"
+#include <sys/core.h>
+
+extern char register_valid[];
+
+/* Fetch one or more registers from the inferior.  REGNO == -1 to get
+   them all.  We actually fetch more than requested, when convenient,
+   marking them as valid so we won't fetch them again.  */
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  int i;
+
+  /* We should never be called with deferred stores, because a prerequisite
+     for writing regs is to have fetched them all (PREPARE_TO_STORE), sigh.  */
+  if (deferred_stores) abort();
+
+  DO_DEFERRED_STORES;
+
+  /* Global and Out regs are fetched directly, as well as the control
+     registers.  If we're getting one of the in or local regs,
+     and the stack pointer has not yet been fetched,
+     we have to do that first, since they're found in memory relative
+     to the stack pointer.  */
+  if (regno < O7_REGNUM  /* including -1 */
+      || regno >= Y_REGNUM
+      || (!register_valid[SP_REGNUM] && regno < I7_REGNUM))
+    {
+      if (0 != ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers))
+           perror("ptrace_getregs");
+      
+      registers[REGISTER_BYTE (0)] = 0;
+      bcopy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (1)], 15 * REGISTER_RAW_SIZE (G0_REGNUM));
+      *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; 
+      *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+      *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
+      *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
+
+      for (i = G0_REGNUM; i <= O7_REGNUM; i++)
+       register_valid[i] = 1;
+      register_valid[Y_REGNUM] = 1;
+      register_valid[PS_REGNUM] = 1;
+      register_valid[PC_REGNUM] = 1;
+      register_valid[NPC_REGNUM] = 1;
+      /* If we don't set these valid, read_register_bytes() rereads
+        all the regs every time it is called!  FIXME.  */
+      register_valid[WIM_REGNUM] = 1;  /* Not true yet, FIXME */
+      register_valid[TBR_REGNUM] = 1;  /* Not true yet, FIXME */
+      register_valid[FPS_REGNUM] = 1;  /* Not true yet, FIXME */
+      register_valid[CPS_REGNUM] = 1;  /* Not true yet, FIXME */
+    }
+
+  /* Floating point registers */
+  if (regno == -1 || (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31))
+    {
+      if (0 != ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers))
+           perror("ptrace_getfpregs");
+      bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+            sizeof inferior_fp_registers.fpu_fr);
+      /* bcopy (&inferior_fp_registers.Fpu_fsr,
+            &registers[REGISTER_BYTE (FPS_REGNUM)],
+            sizeof (FPU_FSR_TYPE));  FIXME???  -- gnu@cyg */
+      for (i = FP0_REGNUM; i <= FP0_REGNUM+31; i++)
+       register_valid[i] = 1;
+      register_valid[FPS_REGNUM] = 1;
+    }
+
+  /* These regs are saved on the stack by the kernel.  Only read them
+     all (16 ptrace calls!) if we really need them.  */
+  if (regno == -1)
+    {
+      target_xfer_memory (*(CORE_ADDR*)&registers[REGISTER_BYTE (SP_REGNUM)],
+                         &registers[REGISTER_BYTE (L0_REGNUM)],
+                         16*REGISTER_RAW_SIZE (L0_REGNUM), 0);
+      for (i = L0_REGNUM; i <= I7_REGNUM; i++)
+       register_valid[i] = 1;
+    }
+  else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+    {
+      CORE_ADDR sp = *(CORE_ADDR*)&registers[REGISTER_BYTE (SP_REGNUM)];
+      i = REGISTER_BYTE (regno);
+      if (register_valid[regno])
+       printf("register %d valid and read\n", regno);
+      target_xfer_memory (sp + i - REGISTER_BYTE (L0_REGNUM),
+                         &registers[i], REGISTER_RAW_SIZE (regno), 0);
+      register_valid[regno] = 1;
+    }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+#define        INT_REGS        1
+#define        STACK_REGS      2
+#define        FP_REGS         4
+int deferred_stores = 0;       /* Cumulates stores we want to do eventually. */
+
+int
+store_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  int wanna_store = INT_REGS + STACK_REGS + FP_REGS;
+
+  /* First decide which pieces of machine-state we need to modify.  
+     Default for regno == -1 case is all pieces.  */
+  if (regno >= 0)
+    if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32)
+      {
+       wanna_store = FP_REGS;
+      }
+    else 
+      {
+       if (regno == SP_REGNUM)
+         wanna_store = INT_REGS + STACK_REGS;
+       else if (regno < L0_REGNUM || regno > I7_REGNUM)
+         wanna_store = INT_REGS;
+       else
+         wanna_store = STACK_REGS;
+      }
+
+  /* See if we're forcing the stores to happen now, or deferring. */
+  if (regno == -2)
+    {
+      wanna_store = deferred_stores;
+      deferred_stores = 0;
+    }
+  else
+    {
+      if (wanna_store == STACK_REGS)
+       {
+         /* Fall through and just store one stack reg.  If we deferred
+            it, we'd have to store them all, or remember more info.  */
+       }
+      else
+       {
+         deferred_stores |= wanna_store;
+         return 0;
+       }
+    }
+
+  if (wanna_store & STACK_REGS)
+    {
+      CORE_ADDR sp = *(CORE_ADDR *)&registers[REGISTER_BYTE (SP_REGNUM)];
+
+      if (regno < 0 || regno == SP_REGNUM)
+       {
+         if (!register_valid[L0_REGNUM+5]) abort();
+         target_xfer_memory (sp, 
+                             &registers[REGISTER_BYTE (L0_REGNUM)],
+                             16*REGISTER_RAW_SIZE (L0_REGNUM), 1);
+       }
+      else
+       {
+         if (!register_valid[regno]) abort();
+         target_xfer_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
+                             &registers[REGISTER_BYTE (regno)],
+                             REGISTER_RAW_SIZE (regno), 1);
+       }
+       
+    }
+
+  if (wanna_store & INT_REGS)
+    {
+      if (!register_valid[G1_REGNUM]) abort();
+
+      bcopy (&registers[REGISTER_BYTE (G1_REGNUM)],
+            &inferior_registers.r_g1, 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+      inferior_registers.r_ps =
+       *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+      inferior_registers.r_pc =
+       *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+      inferior_registers.r_npc =
+       *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)];
+      inferior_registers.r_y =
+       *(int *)&registers[REGISTER_BYTE (Y_REGNUM)];
+
+      if (0 != ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers))
+       perror("ptrace_setregs");
+    }
+
+  if (wanna_store & FP_REGS)
+    {
+      if (!register_valid[FP0_REGNUM+9]) abort();
+      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+            &inferior_fp_registers,
+            sizeof inferior_fp_registers.fpu_fr);
+
+/*      bcopy (&registers[REGISTER_BYTE (FPS_REGNUM)],
+            &inferior_fp_registers.Fpu_fsr,
+            sizeof (FPU_FSR_TYPE));
+****/
+      if (0 !=
+        ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers))
+        perror("ptrace_setfpregs");
+    }
+    return 0;
+}
+\f
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which)
+  char *core_reg_sect;
+  unsigned core_reg_size;
+  int which;
+{
+
+  if (which == 0) {
+
+    /* Integer registers */
+
+#define gregs ((struct regs *)core_reg_sect)
+    /* G0 *always* holds 0.  */
+    *(int *)&registers[REGISTER_BYTE (0)] = 0;
+
+    /* The globals and output registers.  */
+    bcopy (&gregs->r_g1, 
+          &registers[REGISTER_BYTE (G1_REGNUM)],
+          15 * REGISTER_RAW_SIZE (G1_REGNUM));
+    *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
+    *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
+    *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
+    *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
+
+    /* My best guess at where to get the locals and input
+       registers is exactly where they usually are, right above
+       the stack pointer.  If the core dump was caused by a bus error
+       from blowing away the stack pointer (as is possible) then this
+       won't work, but it's worth the try. */
+    {
+      int sp;
+
+      sp = *(int *)&registers[REGISTER_BYTE (SP_REGNUM)];
+      if (0 != target_read_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)], 
+                         16 * REGISTER_RAW_SIZE (L0_REGNUM)))
+       {
+         /* fprintf so user can still use gdb */
+         fprintf (stderr,
+                  "Couldn't read input and local registers from core file\n");
+       }
+    }
+  } else if (which == 2) {
+
+    /* Floating point registers */
+
+#define fpuregs  ((struct fpu *) core_reg_sect)
+    if (core_reg_size >= sizeof (struct fpu))
+      {
+       bcopy (fpuregs->fpu_regs,
+              &registers[REGISTER_BYTE (FP0_REGNUM)],
+              sizeof (fpuregs->fpu_regs));
+       bcopy (&fpuregs->fpu_fsr,
+              &registers[REGISTER_BYTE (FPS_REGNUM)],
+              sizeof (FPU_FSR_TYPE));
+      }
+    else
+      fprintf (stderr, "Couldn't read float regs from core file\n");
+  }
+}
diff --git a/gdb/stab.def b/gdb/stab.def
new file mode 100755 (executable)
index 0000000..58364e1
--- /dev/null
@@ -0,0 +1,182 @@
+/* Table of DBX symbol codes for the GNU system.
+   Copyright (C) 1988 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+/* Global variable.  Only the name is significant.
+   To find the address, look in the corresponding external symbol.  */
+__define_stab (N_GSYM, 0x20, "GSYM")
+
+/* Function name for BSD Fortran.  Only the name is significant.
+   To find the address, look in the corresponding external symbol.  */
+__define_stab (N_FNAME, 0x22, "FNAME")
+
+/* Function name or text-segment variable for C.  Value is its address.
+   Desc is supposedly starting line number, but GCC doesn't set it
+   and DBX seems not to miss it.  */
+__define_stab (N_FUN, 0x24, "FUN")
+
+/* Data-segment variable with internal linkage.  Value is its address.  */
+__define_stab (N_STSYM, 0x26, "STSYM")
+
+/* BSS-segment variable with internal linkage.  Value is its address.  */
+__define_stab (N_LCSYM, 0x28, "LCSYM")
+
+/* Name of main routine.  Only the name is significant.
+   This is not used in C.  */
+__define_stab (N_MAIN, 0x2a, "MAIN")
+
+/* Register variable.  Value is number of register.  */
+__define_stab (N_RSYM, 0x40, "RSYM")
+
+/* Structure or union element.  Value is offset in the structure.  */
+__define_stab (N_SSYM, 0x60, "SSYM")
+
+/* Parameter variable.  Value is offset from argument pointer.
+   (On most machines the argument pointer is the same as the frame pointer.  */
+__define_stab (N_PSYM, 0xa0, "PSYM")
+
+/* Automatic variable in the stack.  Value is offset from frame pointer.
+   Also used for type descriptions.  */
+__define_stab (N_LSYM, 0x80, "LSYM")
+
+/* Alternate entry point.  Value is its address.  */
+__define_stab (N_ENTRY, 0xa4, "ENTRY")
+
+/* Name of main source file.
+   Value is starting text address of the compilation.  */
+__define_stab (N_SO, 0x64, "SO")
+
+/* Name of sub-source file.
+   Value is starting text address of the compilation.  */
+__define_stab (N_SOL, 0x84, "SOL")
+
+/* Line number in text segment.  Desc is the line number;
+   value is corresponding address.  */
+__define_stab (N_SLINE, 0x44, "SLINE")
+/* Similar, for data segment.  */
+__define_stab (N_DSLINE, 0x66, "DSLINE")
+/* Similar, for bss segment.  */
+__define_stab (N_BSLINE, 0x68, "BSLINE")
+
+/* Beginning of an include file.  Only Sun uses this.
+   In an object file, only the name is significant.
+   The Sun linker puts data into some of the other fields.  */
+__define_stab (N_BINCL, 0x82, "BINCL")
+/* End of an include file.  No name.
+   These two act as brackets around the file's output.
+   In an object file, there is no significant data in this entry.
+   The Sun linker puts data into some of the fields.  */
+__define_stab (N_EINCL, 0xa2, "EINCL")
+/* Place holder for deleted include file.
+   This appears only in output from the Sun linker.  */
+__define_stab (N_EXCL, 0xc2, "EXCL")
+
+/* Beginning of lexical block.
+   The desc is the nesting level in lexical blocks.
+   The value is the address of the start of the text for the block.
+   The variables declared inside the block *precede* the N_LBRAC symbol.  */
+__define_stab (N_LBRAC, 0xc0, "LBRAC")
+/* End of a lexical block.  Desc matches the N_LBRAC's desc.
+   The value is the address of the end of the text for the block.  */
+__define_stab (N_RBRAC, 0xe0, "RBRAC")
+
+/* Begin named common block.  Only the name is significant.  */
+__define_stab (N_BCOMM, 0xe2, "BCOMM")
+/* Begin named common block.  Only the name is significant
+   (and it should match the N_BCOMM).  */
+__define_stab (N_ECOMM, 0xe4, "ECOMM")
+/* End common (local name): value is address.
+   I'm not sure how this is used.  */
+__define_stab (N_ECOML, 0xe8, "ECOML")
+/* Second symbol entry containing a length-value for the preceding entry.
+   The value is the length.  */
+__define_stab (N_LENG, 0xfe, "LENG")
+
+/* Global symbol in Pascal.
+   Supposedly the value is its line number; I'm skeptical.  */
+__define_stab (N_PC, 0x30, "PC")
+
+/* Modula-2 compilation unit.  Can someone say what info it contains?  */
+__define_stab (N_M2C, 0x42, "M2C")
+/* Modula-2 scope information.  Can someone say what info it contains?  */
+__define_stab (N_SCOPE, 0xc4, "SCOPE")
+
+/* Sun's source-code browser stabs.  ?? Don't know what the fields are.
+   Supposedly the field is "path to associated .cb file".  */
+__define_stab (N_BROWS, 0x48, "BROWS")
+
+/* GNU C++ exception stabs.  */
+
+/* GNU C++ exception variable.  Name is variable name.  */
+__define_stab (N_EHDECL, 0x50, "EHDECL")
+
+/* GNU C++ `catch' clause.  Value is its address.  Desc is nonzero if
+   this entry is immediately followed by a CAUGHT stab saying what exception
+   was caught.  Multiple CAUGHT stabs means that multiple exceptions
+   can be caught here.  If Desc is 0, it means all exceptions are caught
+   here.  */
+__define_stab (N_CATCH, 0x54, "CATCH")
+
+/* These STAB's are used on Gould systems for Non-Base register symbols
+   or something like that.  FIXME.  I have assigned the values at random
+   since I don't have a Gould here.  Fixups from Gould folk welcome... */
+__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
+__define_stab (N_NBDATA, 0xF2, "NBDATA")
+__define_stab (N_NBBSS,  0xF4, "NBBSS")
+__define_stab (N_NBSTS,  0xF6, "NBSTS")
+__define_stab (N_NBLCS,  0xF8, "NBLCS")
+__define_stab (N_NSYMS,  0xFA, "NSYMS")
+\f
+/* The above information, in matrix format.
+
+                       STAB MATRIX
+       _________________________________________________
+       | 00 - 1F are not dbx stab symbols              |
+       | Entries with bits 01 set are external symbols |
+       | N_UNDEF   | N_ABS     | N_TEXT    | N_DATA    |
+       | N_BSS     | N_COMM    |           | N_FN      |
+       |_______________________________________________|
+       | 20 GSYM   | 22 FNAME  | 24 FUN    | 26 STSYM  |
+       | 28 LCSYM  | 2A MAIN   | 2C        | 2E        |
+       | 30 PC     | 32        | 34        | 36        |
+       | 38        | 3A        | 3C        | 3E        |
+       | 40 RSYM   | 42 M2C    | 44 SLINE  | 46        |
+       | 48 BROWS  | 4A        | 4C        | 4E        |
+       | 50 EHDECL | 52        | 54 CATCH  | 56        |
+       | 58        | 5A        | 5C        | 5E        |
+       | 60 SSYM   | 62        | 64 SO     | 66 DSLINE |
+       | 68 BSLINE | 6A        | 6C        | 6E        |
+       | 70        | 72        | 74        | 76        |
+       | 78        | 7A        | 7C        | 7E        |
+       | 80 LSYM   | 82 BINCL  | 84 SOL    | 86        |
+       | 88        | 8A        | 8C        | 8E        |
+       | 90        | 92        | 94        | 96        |
+       | 98        | 9A        | 9C        | 9E        |
+       | A0 PSYM   | A2 EINCL  | A4 ENTRY  | A6        |
+       | A8        | AA        | AC        | AE        |
+       | B0        | B2        | B4        | B6        |
+       | B8        | BA        | BC        | BE        |
+       | C0 LBRAC  | C2 EXCL   | C4 SCOPE  | C6        |
+       | C8        | CA        | CC        | CE        |
+       | D0        | D2        | D4        | D6        |
+       | D8        | DA        | DC        | DE        |
+       | E0 RBRAC  | E2 BCOMM  | E4 ECOMM  | E6        |
+       | E8 ECOML  | EA        | EC        | EE        |
+       | F0        | F2        | F4        | F6        |
+       | F8        | FA        | FC        | FE LENG   |
+       +-----------------------------------------------+
+
+*/
diff --git a/gdb/stack.c b/gdb/stack.c
new file mode 100644 (file)
index 0000000..0992013
--- /dev/null
@@ -0,0 +1,1139 @@
+/* Print and select stack frames for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "gdbcmd.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "breakpoint.h"
+
+extern int addressprint;       /* Print addresses, or stay symbolic only? */
+extern int info_verbose;       /* Verbosity of symbol reading msgs */
+extern char *reg_names[];      /* Names of registers */
+
+/* Thie "selected" stack frame is used by default for local and arg access.
+   May be zero, for no selected frame.  */
+
+FRAME selected_frame;
+
+/* Level of the selected frame:
+   0 for innermost, 1 for its caller, ...
+   or -1 for frame specified by address with no defined level.  */
+
+int selected_frame_level;
+
+/* Nonzero means print the full filename and linenumber
+   when a frame is printed, and do so in a format programs can parse.  */
+
+int frame_file_full_name = 0;
+
+void print_frame_info ();
+\f
+/* Print a stack frame briefly.  FRAME should be the frame id
+   and LEVEL should be its level in the stack (or -1 for level not defined).
+   This prints the level, the function executing, the arguments,
+   and the file name and line number.
+   If the pc is not at the beginning of the source line,
+   the actual pc is printed at the beginning.
+
+   If SOURCE is 1, print the source line as well.
+   If SOURCE is -1, print ONLY the source line.  */
+
+static void
+print_stack_frame (frame, level, source)
+     FRAME frame;
+     int level;
+     int source;
+{
+  struct frame_info *fi;
+
+  fi = get_frame_info (frame);
+
+  print_frame_info (fi, level, source, 1);
+}
+
+void
+print_frame_info (fi, level, source, args)
+     struct frame_info *fi;
+     register int level;
+     int source;
+     int args;
+{
+  struct symtab_and_line sal;
+  struct symbol *func;
+  register char *funname = 0;
+  int numargs;
+
+#if 0  /* Symbol reading is fast enough now */
+  struct partial_symtab *pst;
+
+  /* Don't give very much information if we haven't readin the
+     symbol table yet.  */
+  pst = find_pc_psymtab (fi->pc);
+  if (pst && !pst->readin)
+    {
+      /* Abbreviated information.  */
+      char *fname;
+
+      if (!find_pc_partial_function (fi->pc, &fname, 0))
+       fname = "??";
+       
+      printf_filtered ("#%-2d ", level);
+      if (addressprint)
+        printf_filtered ("0x%x in ", fi->pc);
+
+      fputs_demangled (fname, stdout, -1);
+      fputs_filtered (" (...)\n", stdout);
+      
+      return;
+    }
+#endif
+
+  sal = find_pc_line (fi->pc, fi->next_frame);
+  func = find_pc_function (fi->pc);
+  if (func)
+    {
+      /* In certain pathological cases, the symtabs give the wrong
+        function (when we are in the first function in a file which
+        is compiled without debugging symbols, the previous function
+        is compiled with debugging symbols, and the "foo.o" symbol
+        that is supposed to tell us where the file with debugging symbols
+        ends has been truncated by ar because it is longer than 15
+        characters).
+
+        So look in the misc_function_vector as well, and if it comes
+        up with a larger address for the function use that instead.
+        I don't think this can ever cause any problems;
+        there shouldn't be any
+        misc_function_vector symbols in the middle of a function.  */
+      int misc_index = find_pc_misc_function (fi->pc);
+      if (misc_index >= 0
+         && (misc_function_vector[misc_index].address
+             > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
+       {
+         /* In this case we have no way of knowing the source file
+            and line number, so don't print them.  */
+         sal.symtab = 0;
+         /* We also don't know anything about the function besides
+            its address and name.  */
+         func = 0;
+         funname = misc_function_vector[misc_index].name;
+       }
+      else
+       funname = SYMBOL_NAME (func);
+    }
+  else
+    {
+      register int misc_index = find_pc_misc_function (fi->pc);
+      if (misc_index >= 0)
+       funname = misc_function_vector[misc_index].name;
+    }
+
+  if (source >= 0 || !sal.symtab)
+    {
+      if (level >= 0)
+       printf_filtered ("#%-2d ", level);
+      if (addressprint)
+       if (fi->pc != sal.pc || !sal.symtab)
+         printf_filtered ("0x%x in ", fi->pc);
+      fputs_demangled (funname ? funname : "??", stdout, -1);
+      wrap_here ("   ");
+      fputs_filtered (" (", stdout);
+      if (args)
+       {
+         FRAME_NUM_ARGS (numargs, fi);
+         print_frame_args (func, fi, numargs, stdout);
+       }
+      printf_filtered (")");
+      if (sal.symtab && sal.symtab->filename)
+       {
+          wrap_here ("   ");
+         printf_filtered (" at %s:%d", sal.symtab->filename, sal.line);
+       }
+      printf_filtered ("\n");
+    }
+
+  if ((source != 0) && sal.symtab)
+    {
+      int done = 0;
+      int mid_statement = source < 0 && fi->pc != sal.pc;
+      if (frame_file_full_name)
+       done = identify_source_line (sal.symtab, sal.line, mid_statement);
+      if (!done)
+       {
+         if (addressprint && mid_statement)
+           printf_filtered ("0x%x\t", fi->pc);
+         print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
+       }
+      current_source_line = max (sal.line - lines_to_list () / 2, 1);
+    }
+  if (source != 0)
+    set_default_breakpoint (1, fi->pc, sal.symtab, sal.line);
+
+  fflush (stdout);
+}
+
+/* Call here to print info on selected frame, after a trap.  */
+
+void
+print_sel_frame (just_source)
+     int just_source;
+{
+  print_stack_frame (selected_frame, -1, just_source ? -1 : 1);
+}
+
+/* Print info on the selected frame, including level number
+   but not source.  */
+
+void
+print_selected_frame ()
+{
+  print_stack_frame (selected_frame, selected_frame_level, 0);
+}
+
+void flush_cached_frames ();
+
+#ifdef FRAME_SPECIFICATION_DYADIC
+extern FRAME setup_arbitrary_frame ();
+#endif
+
+/*
+ * Read a frame specification in whatever the appropriate format is.
+ */
+static FRAME
+parse_frame_specification (frame_exp)
+     char *frame_exp;
+{
+  int numargs = 0;
+  int arg1, arg2;
+  
+  if (frame_exp)
+    {
+      char *addr_string, *p;
+      struct cleanup *tmp_cleanup;
+
+      while (*frame_exp == ' ') frame_exp++;
+      for (p = frame_exp; *p && *p != ' '; p++)
+       ;
+
+      if (*frame_exp)
+       {
+         numargs = 1;
+         addr_string = savestring(frame_exp, p - frame_exp);
+
+         {
+           tmp_cleanup = make_cleanup (free, addr_string);
+           arg1 = parse_and_eval_address (addr_string);
+           do_cleanups (tmp_cleanup);
+         }
+
+         while (*p == ' ') p++;
+         
+         if (*p)
+           {
+             numargs = 2;
+             arg2 = parse_and_eval_address (p);
+           }
+       }
+    }
+
+  switch (numargs)
+    {
+    case 0:
+      return selected_frame;
+      /* NOTREACHED */
+    case 1:
+      {
+       int level = arg1;
+       FRAME fid = find_relative_frame (get_current_frame (), &level);
+       FRAME tfid;
+
+       if (level == 0)
+         /* find_relative_frame was successful */
+         return fid;
+
+       /* If (s)he specifies the frame with an address, he deserves what
+          (s)he gets.  Still, give the highest one that matches.  */
+
+       for (fid = get_current_frame ();
+            fid && FRAME_FP (fid) != arg1;
+            fid = get_prev_frame (fid))
+         ;
+
+       if (fid)
+         while ((tfid = get_prev_frame (fid)) &&
+                (FRAME_FP (tfid) == arg1))
+           fid = tfid;
+         
+#ifdef FRAME_SPECIFICATION_DYADIC
+       if (!fid)
+         error ("Incorrect number of args in frame specification");
+
+       return fid;
+#else
+       return create_new_frame (arg1, 0);
+#endif
+      }
+      /* NOTREACHED */
+    case 2:
+      /* Must be addresses */
+#ifndef FRAME_SPECIFICATION_DYADIC
+      error ("Incorrect number of args in frame specification");
+#else
+      return setup_arbitrary_frame (arg1, arg2);
+#endif
+      /* NOTREACHED */
+    }
+  fatal ("Internal: Error in parsing in parse_frame_specification");
+  /* NOTREACHED */
+}
+
+/* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
+   that if it is unsure about the answer, it returns 0
+   instead of guessing (this happens on the VAX and i960, for example).
+
+   On most machines, we never have to guess about the args address,
+   so FRAME_ARGS_ADDRESS{,_CORRECT} are the same.  */
+#if !defined (FRAME_ARGS_ADDRESS_CORRECT)
+#define FRAME_ARGS_ADDRESS_CORRECT FRAME_ARGS_ADDRESS
+#endif
+
+/* Print verbosely the selected frame or the frame at address ADDR.
+   This means absolutely all information in the frame is printed.  */
+
+static void
+frame_info (addr_exp)
+     char *addr_exp;
+{
+  FRAME frame;
+  struct frame_info *fi;
+  struct frame_saved_regs fsr;
+  struct symtab_and_line sal;
+  struct symbol *func;
+  FRAME calling_frame;
+  int i, count;
+  char *funname = 0;
+
+  if (!target_has_stack)
+    error ("No inferior or core file.");
+
+  frame = parse_frame_specification (addr_exp);
+  if (!frame)
+    error ("Invalid frame specified.");
+
+  fi = get_frame_info (frame);
+  sal = find_pc_line (fi->pc, fi->next_frame);
+  func = get_frame_function (frame);
+  if (func)
+    funname = SYMBOL_NAME (func);
+  else
+    {
+      register int misc_index = find_pc_misc_function (fi->pc);
+      if (misc_index >= 0)
+       funname = misc_function_vector[misc_index].name;
+    }
+  calling_frame = get_prev_frame (frame);
+
+  if (!addr_exp && selected_frame_level >= 0)
+    printf_filtered ("Stack level %d, frame at 0x%x:\n %s = 0x%x",
+           selected_frame_level, FRAME_FP(frame),
+           reg_names[PC_REGNUM], fi->pc);
+  else
+    printf_filtered ("Stack frame at 0x%x:\n %s = 0x%x",
+           FRAME_FP(frame), reg_names[PC_REGNUM], fi->pc);
+
+  wrap_here ("   ");
+  if (funname)
+    printf_filtered (" in %s", funname);
+  wrap_here ("   ");
+  if (sal.symtab)
+    printf_filtered (" (%s:%d)", sal.symtab->filename, sal.line);
+  puts_filtered ("; ");
+  wrap_here ("    ");
+  printf_filtered ("saved %s 0x%x\n", reg_names[PC_REGNUM],
+                                     FRAME_SAVED_PC (frame));
+  if (calling_frame)
+    printf_filtered (" called by frame at 0x%x", FRAME_FP (calling_frame));
+  if (fi->next_frame && calling_frame)
+    puts_filtered (",");
+  wrap_here ("   ");
+  if (fi->next_frame)
+    printf_filtered (" caller of frame at 0x%x", fi->next_frame);
+  if (fi->next_frame || calling_frame)
+    puts_filtered ("\n");
+
+  {
+    /* Address of the argument list for this frame, or 0.  */
+    CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi);
+    /* Number of args for this frame, or -1 if unknown.  */
+    int numargs;
+
+    if (arg_list == 0)
+       printf_filtered (" Arglist at unknown address.\n");
+    else
+      {
+       printf_filtered (" Arglist at 0x%x,", arg_list);
+
+       FRAME_NUM_ARGS (numargs, fi);
+       if (numargs < 0)
+         puts_filtered (" args: ");
+       else if (numargs == 0)
+         puts_filtered (" no args.");
+       else if (numargs == 1)
+         puts_filtered (" 1 arg: ");
+       else
+         printf_filtered (" %d args: ", numargs);
+       print_frame_args (func, fi, numargs, stdout);
+       puts_filtered ("\n");
+      }
+  }
+
+#if defined (FRAME_FIND_SAVED_REGS)  
+  get_frame_saved_regs (fi, &fsr);
+  /* The sp is special; what's returned isn't the save address, but
+     actually the value of the previous frame's sp.  */
+  printf_filtered (" Previous frame's sp is 0x%x\n", fsr.regs[SP_REGNUM]);
+  count = 0;
+  for (i = 0; i < NUM_REGS; i++)
+    if (fsr.regs[i] && i != SP_REGNUM)
+      {
+       if (count == 0)
+         puts_filtered (" Saved registers:\n ");
+       else
+         puts_filtered (",");
+       wrap_here (" ");
+       printf_filtered (" %s at 0x%x", reg_names[i], fsr.regs[i]);
+       count++;
+      }
+  if (count)
+    puts_filtered ("\n");
+#endif /* Have FRAME_FIND_SAVED_REGS.  */
+}
+
+#if 0
+/* Set a limit on the number of frames printed by default in a
+   backtrace.  */
+
+static int backtrace_limit;
+
+static void
+set_backtrace_limit_command (count_exp, from_tty)
+     char *count_exp;
+     int from_tty;
+{
+  int count = parse_and_eval_address (count_exp);
+
+  if (count < 0)
+    error ("Negative argument not meaningful as backtrace limit.");
+
+  backtrace_limit = count;
+}
+
+static void
+backtrace_limit_info (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  if (arg)
+    error ("\"Info backtrace-limit\" takes no arguments.");
+
+  printf ("Backtrace limit: %d.\n", backtrace_limit);
+}
+#endif
+
+/* Print briefly all stack frames or just the innermost COUNT frames.  */
+
+static void
+backtrace_command (count_exp, from_tty)
+     char *count_exp;
+     int from_tty;
+{
+  struct frame_info *fi;
+  register int count;
+  register FRAME frame;
+  register int i;
+  register FRAME trailing;
+  register int trailing_level;
+
+  /* The following code must do two things.  First, it must
+     set the variable TRAILING to the frame from which we should start
+     printing.  Second, it must set the variable count to the number
+     of frames which we should print, or -1 if all of them.  */
+  trailing = get_current_frame ();
+  trailing_level = 0;
+  if (count_exp)
+    {
+      count = parse_and_eval_address (count_exp);
+      if (count < 0)
+       {
+         FRAME current;
+
+         count = -count;
+
+         current = trailing;
+         while (current && count--)
+           {
+             QUIT;
+             current = get_prev_frame (current);
+           }
+         
+         /* Will stop when CURRENT reaches the top of the stack.  TRAILING
+            will be COUNT below it.  */
+         while (current)
+           {
+             QUIT;
+             trailing = get_prev_frame (trailing);
+             current = get_prev_frame (current);
+             trailing_level++;
+           }
+         
+         count = -1;
+       }
+    }
+  else
+    count = -1;
+
+  if (info_verbose)
+    {
+      struct partial_symtab *ps;
+      
+      /* Read in symbols for all of the frames.  Need to do this in
+        a separate pass so that "Reading in symbols for xxx" messages
+        don't screw up the appearance of the backtrace.  Also
+        if people have strong opinions against reading symbols for
+        backtrace this may have to be an option.  */
+      i = count;
+      for (frame = trailing;
+          frame != NULL && i--;
+          frame = get_prev_frame (frame))
+       {
+         QUIT;
+         fi = get_frame_info (frame);
+         ps = find_pc_psymtab (fi->pc);
+         if (ps)
+           (void) PSYMTAB_TO_SYMTAB (ps);      /* Force syms to come in */
+       }
+    }
+
+  for (i = 0, frame = trailing;
+       frame && count--;
+       i++, frame = get_prev_frame (frame))
+    {
+      QUIT;
+      fi = get_frame_info (frame);
+      print_frame_info (fi, trailing_level + i, 0, 1);
+    }
+
+  /* If we've stopped before the end, mention that.  */
+  if (frame && from_tty)
+    printf_filtered ("(More stack frames follow...)\n");
+}
+\f
+/* Print the local variables of a block B active in FRAME.
+   Return 1 if any variables were printed; 0 otherwise.  */
+
+static int
+print_block_frame_locals (b, frame, stream)
+     struct block *b;
+     register FRAME frame;
+     register FILE *stream;
+{
+  int nsyms;
+  register int i;
+  register struct symbol *sym;
+  register int values_printed = 0;
+
+  nsyms = BLOCK_NSYMS (b);
+
+  for (i = 0; i < nsyms; i++)
+    {
+      sym = BLOCK_SYM (b, i);
+      if (SYMBOL_CLASS (sym) == LOC_LOCAL
+         || SYMBOL_CLASS (sym) == LOC_REGISTER
+         || SYMBOL_CLASS (sym) == LOC_STATIC)
+       {
+         values_printed = 1;
+         fprint_symbol (stream, SYMBOL_NAME (sym));
+         fputs_filtered (" = ", stream);
+         print_variable_value (sym, frame, stream);
+         fprintf_filtered (stream, "\n");
+         fflush (stream);
+       }
+    }
+  return values_printed;
+}
+
+/* Same, but print labels.
+   FIXME, this does not even reference FRAME... --gnu  */
+
+static int
+print_block_frame_labels (b, frame, have_default, stream)
+     struct block *b;
+     register FRAME frame;
+     int *have_default;
+     register FILE *stream;
+{
+  int nsyms;
+  register int i;
+  register struct symbol *sym;
+  register int values_printed = 0;
+
+  nsyms = BLOCK_NSYMS (b);
+
+  for (i = 0; i < nsyms; i++)
+    {
+      sym = BLOCK_SYM (b, i);
+      if (! strcmp (SYMBOL_NAME (sym), "default"))
+       {
+         if (*have_default)
+           continue;
+         *have_default = 1;
+       }
+      if (SYMBOL_CLASS (sym) == LOC_LABEL)
+       {
+         struct symtab_and_line sal;
+         sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0);
+         values_printed = 1;
+         fputs_demangled (SYMBOL_NAME (sym), stream, 1);
+         if (addressprint)
+           fprintf_filtered (stream, " 0x%x", SYMBOL_VALUE_ADDRESS (sym));
+         fprintf_filtered (stream, " in file %s, line %d\n",
+                           sal.symtab->filename, sal.line);
+         fflush (stream);
+       }
+    }
+  return values_printed;
+}
+
+/* Print on STREAM all the local variables in frame FRAME,
+   including all the blocks active in that frame
+   at its current pc.
+
+   Returns 1 if the job was done,
+   or 0 if nothing was printed because we have no info
+   on the function running in FRAME.  */
+
+static int
+print_frame_local_vars (frame, stream)
+     register FRAME frame;
+     register FILE *stream;
+{
+  register struct block *block = get_frame_block (frame);
+  register int values_printed = 0;
+
+  if (block == 0)
+    {
+      fprintf_filtered (stream, "No symbol table info available.\n");
+      fflush (stream);
+      return 0;
+    }
+  
+  while (block != 0)
+    {
+      if (print_block_frame_locals (block, frame, stream))
+       values_printed = 1;
+      /* After handling the function's top-level block, stop.
+        Don't continue to its superblock, the block of
+        per-file symbols.  */
+      if (BLOCK_FUNCTION (block))
+       break;
+      block = BLOCK_SUPERBLOCK (block);
+    }
+
+  if (!values_printed)
+    {
+      fprintf_filtered (stream, "No locals.\n");
+      fflush (stream);
+    }
+  
+  return 1;
+}
+
+/* Same, but print labels.  */
+
+static int
+print_frame_label_vars (frame, this_level_only, stream)
+     register FRAME frame;
+     int this_level_only;
+     register FILE *stream;
+{
+  extern struct blockvector *blockvector_for_pc ();
+  register struct blockvector *bl;
+  register struct block *block = get_frame_block (frame);
+  register int values_printed = 0;
+  int index, have_default = 0;
+  char *blocks_printed;
+  struct frame_info *fi = get_frame_info (frame);
+  CORE_ADDR pc = fi->pc;
+
+  if (block == 0)
+    {
+      fprintf_filtered (stream, "No symbol table info available.\n");
+      fflush (stream);
+      return 0;
+    }
+
+  bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
+  blocks_printed = (char *) alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+  bzero (blocks_printed, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+
+  while (block != 0)
+    {
+      CORE_ADDR end = BLOCK_END (block) - 4;
+      int last_index;
+
+      if (bl != blockvector_for_pc (end, &index))
+       error ("blockvector blotch");
+      if (BLOCKVECTOR_BLOCK (bl, index) != block)
+       error ("blockvector botch");
+      last_index = BLOCKVECTOR_NBLOCKS (bl);
+      index += 1;
+
+      /* Don't print out blocks that have gone by.  */
+      while (index < last_index
+            && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < pc)
+       index++;
+
+      while (index < last_index
+            && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < end)
+       {
+         if (blocks_printed[index] == 0)
+           {
+             if (print_block_frame_labels (BLOCKVECTOR_BLOCK (bl, index), frame, &have_default, stream))
+               values_printed = 1;
+             blocks_printed[index] = 1;
+           }
+         index++;
+       }
+      if (have_default)
+       return 1;
+      if (values_printed && this_level_only)
+       return 1;
+
+      /* After handling the function's top-level block, stop.
+        Don't continue to its superblock, the block of
+        per-file symbols.  */
+      if (BLOCK_FUNCTION (block))
+       break;
+      block = BLOCK_SUPERBLOCK (block);
+    }
+
+  if (!values_printed && !this_level_only)
+    {
+      fprintf_filtered (stream, "No catches.\n");
+      fflush (stream);
+    }
+  
+  return values_printed;
+}
+
+static void
+locals_info (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (!target_has_stack)
+    error ("No stack.");
+
+  print_frame_local_vars (selected_frame, stdout);
+}
+
+static void
+catch_info ()
+{
+  if (!target_has_stack)
+    error ("No stack.");
+
+  print_frame_label_vars (selected_frame, 0, stdout);
+}
+
+static int
+print_frame_arg_vars (frame, stream)
+     register FRAME frame;
+     register FILE *stream;
+{
+  struct symbol *func = get_frame_function (frame);
+  register struct block *b;
+  int nsyms;
+  register int i;
+  register struct symbol *sym, *sym2;
+  register int values_printed = 0;
+
+  if (func == 0)
+    {
+      fprintf_filtered (stream, "No symbol table info available.\n");
+      fflush (stream);
+      return 0;
+    }
+
+  b = SYMBOL_BLOCK_VALUE (func);
+  nsyms = BLOCK_NSYMS (b);
+
+  for (i = 0; i < nsyms; i++)
+    {
+      sym = BLOCK_SYM (b, i);
+      if (SYMBOL_CLASS (sym) == LOC_ARG
+         || SYMBOL_CLASS (sym) == LOC_LOCAL_ARG
+         || SYMBOL_CLASS (sym) == LOC_REF_ARG
+         || SYMBOL_CLASS (sym) == LOC_REGPARM)
+       {
+         values_printed = 1;
+         fprint_symbol (stream, SYMBOL_NAME (sym));
+         fputs_filtered (" = ", stream);
+         /* We have to look up the symbol because arguments often have
+            two entries (one a parameter, one a register) and the one
+            we want is the register, which lookup_symbol will find for
+            us.  */
+         sym2 = lookup_symbol (SYMBOL_NAME (sym),
+                       b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+         print_variable_value (sym2, frame, stream);
+         fprintf_filtered (stream, "\n");
+         fflush (stream);
+       }
+    }
+
+  if (!values_printed)
+    {
+      fprintf_filtered (stream, "No arguments.\n");
+      fflush (stream);
+    }
+
+  return 1;
+}
+
+static void
+args_info ()
+{
+  if (!target_has_stack)
+    error ("No stack.");
+  print_frame_arg_vars (selected_frame, stdout);
+}
+\f
+/* Select frame FRAME, and note that its stack level is LEVEL.
+   LEVEL may be -1 if an actual level number is not known.  */
+
+void
+select_frame (frame, level)
+     FRAME frame;
+     int level;
+{
+  selected_frame = frame;
+  selected_frame_level = level;
+  /* Ensure that symbols for this frame are readin.  */
+  if (frame)
+    find_pc_symtab (get_frame_info (frame)->pc);
+}
+
+/* Store the selected frame and its level into *FRAMEP and *LEVELP.  */
+
+void
+record_selected_frame (frameaddrp, levelp)
+     FRAME_ADDR *frameaddrp;
+     int *levelp;
+{
+  *frameaddrp = FRAME_FP (selected_frame);
+  *levelp = selected_frame_level;
+}
+
+/* Return the symbol-block in which the selected frame is executing.
+   Can return zero under various legitimate circumstances.  */
+
+struct block *
+get_selected_block ()
+{
+  if (!target_has_stack)
+    return 0;
+
+  if (!selected_frame)
+    return get_current_block ();
+  return get_frame_block (selected_frame);
+}
+
+/* Find a frame a certain number of levels away from FRAME.
+   LEVEL_OFFSET_PTR points to an int containing the number of levels.
+   Positive means go to earlier frames (up); negative, the reverse.
+   The int that contains the number of levels is counted toward
+   zero as the frames for those levels are found.
+   If the top or bottom frame is reached, that frame is returned,
+   but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates
+   how much farther the original request asked to go.  */
+
+FRAME
+find_relative_frame (frame, level_offset_ptr)
+     register FRAME frame;
+     register int* level_offset_ptr;
+{
+  register FRAME prev;
+  register FRAME frame1, frame2;
+
+  /* Going up is simple: just do get_prev_frame enough times
+     or until initial frame is reached.  */
+  while (*level_offset_ptr > 0)
+    {
+      prev = get_prev_frame (frame);
+      if (prev == 0)
+       break;
+      (*level_offset_ptr)--;
+      frame = prev;
+    }
+  /* Going down could be done by iterating get_frame_info to
+     find the next frame, but that would be quadratic
+     since get_frame_info must scan all the way from the current frame.
+     The following algorithm is linear.  */
+  if (*level_offset_ptr < 0)
+    {
+      /* First put frame1 at innermost frame
+        and frame2 N levels up from there.  */
+      frame1 = get_current_frame ();
+      frame2 = frame1;
+      while (*level_offset_ptr < 0 && frame2 != frame)
+       {
+         frame2 = get_prev_frame (frame2);
+         (*level_offset_ptr) ++;
+       }
+      /* Then slide frame1 and frame2 up in synchrony
+        and when frame2 reaches our starting point
+        frame1 must be N levels down from there.  */
+      while (frame2 != frame)
+       {
+         frame1 = get_prev_frame (frame1);
+         frame2 = get_prev_frame (frame2);
+       }
+      return frame1;
+    }
+  return frame;
+}
+
+/* The "frame" command.  With no arg, print selected frame briefly.
+   With arg LEVEL_EXP, select the frame at level LEVEL if it is a
+   valid level.  Otherwise, treat level_exp as an address expression
+   and print it.  See parse_frame_specification for more info on proper
+   frame expressions. */
+
+static void
+frame_command (level_exp, from_tty)
+     char *level_exp;
+     int from_tty;
+{
+  register FRAME frame, frame1;
+  unsigned int level = 0;
+
+  if (!target_has_stack)
+    error ("No stack.");
+
+  frame = parse_frame_specification (level_exp);
+
+  for (frame1 = get_prev_frame (0);
+       frame1 && frame1 != frame;
+       frame1 = get_prev_frame (frame1))
+    level++;
+
+  if (!frame1)
+    level = 0;
+
+  select_frame (frame, level);
+
+  if (!from_tty)
+    return;
+
+  print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* Select the frame up one or COUNT stack levels
+   from the previously selected frame, and print it briefly.  */
+
+static void
+up_silently_command (count_exp, from_tty)
+     char *count_exp;
+     int from_tty;
+{
+  register FRAME frame;
+  int count = 1, count1;
+  if (count_exp)
+    count = parse_and_eval_address (count_exp);
+  count1 = count;
+  
+  if (!target_has_stack)
+    error ("No stack.");
+
+  frame = find_relative_frame (selected_frame, &count1);
+  if (count1 != 0 && count_exp == 0)
+    error ("Initial frame selected; you cannot go up.");
+  select_frame (frame, selected_frame_level + count - count1);
+}
+
+static void
+up_command (count_exp, from_tty)
+     char *count_exp;
+     int from_tty;
+{
+  up_silently_command (count_exp, from_tty);
+  print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* Select the frame down one or COUNT stack levels
+   from the previously selected frame, and print it briefly.  */
+
+static void
+down_silently_command (count_exp, from_tty)
+     char *count_exp;
+     int from_tty;
+{
+  register FRAME frame;
+  int count = -1, count1;
+  if (count_exp)
+    count = - parse_and_eval_address (count_exp);
+  count1 = count;
+  
+  frame = find_relative_frame (selected_frame, &count1);
+  if (count1 != 0 && count_exp == 0)
+    error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
+  select_frame (frame, selected_frame_level + count - count1);
+}
+
+
+static void
+down_command (count_exp, from_tty)
+     char *count_exp;
+     int from_tty;
+{
+  down_silently_command (count_exp, from_tty);
+  print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+\f
+static void
+return_command (retval_exp, from_tty)
+     char *retval_exp;
+     int from_tty;
+{
+  struct symbol *thisfun = get_frame_function (selected_frame);
+  FRAME_ADDR selected_frame_addr = FRAME_FP (selected_frame);
+  CORE_ADDR selected_frame_pc = (get_frame_info (selected_frame))->pc;
+  FRAME frame;
+
+  /* If interactive, require confirmation.  */
+
+  if (from_tty)
+    {
+      if (thisfun != 0)
+       {
+         if (!query ("Make %s return now? ", SYMBOL_NAME (thisfun)))
+           error ("Not confirmed.");
+       }
+      else
+       if (!query ("Make selected stack frame return now? "))
+         error ("Not confirmed.");
+    }
+
+  /* Do the real work.  Pop until the specified frame is current.  We
+     use this method because the selected_frame is not valid after
+     a POP_FRAME.  The pc comparison makes this work even if the
+     selected frame shares its fp with another frame.  */
+
+  while ( selected_frame_addr != FRAME_FP (frame = get_current_frame())
+       || selected_frame_pc   != (get_frame_info (frame))->pc  )
+    POP_FRAME;
+
+  /* Then pop that frame.  */
+
+  POP_FRAME;
+
+  /* Compute the return value (if any) and store in the place
+     for return values.  */
+
+  if (retval_exp)
+    set_return_value (parse_and_eval (retval_exp));
+
+  /* If interactive, print the frame that is now current.  */
+
+  if (from_tty)
+    frame_command ("0", 1);
+}
+\f
+void
+_initialize_stack ()
+{
+#if 0  
+  backtrace_limit = 30;
+#endif
+
+  add_com ("return", class_stack, return_command,
+          "Make selected stack frame return to its caller.\n\
+Control remains in the debugger, but when you continue\n\
+execution will resume in the frame above the one now selected.\n\
+If an argument is given, it is an expression for the value to return.");
+
+  add_com ("up", class_stack, up_command,
+          "Select and print stack frame that called this one.\n\
+An argument says how many frames up to go.");
+  add_com ("up-silently", class_support, up_silently_command,
+          "Same as the `up' command, but does not print anything.\n\
+This is useful in command scripts.");
+
+  add_com ("down", class_stack, down_command,
+          "Select and print stack frame called by this one.\n\
+An argument says how many frames down to go.");
+  add_com_alias ("do", "down", class_stack, 1);
+  add_com ("down-silently", class_support, down_silently_command,
+          "Same as the `down' command, but does not print anything.\n\
+This is useful in command scripts.");
+
+  add_com ("frame", class_stack, frame_command,
+          "Select and print a stack frame.\n\
+With no argument, print the selected stack frame.  (See also \"info frame\").\n\
+An argument specifies the frame to select.\n\
+It can be a stack frame number or the address of the frame.\n\
+With argument, nothing is printed if input is coming from\n\
+a command file or a user-defined command.");
+
+  add_com_alias ("f", "frame", class_stack, 1);
+
+  add_com ("backtrace", class_stack, backtrace_command,
+          "Print backtrace of all stack frames, or innermost COUNT frames.\n\
+With a negative argument, print outermost -COUNT frames.");
+  add_com_alias ("bt", "backtrace", class_stack, 0);
+  add_com_alias ("where", "backtrace", class_alias, 0);
+  add_info ("stack", backtrace_command,
+           "Backtrace of the stack, or innermost COUNT frames.");
+  add_info_alias ("s", "stack", 1);
+  add_info ("frame", frame_info,
+           "All about selected stack frame, or frame at ADDR.");
+  add_info_alias ("f", "frame", 1);
+  add_info ("locals", locals_info,
+           "Local variables of current stack frame.");
+  add_info ("args", args_info,
+           "Argument variables of current stack frame.");
+  add_info ("catch", catch_info,
+           "Exceptions that can be caught in the current stack frame.");
+
+#if 0
+  add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command, 
+          "Specify maximum number of frames for \"backtrace\" to print by default.",
+          &setlist);
+  add_info ("backtrace-limit", backtrace_limit_info,
+           "The maximum number of frames for \"backtrace\" to print by default.");
+#endif
+}
+
diff --git a/gdb/standalone.c b/gdb/standalone.c
new file mode 100644 (file)
index 0000000..fcb6e7e
--- /dev/null
@@ -0,0 +1,594 @@
+/* Interface to bare machine for GDB running as kernel debugger.
+   Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined (SIGTSTP) && defined (SIGIO)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* SIGTSTP and SIGIO defined (must be 4.2) */
+
+#include "defs.h"
+#include "param.h"
+#include "signals.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+\f
+/* Random system calls, mostly no-ops to prevent link problems  */
+
+ioctl (desc, code, arg)
+{}
+
+int (* signal ()) ()
+{}
+
+kill ()
+{}
+
+getpid ()
+{
+  return 0;
+}
+
+sigsetmask ()
+{}
+
+chdir ()
+{}
+
+char *
+getwd (buf)
+     char *buf;
+{
+  buf[0] = '/';
+  buf[1] = 0;
+  return buf;
+}
+
+/* Used to check for existence of .gdbinit.  Say no.  */
+
+access ()
+{
+  return -1;
+}
+
+exit ()
+{
+  error ("Fatal error; restarting.");
+}
+\f
+/* Reading "files".  The contents of some files are written into kdb's
+   data area before it is run.  These files are used to contain the
+   symbol table for kdb to load, and the source files (in case the
+   kdb user wants to print them).  The symbols are stored in a file
+   named "kdb-symbols" in a.out format (except that all the text and
+   data have been stripped to save room).
+
+   The files are stored in the following format:
+   int     number of bytes of data for this file, including these four.
+   char[]  name of the file, ending with a null.
+   padding to multiple of 4 boundary.
+   char[]  file contents.  The length can be deduced from what was
+           specified before.  There is no terminating null here.
+
+   If the int at the front is zero, it means there are no more files.
+
+   Opening a file in kdb returns a nonzero value to indicate success,
+   but the value does not matter.  Only one file can be open, and only
+   for reading.  All the primitives for input from the file know
+   which file is open and ignore what is specified for the descriptor
+   or for the stdio stream.
+
+   Input with fgetc can be done either on the file that is open
+   or on stdin (which reads from the terminal through tty_input ()  */
+
+/* Address of data for the files stored in format described above.  */
+char *files_start;
+
+/* The file stream currently open:  */
+
+char *sourcebeg;               /* beginning of contents */
+int sourcesize;                        /* size of contents */
+char *sourceptr;               /* current read pointer */
+int sourceleft;                        /* number of bytes to eof */
+
+/* "descriptor" for the file now open.
+   Incremented at each close.
+   If specified descriptor does not match this,
+   it means the program is trying to use a closed descriptor.
+   We report an error for that.  */
+
+int sourcedesc;
+
+open (filename, modes)
+     char *filename;
+     int modes;
+{
+  register char *next;
+
+  if (modes)
+    {
+      errno = EROFS;
+      return -1;
+    }
+
+  if (sourceptr)
+    {
+      errno = EMFILE;
+      return -1;
+    }
+
+  for (next - files_start; * (int *) next;
+       next += * (int *) next)
+    {
+      if (!strcmp (next + 4, filename))
+       {
+         sourcebeg = next + 4 + strlen (next + 4) + 1;
+         sourcebeg = (char *) (((int) sourcebeg + 3) & (-4));
+         sourceptr = sourcebeg;
+         sourcesize = next + * (int *) next - sourceptr;
+         sourceleft = sourcesize;
+         return sourcedesc;
+       }
+    }
+  return 0;
+}
+
+close (desc)
+     int desc;
+{
+  sourceptr = 0;
+  sourcedesc++;
+  /* Don't let sourcedesc get big enough to be confused with stdin.  */
+  if (sourcedesc == 100)
+    sourcedesc = 5;
+}
+
+FILE *
+fopen (filename, modes)
+     char *filename;
+     char *modes;
+{
+  return (FILE *) open (filename, *modes == 'w');
+}
+
+FILE *
+fdopen (desc)
+     int desc;
+{
+  return (FILE *) desc;
+}
+
+fclose (desc)
+     int desc;
+{
+  close (desc);
+}
+
+fstat (desc, statbuf)
+     struct stat *statbuf;
+{
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  statbuf->st_size = sourcesize;
+}
+
+myread (desc, destptr, size, filename)
+     int desc;
+     char *destptr;
+     int size;
+     char *filename;
+{
+  int len = min (sourceleft, size);
+
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  bcopy (sourceptr, destptr, len);
+  sourceleft -= len;
+  return len;
+}
+
+int
+fread (bufp, numelts, eltsize, stream)
+{
+  register int elts = min (numelts, sourceleft / eltsize);
+  register int len = elts * eltsize;
+
+  if (stream != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  bcopy (sourceptr, bufp, len);
+  sourceleft -= len;
+  return elts;
+}
+
+int
+fgetc (desc)
+     int desc;
+{
+
+  if (desc == (int) stdin)
+    return tty_input ();
+
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  if (sourceleft-- <= 0)
+    return EOF;
+  return *sourceptr++;
+}
+
+lseek (desc, pos)
+     int desc;
+     int pos;
+{
+
+  if (desc != sourcedesc)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  if (pos < 0 || pos > sourcesize)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  sourceptr = sourcebeg + pos;
+  sourceleft = sourcesize - pos;
+}
+\f
+/* Output in kdb can go only to the terminal, so the stream
+   specified may be ignored.  */
+
+printf (a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+  char buffer[1024];
+  sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  display_string (buffer);
+}
+
+fprintf (ign, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+  char buffer[1024];
+  sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  display_string (buffer);
+}
+
+fwrite (buf, numelts, size, stream)
+     register char *buf;
+     int numelts, size;
+{
+  register int i = numelts * size;
+  while (i-- > 0)
+    fputc (*buf++, stream);
+}
+
+fputc (c, ign)
+{
+  char buf[2];
+  buf[0] = c;
+  buf[1] = 0;
+  display_string (buf);
+}
+
+/* sprintf refers to this, but loading this from the
+   library would cause fflush to be loaded from it too.
+   In fact there should be no need to call this (I hope).  */
+
+_flsbuf ()
+{
+  error ("_flsbuf was actually called.");
+}
+
+fflush (ign)
+{
+}
+\f
+/* Entries into core and inflow, needed only to make things link ok.  */
+
+exec_file_command ()
+{}
+
+core_file_command ()
+{}
+
+char *
+get_exec_file (err)
+     int err;
+{
+  /* Makes one printout look reasonable; value does not matter otherwise.  */
+  return "run";
+}
+
+have_core_file_p ()
+{
+  return 0;
+}
+
+kill_command ()
+{
+  inferior_pid = 0;
+}
+
+terminal_inferior ()
+{}
+
+terminal_ours ()
+{}
+
+terminal_init_inferior ()
+{}
+
+write_inferior_register ()
+{}
+
+read_inferior_register ()
+{}
+
+read_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  bcopy (memaddr, myaddr, len);
+}
+
+/* Always return 0 indicating success.  */
+
+write_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  bcopy (myaddr, memaddr, len);
+  return 0;
+}
+
+static REGISTER_TYPE saved_regs[NUM_REGS];
+
+REGISTER_TYPE
+read_register (regno)
+     int regno;
+{
+  if (regno < 0 || regno >= NUM_REGS)
+    error ("Register number %d out of range.", regno);
+  return saved_regs[regno];
+}
+
+void
+write_register (regno, value)
+     int regno;
+     REGISTER_TYPE value;
+{
+  if (regno < 0 || regno >= NUM_REGS)
+    error ("Register number %d out of range.", regno);
+  saved_regs[regno] = value;
+}
+\f
+/* System calls needed in relation to running the "inferior".  */
+
+vfork ()
+{
+  /* Just appear to "succeed".  Say the inferior's pid is 1.  */
+  return 1;
+}
+
+/* These are called by code that normally runs in the inferior
+   that has just been forked.  That code never runs, when standalone,
+   and these definitions are so it will link without errors.  */
+
+ptrace ()
+{}
+
+setpgrp ()
+{}
+
+execle ()
+{}
+
+_exit ()
+{}
+\f
+/* Malloc calls these.  */
+
+malloc_warning (str)
+     char *str;
+{
+  printf ("\n%s.\n\n", str);
+}
+
+char *next_free;
+char *memory_limit;
+
+char *
+sbrk (amount)
+     int amount;
+{
+  if (next_free + amount > memory_limit)
+    return (char *) -1;
+  next_free += amount;
+  return next_free - amount;
+}
+
+/* Various ways malloc might ask where end of memory is.  */
+
+char *
+ulimit ()
+{
+  return memory_limit;
+}
+
+int
+vlimit ()
+{
+  return memory_limit - next_free;
+}
+
+getrlimit (addr)
+     struct rlimit *addr;
+{
+  addr->rlim_cur = memory_limit - next_free;
+}
+\f
+/* Context switching to and from program being debugged.  */
+
+/* GDB calls here to run the user program.
+   The frame pointer for this function is saved in
+   gdb_stack by save_frame_pointer; then we restore
+   all of the user program's registers, including PC and PS.  */
+
+static int fault_code;
+static REGISTER_TYPE gdb_stack;
+
+resume ()
+{
+  REGISTER_TYPE restore[NUM_REGS];
+
+  PUSH_FRAME_PTR;
+  save_frame_pointer ();
+
+  bcopy (saved_regs, restore, sizeof restore);
+  POP_REGISTERS;
+  /* Control does not drop through here!  */
+}
+
+save_frame_pointer (val)
+     CORE_ADDR val;
+{
+  gdb_stack = val;
+}
+
+/* Fault handlers call here, running in the user program stack.
+   They must first push a fault code,
+   old PC, old PS, and any other info about the fault.
+   The exact format is machine-dependent and is known only
+   in the definition of PUSH_REGISTERS.  */
+
+fault ()
+{
+  /* Transfer all registers and fault code to the stack
+     in canonical order: registers in order of GDB register number,
+     followed by fault code.  */
+  PUSH_REGISTERS;
+
+  /* Transfer them to saved_regs and fault_code.  */
+  save_registers ();
+
+  restore_gdb ();
+  /* Control does not reach here */
+}
+
+restore_gdb ()
+{
+  CORE_ADDR new_fp = gdb_stack;
+  /* Switch to GDB's stack  */
+  POP_FRAME_PTR;
+  /* Return from the function `resume'.  */
+}
+
+/* Assuming register contents and fault code have been pushed on the stack as
+   arguments to this function, copy them into the standard place
+   for the program's registers while GDB is running.  */
+
+save_registers (firstreg)
+     int firstreg;
+{
+  bcopy (&firstreg, saved_regs, sizeof saved_regs);
+  fault_code = (&firstreg)[NUM_REGS];
+}
+
+/* Store into the structure such as `wait' would return
+   the information on why the program faulted,
+   converted into a machine-independent signal number.  */
+
+static int fault_table[] = FAULT_TABLE;
+
+int
+wait (w)
+     WAITTYPE *w;
+{
+  WSETSTOP (*w, fault_table[fault_code / FAULT_CODE_UNITS]);
+  return inferior_pid;
+}
+\f
+/* Allocate a big space in which files for kdb to read will be stored.
+   Whatever is left is where malloc can allocate storage.
+
+   Initialize it, so that there will be space in the executable file
+   for it.  Then the files can be put into kdb by writing them into
+   kdb's executable file.  */
+
+/* The default size is as much space as we expect to be available
+   for kdb to use!  */
+
+#ifndef HEAP_SIZE
+#define HEAP_SIZE 400000
+#endif
+
+char heap[HEAP_SIZE] = {0};
+
+#ifndef STACK_SIZE
+#define STACK_SIZE 100000
+#endif
+
+int kdb_stack_beg[STACK_SIZE / sizeof (int)];
+int kdb_stack_end;
+
+_initialize_standalone ()
+{
+  register char *next;
+
+  /* Find start of data on files.  */
+
+  files_start = heap;
+
+  /* Find the end of the data on files.  */
+
+  for (next - files_start; * (int *) next;
+       next += * (int *) next)
+    {}
+
+  /* That is where free storage starts for sbrk to give out.  */
+  next_free = next;
+
+  memory_limit = heap + sizeof heap;
+}
+
diff --git a/gdb/stddef.h b/gdb/stddef.h
new file mode 100755 (executable)
index 0000000..d95a815
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+/* Signed type of difference of two pointers.  */
+
+typedef long ptrdiff_t;
+
+/* Unsigned type of `sizeof' something.  */
+
+#ifndef _SIZE_T        /* in case <sys/types.h> has defined it. */
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif /* _SIZE_T */
+
+/* A null pointer constant.  */
+
+#undef NULL            /* in case <stdio.h> has defined it. */
+#define NULL 0
+
+/* Offset of member MEMBER in a struct of type TYPE.  */
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* _STDDEF_H */
diff --git a/gdb/stdlib.h b/gdb/stdlib.h
new file mode 100755 (executable)
index 0000000..40ce167
--- /dev/null
@@ -0,0 +1,10 @@
+/* Fake stdlib.h supplying the stuff needed by malloc. */
+
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern void EXFUN(abort, (void));
+extern void EXFUN(free, (PTR));
+extern PTR EXFUN(malloc, (size_t));
+extern PTR EXFUN(realloc, (PTR, size_t));
diff --git a/gdb/stuff.c b/gdb/stuff.c
new file mode 100644 (file)
index 0000000..2ffdc97
--- /dev/null
@@ -0,0 +1,174 @@
+/* Program to stuff files into a specially prepared space in kdb.
+   Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written 13-Mar-86 by David Bridgham. */
+
+#include <stdio.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <varargs.h>
+
+extern char *sys_errlist[];
+
+main (argc, argv)
+     int argc;
+     char *argv[];
+{
+  register char *cp;
+  char *outfile;
+  register int i;
+  int offset;
+  int out_fd, in_fd;
+  struct stat stat_buf;
+  int size, pad;
+  char buf[1024];
+  static char zeros[4] = {0};
+
+  if (argc < 4)
+    err("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n",
+       argv[0]);
+
+  outfile = 0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-o") == 0)
+       outfile = argv[++i];
+    }
+  if (outfile == 0)
+    err("Output file not specified\n");
+
+  offset = get_offset (outfile, "_heap");
+
+  out_fd = open (outfile, O_WRONLY);
+  if (out_fd < 0)
+    err ("Error opening %s for write: %s\n", outfile, sys_errlist[errno]);
+  if (lseek (out_fd, offset, 0) < 0)
+    err ("Error seeking to heap in %s: %s\n", outfile, sys_errlist[errno]);
+
+  /* For each file listed on the command line, write it into the
+   * 'heap' of the output file.  Make sure to skip the arguments
+   * that name the output file. */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-o") == 0)
+       continue;
+      if ((in_fd = open (argv[i], O_RDONLY)) < 0)
+       err ("Error opening %s for read: %s\n", argv[i], sys_errlist[errno]);
+      if (fstat (in_fd, &stat_buf) < 0)
+       err ("Error stat'ing %s: %s\n", argv[i], sys_errlist[errno]);
+      size = strlen (argv[i]);
+      pad = 4 - (size & 3);
+      size += pad + stat_buf.st_size + sizeof (int);
+      write (out_fd, &size, sizeof (int));
+      write (out_fd, argv[i], strlen (argv[i]));
+      write (out_fd, zeros, pad);
+      while ((size = read (in_fd, buf, sizeof (buf))) > 0)
+       write (out_fd, buf, size);
+      close (in_fd);
+    }
+  size = 0;
+  write (out_fd, &size, sizeof (int));
+  close (out_fd);
+  return (0);
+}
+
+/* Read symbol table from file and returns the offset into the file
+ * where symbol sym_name is located.  If error, print message and
+ * exit. */
+get_offset (file, sym_name)
+     char *file;
+     char *sym_name;
+{
+  int f;
+  struct exec file_hdr;
+  struct nlist *symbol_table;
+  int size;
+  char *strings;
+
+  f = open (file, O_RDONLY);
+  if (f < 0)
+    err ("Error opening %s: %s\n", file, sys_errlist[errno]);
+  if (read (f, &file_hdr, sizeof (file_hdr)) < 0)
+    err ("Error reading exec structure: %s\n", sys_errlist[errno]);
+  if (N_BADMAG (file_hdr))
+    err ("File %s not an a.out file\n", file);
+
+  /* read in symbol table */
+  if ((symbol_table = (struct nlist *)malloc (file_hdr.a_syms)) == 0)
+    err ("Couldn't allocate space for symbol table\n");
+  if (lseek (f, N_SYMOFF (file_hdr), 0) == -1)
+    err ("lseek error: %s\n", sys_errlist[errno]);
+  if (read (f, symbol_table, file_hdr.a_syms) == -1)
+    err ("Error reading symbol table from %s: %s\n", file, sys_errlist[errno]);
+
+  /* read in string table */
+  if (read (f, &size, 4) == -1)
+    err ("reading string table size: %s\n", sys_errlist[errno]);
+  if ((strings = (char *)malloc (size)) == 0)
+    err ("Couldn't allocate memory for string table\n");
+  if (read (f, strings, size - 4) == -1)
+    err ("reading string table: %s\n", sys_errlist[errno]);
+
+  /* Find the core address at which the first byte of kdb text segment
+     should be loaded into core when kdb is run.  */
+  origin = find_symbol ("_etext", symbol_table, file_hdr.a_syms, strings)
+    - file_hdr.a_text;
+  /* Find the core address at which the heap will appear.  */
+  coreaddr = find_symbol (sym_name, symbol_table, file_hdr.a_syms, strings);
+  /* Return address in file of the heap data space.  */
+  return (N_TXTOFF (file_hdr) + core_addr - origin);
+}
+
+find_symbol (sym_name, symbol_table, length, strings)
+     char *sym_name;
+     struct nlist *symbol_table;
+     int length;
+     char *strings;
+{
+  register struct nlist *sym;
+
+  /* Find symbol in question */
+  for (sym = symbol_table;
+       sym != (struct nlist *)((char *)symbol_table + length);
+       sym++)
+      {
+       if ((sym->n_type & N_TYPE) != N_DATA) continue;
+       if (sym->n_un.n_strx == 0) continue;
+       if (strcmp (sym_name, strings + sym->n_un.n_strx - 4) == 0)
+         return sym->n_value;
+      }
+    err ("Data symbol %s not found in %s\n", sym_name, file);
+}
+
+/* VARARGS */
+void
+err (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *string;
+
+  va_start (args);
+  string = va_arg (args, char *);
+  vfprintf (stderr, string, args);
+  va_end (args);
+  exit (-1);
+}
diff --git a/gdb/sun3-xdep.c b/gdb/sun3-xdep.c
new file mode 100644 (file)
index 0000000..6789cd6
--- /dev/null
@@ -0,0 +1,133 @@
+/* Sun-3 Machine-dependent code which would otherwise be in inflow.c and core.c,
+   for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "inferior.h"
+
+#include <sys/ptrace.h>
+#define KERNEL         /* To get floating point reg definitions */
+#include <machine/reg.h>
+
+#include "gdbcore.h"
+
+extern int errno;
+
+void
+fetch_inferior_registers ()
+{
+  struct regs inferior_registers;
+#ifdef FP0_REGNUM
+  struct fp_status inferior_fp_registers;
+#endif
+  extern char registers[];
+
+  registers_fetched ();
+  
+  ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+#ifdef FP0_REGNUM
+  ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+#endif 
+  
+  bcopy (&inferior_registers, registers, 16 * 4);
+#ifdef FP0_REGNUM
+  bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+        sizeof inferior_fp_registers.fps_regs);
+#endif 
+  *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+  *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+#ifdef FP0_REGNUM
+  bcopy (&inferior_fp_registers.fps_control,
+        &registers[REGISTER_BYTE (FPC_REGNUM)],
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif 
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+#ifdef FP0_REGNUM
+  struct fp_status inferior_fp_registers;
+#endif
+  extern char registers[];
+
+  bcopy (registers, &inferior_registers, 16 * 4);
+#ifdef FP0_REGNUM
+  bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+        sizeof inferior_fp_registers.fps_regs);
+#endif
+  inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+  inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+
+#ifdef FP0_REGNUM
+  bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+        &inferior_fp_registers.fps_control,
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif
+
+  ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+#if FP0_REGNUM
+  ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+#endif
+}
+
+/* Machine-dependent code for pulling registers out of a Sun-3 core file. */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which)
+     char *core_reg_sect;
+     unsigned core_reg_size;
+     int which;
+{
+  extern char registers[];
+  struct regs *regs = (struct regs *) core_reg_sect;
+
+  if (which == 0) {
+    if (core_reg_size < sizeof (struct regs))
+      error ("Can't find registers in core file");
+
+    bcopy ((char *)regs, registers, 16 * 4);
+    supply_register (PS_REGNUM, &regs->r_ps);
+    supply_register (PC_REGNUM, &regs->r_pc);
+
+  } else if (which == 2) {
+
+#define fpustruct  ((struct fpu *) core_reg_sect)
+
+    if (core_reg_size >= sizeof (struct fpu))
+      {
+       bcopy (fpustruct->f_fpstatus.fps_regs,
+             &registers[REGISTER_BYTE (FP0_REGNUM)],
+             sizeof fpustruct->f_fpstatus.fps_regs);
+       bcopy (&fpustruct->f_fpstatus.fps_control,
+             &registers[REGISTER_BYTE (FPC_REGNUM)],
+             sizeof fpustruct->f_fpstatus - 
+               sizeof fpustruct->f_fpstatus.fps_regs);
+      }
+    else
+      fprintf (stderr, "Couldn't read float regs from core file\n");
+  }
+}
diff --git a/gdb/sun386-xdep.c b/gdb/sun386-xdep.c
new file mode 100644 (file)
index 0000000..d9f1cb5
--- /dev/null
@@ -0,0 +1,252 @@
+/* Machine-dependent code for host Sun 386i's for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Changes for sun386i by Jean Daniel Fekete (jdf@litp.univ-p6-7.fr),
+   C2V Paris, April 89.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "signame.h"
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/core.h>
+\f
+void
+fetch_inferior_registers ()
+{
+  struct regs inferior_registers;
+  struct fp_state inferior_fp_registers;
+  extern char registers[];
+
+  registers_fetched ();
+
+  ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+  ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+
+  bcopy (&inferior_registers, registers, sizeof inferior_registers);
+
+  bcopy (inferior_fp_registers.f_st,&registers[REGISTER_BYTE (FP0_REGNUM)],
+        sizeof inferior_fp_registers.f_st);
+  bcopy (&inferior_fp_registers.f_ctrl,
+        &registers[REGISTER_BYTE (FPC_REGNUM)],
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+store_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_state inferior_fp_registers;
+  extern char registers[];
+
+  bcopy (registers, &inferior_registers, 20 * 4);
+
+  bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],inferior_fp_registers.f_st,
+        sizeof inferior_fp_registers.f_st);
+  bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+        &inferior_fp_registers.f_ctrl,
+        sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+  
+#ifdef PTRACE_FP_BUG
+  if (regno == FP_REGNUM || regno == -1)
+    /* Storing the frame pointer requires a gross hack, in which an
+       instruction that moves eax into ebp gets single-stepped.  */
+    {
+      int stack = inferior_registers.r_reg[SP_REGNUM];
+      int stuff = ptrace (PTRACE_PEEKDATA, inferior_pid, stack);
+      int reg = inferior_registers.r_reg[EAX];
+      inferior_registers.r_reg[EAX] =
+       inferior_registers.r_reg[FP_REGNUM];
+      ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+      ptrace (PTRACE_POKEDATA, inferior_pid, stack, 0xc589);
+      ptrace (PTRACE_SINGLESTEP, inferior_pid, stack, 0);
+      wait (0);
+      ptrace (PTRACE_POKEDATA, inferior_pid, stack, stuff);
+      inferior_registers.r_reg[EAX] = reg;
+    }
+#endif
+  ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+  ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+}
+
+/* Machine-dependent code which would otherwise be in core.c */
+/* Work with core files, for GDB. */
+
+\f
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+
+      {
+       struct core corestr;
+
+       val = myread (corechan, &corestr, sizeof corestr);
+       if (val < 0)
+         perror_with_name (filename);
+       if (corestr.c_magic != CORE_MAGIC)
+         error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)",
+                filename, corestr.c_magic, (int) CORE_MAGIC);
+       else if (sizeof (struct core) != corestr.c_len)
+         error ("\"%s\" has an invalid struct core length (%d, expected %d)",
+                filename, corestr.c_len, (int) sizeof (struct core));
+
+       data_start = exec_data_start;
+       data_end = data_start + corestr.c_dsize;
+       stack_start = stack_end - corestr.c_ssize;
+       data_offset = sizeof corestr;
+       stack_offset = sizeof corestr + corestr.c_dsize;
+
+       bcopy (&corestr.c_regs, registers, sizeof corestr.c_regs);
+
+       bcopy (corestr.c_fpu.f_fpstatus.f_st,
+              &registers[REGISTER_BYTE (FP0_REGNUM)],
+              sizeof corestr.c_fpu.f_fpstatus.f_st);
+       bcopy (&corestr.c_fpu.f_fpstatus.f_ctrl,
+              &registers[REGISTER_BYTE (FPC_REGNUM)],
+              sizeof corestr.c_fpu.f_fpstatus -
+              sizeof corestr.c_fpu.f_fpstatus.f_st);
+
+       /* the struct aouthdr of sun coff is not the struct exec stored
+          in the core file. */
+       bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
+#ifndef COFF_ENCAPSULATE
+       core_aouthdr.magic = corestr.c_aouthdr.a_info;
+       core_aouthdr.vstamp = /*SUNVERSION*/ 31252;
+#endif
+       printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
+       if (corestr.c_signo > 0)
+         printf ("Program terminated with signal %d, %s.\n",
+                       corestr.c_signo,
+                       corestr.c_signo < NSIG
+                       ? sys_siglist[corestr.c_signo]
+                       : "(undocumented)");
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      select_frame (get_current_frame (), 0);
+
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
+
+i387_to_double (from, to)
+     char *from;
+     char *to;
+{
+  long *lp;
+  /* push extended mode on 387 stack, then pop in double mode
+   *
+   * first, set exception masks so no error is generated -
+   * number will be rounded to inf or 0, if necessary 
+   */
+  asm ("pushl %eax");          /* grab a stack slot */
+  asm ("fstcw (%esp)");                /* get 387 control word */
+  asm ("movl (%esp),%eax");    /* save old value */
+  asm ("orl $0x3f,%eax");              /* mask all exceptions */
+  asm ("pushl %eax");
+  asm ("fldcw (%esp)");                /* load new value into 387 */
+  
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldt (%eax)");         /* push extended number on 387 stack */
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpl (%eax)");                /* pop double */
+  asm ("fwait");
+  
+  asm ("popl %eax");           /* flush modified control word */
+  asm ("fnclex");                      /* clear exceptions */
+  asm ("fldcw (%esp)");                /* restore original control word */
+  asm ("popl %eax");           /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+     char *from;
+     char *to;
+{
+  /* push double mode on 387 stack, then pop in extended mode
+   * no errors are possible because every 64-bit pattern
+   * can be converted to an extended
+   */
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldl (%eax)");
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpt (%eax)");
+  asm ("fwait");
+}
diff --git a/gdb/symfile.c b/gdb/symfile.c
new file mode 100644 (file)
index 0000000..31aa1e2
--- /dev/null
@@ -0,0 +1,746 @@
+/* Generic symbol file reading for the GNU debugger, GDB.
+   Copyright 1990, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support, using pieces from other GDB modules.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "symtab.h"
+#include "param.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "target.h"
+#include "value.h"
+#include "symfile.h"
+#include "gdbcmd.h"
+#include "breakpoint.h"
+
+#include <obstack.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+
+extern int info_verbose;
+
+extern int close ();
+extern void qsort ();
+extern char *getenv ();
+
+/* Functions this file defines */
+static bfd *symfile_open();
+static struct sym_fns *symfile_init();
+
+/* List of all available sym_fns.  */
+
+struct sym_fns *symtab_fns = NULL;
+
+/* Saves the sym_fns of the current symbol table, so we can call
+   the right sym_discard function when we free it.  */
+
+static struct sym_fns *symfile_fns;
+
+/* Allocate an obstack to hold objects that should be freed
+   when we load a new symbol table.
+   This includes the symbols made by dbxread
+   and the types that are not permanent.  */
+
+struct obstack obstack1;
+
+struct obstack *symbol_obstack = &obstack1;
+
+/* This obstack will be used for partial_symbol objects.  It can
+   probably actually be the same as the symbol_obstack above, but I'd
+   like to keep them seperate for now.  If I want to later, I'll
+   replace one with the other.  */
+
+struct obstack obstack2;
+
+struct obstack *psymbol_obstack = &obstack2;
+
+/* File name symbols were loaded from.  */
+
+char *symfile = 0;
+
+/* The modification date of the file when they were loaded.  */
+
+int symfile_mtime = 0;
+
+/* Structures with which to manage partial symbol allocation.  */
+
+struct psymbol_allocation_list global_psymbols = {0}, static_psymbols = {0};
+
+/* Structure to manage complaints about symbol file contents.  */
+
+struct complaint complaint_root[1] = {
+  {(char *)0, 0, complaint_root},
+};
+
+\f
+/* In the following sort, we always make sure that
+   register debug symbol declarations always come before regular
+   debug symbol declarations (as might happen when parameters are
+   then put into registers by the compiler).  */
+
+static int
+compare_symbols (s1, s2)
+     struct symbol **s1, **s2;
+{
+  register int namediff;
+
+  /* Compare the initial characters.  */
+  namediff = SYMBOL_NAME (*s1)[0] - SYMBOL_NAME (*s2)[0];
+  if (namediff != 0) return namediff;
+
+  /* If they match, compare the rest of the names.  */
+  namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2));
+  if (namediff != 0) return namediff;
+
+  /* For symbols of the same name, registers should come first.  */
+  return ((SYMBOL_CLASS (*s2) == LOC_REGISTER)
+         - (SYMBOL_CLASS (*s1) == LOC_REGISTER));
+}
+
+/* Call sort_block_syms to sort alphabetically the symbols of one block.  */
+
+void
+sort_block_syms (b)
+     register struct block *b;
+{
+  qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+        sizeof (struct symbol *), compare_symbols);
+}
+
+/* Call sort_symtab_syms to sort alphabetically
+   the symbols of each block of one symtab.  */
+
+void
+sort_symtab_syms (s)
+     register struct symtab *s;
+{
+  register struct blockvector *bv = BLOCKVECTOR (s);
+  int nbl = BLOCKVECTOR_NBLOCKS (bv);
+  int i;
+  register struct block *b;
+
+  for (i = 0; i < nbl; i++)
+    {
+      b = BLOCKVECTOR_BLOCK (bv, i);
+      if (BLOCK_SHOULD_SORT (b))
+       sort_block_syms (b);
+    }
+}
+
+void
+sort_all_symtab_syms ()
+{
+  register struct symtab *s;
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      sort_symtab_syms (s);
+    }
+}
+
+/* Make a copy of the string at PTR with SIZE characters in the symbol obstack
+   (and add a null character at the end in the copy).
+   Returns the address of the copy.  */
+
+char *
+obsavestring (ptr, size)
+     char *ptr;
+     int size;
+{
+  register char *p = (char *) obstack_alloc (symbol_obstack, size + 1);
+  /* Open-coded bcopy--saves function call time.
+     These strings are usually short.  */
+  {
+    register char *p1 = ptr;
+    register char *p2 = p;
+    char *end = ptr + size;
+    while (p1 != end)
+      *p2++ = *p1++;
+  }
+  p[size] = 0;
+  return p;
+}
+
+/* Concatenate strings S1, S2 and S3; return the new string.
+   Space is found in the symbol_obstack.  */
+
+char *
+obconcat (s1, s2, s3)
+     char *s1, *s2, *s3;
+{
+  register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+  register char *val = (char *) obstack_alloc (symbol_obstack, len);
+  strcpy (val, s1);
+  strcat (val, s2);
+  strcat (val, s3);
+  return val;
+}
+\f
+/* Accumulate the misc functions in bunches of 127.
+   At the end, copy them all into one newly allocated structure.  */
+
+#define MISC_BUNCH_SIZE 127
+
+struct misc_bunch
+{
+  struct misc_bunch *next;
+  struct misc_function contents[MISC_BUNCH_SIZE];
+};
+
+/* Bunch currently being filled up.
+   The next field points to chain of filled bunches.  */
+
+static struct misc_bunch *misc_bunch;
+
+/* Number of slots filled in current bunch.  */
+
+static int misc_bunch_index;
+
+/* Total number of misc functions recorded so far.  */
+
+static int misc_count;
+
+void
+init_misc_bunches ()
+{
+  misc_count = 0;
+  misc_bunch = 0;
+  misc_bunch_index = MISC_BUNCH_SIZE;
+}
+
+void
+prim_record_misc_function (name, address, misc_type)
+     char *name;
+     CORE_ADDR address;
+     enum misc_function_type misc_type;
+{
+  register struct misc_bunch *new;
+
+  if (misc_bunch_index == MISC_BUNCH_SIZE)
+    {
+      new = (struct misc_bunch *) xmalloc (sizeof (struct misc_bunch));
+      misc_bunch_index = 0;
+      new->next = misc_bunch;
+      misc_bunch = new;
+    }
+  misc_bunch->contents[misc_bunch_index].name = name;
+  misc_bunch->contents[misc_bunch_index].address = address;
+  misc_bunch->contents[misc_bunch_index].type = misc_type;
+  misc_bunch->contents[misc_bunch_index].misc_info = 0;
+  misc_bunch_index++;
+  misc_count++;
+}
+
+static int
+compare_misc_functions (fn1, fn2)
+     struct misc_function *fn1, *fn2;
+{
+  /* Return a signed result based on unsigned comparisons
+     so that we sort into unsigned numeric order.  */
+  if (fn1->address < fn2->address)
+    return -1;
+  if (fn1->address > fn2->address)
+    return 1;
+  return 0;
+}
+
+/* ARGSUSED */
+void
+discard_misc_bunches (foo)
+     int foo;
+{
+  register struct misc_bunch *next;
+
+  while (misc_bunch)
+    {
+      next = misc_bunch->next;
+      free (misc_bunch);
+      misc_bunch = next;
+    }
+}
+
+/* INCLINK nonzero means bunches are from an incrementally-linked file.
+   Add them to the existing bunches.
+   Otherwise INCLINK is zero, and we start from scratch. */
+void
+condense_misc_bunches (inclink)
+     int inclink;
+{
+  register int i, j;
+  register struct misc_bunch *bunch;
+
+  if (inclink)
+    {
+      misc_function_vector
+       = (struct misc_function *)
+         xrealloc (misc_function_vector, (misc_count + misc_function_count)
+                   * sizeof (struct misc_function));
+      j = misc_function_count;
+    }
+  else
+    {
+      misc_function_vector
+       = (struct misc_function *)
+         xmalloc (misc_count * sizeof (struct misc_function));
+      j = 0;
+    }
+
+  bunch = misc_bunch;
+  while (bunch)
+    {
+      for (i = 0; i < misc_bunch_index; i++, j++)
+        {
+         misc_function_vector[j] = bunch->contents[i];
+#ifdef NAMES_HAVE_UNDERSCORE
+         if (misc_function_vector[j].name[0] == '_')
+             misc_function_vector[j].name++;
+#endif
+       }
+      bunch = bunch->next;
+      misc_bunch_index = MISC_BUNCH_SIZE;
+    }
+
+  if (misc_function_count + misc_count != j)           /* DEBUG */
+    printf_filtered ("Function counts are off!  %d + %d != %d\n",
+      misc_function_count, misc_count, j);
+
+  misc_function_count = j;
+
+  /* Sort the misc functions by address.  */
+
+  qsort (misc_function_vector, misc_function_count,
+        sizeof (struct misc_function),
+        compare_misc_functions);
+}
+
+
+/* Get the symbol table that corresponds to a partial_symtab.
+   This is fast after the first time you do it.  In fact, there
+   is an even faster macro PSYMTAB_TO_SYMTAB that does the fast
+   case inline.  */
+
+struct symtab *
+psymtab_to_symtab (pst)
+     register struct partial_symtab *pst;
+{
+  register struct symtab *result;
+
+  /* If it's been looked up before, return it. */
+  if (pst->symtab)
+    return pst->symtab;
+
+  /* If it has not yet been read in, read it.  */
+  if (!pst->readin)
+    { 
+      (*pst->read_symtab) (pst);
+    }
+
+  /* Search through list for correct name. */
+  for (result = symtab_list; result; result = result->next)
+    if (!strcmp (result->filename, pst->filename))
+      {
+       pst->symtab = result;           /* Remember where it was.  */
+       return result;
+      }
+
+  return 0;
+}
+
+/* Process a symbol file, as either the main file or as a dynamically
+   loaded file.
+
+   NAME is the file name (which will be tilde-expanded and made absolute
+   herein).  FROM_TTY says how verbose to be.  MAINLINE specifies whether
+   this is the main symbol file, or whether it's an extra symbol file
+   such as dynamically loaded code.  If !mainline, ADDR is the address
+   where the text segment was loaded.  */
+
+void
+symbol_file_add (name, from_tty, addr, mainline)
+     char *name;
+     int from_tty;
+     CORE_ADDR addr;
+     int mainline;
+{
+  bfd *sym_bfd;
+  asection *text_sect;
+  struct sym_fns *sf;
+  char *realname;
+
+  sym_bfd = symfile_open (name);
+
+  entry_point = bfd_get_start_address (sym_bfd);
+
+  if (mainline)
+    symfile_mtime = bfd_get_mtime (sym_bfd);
+
+  /* There is a distinction between having no symbol table
+     (we refuse to read the file, leaving the old set of symbols around)
+     and having no debugging symbols in your symbol table (we read
+     the file and end up with a mostly empty symbol table).  */
+
+  if (!(bfd_get_file_flags (sym_bfd) & HAS_SYMS))
+    {
+      error ("%s has no symbol-table", name);
+    }
+
+  if ((symtab_list || partial_symtab_list)
+      && mainline
+      && from_tty
+      && !query ("Load new symbol table from \"%s\"? ", name))
+    error ("Not confirmed.");
+
+  if (from_tty)
+    {
+      printf ("Reading symbol data from %s...", name);
+      fflush (stdout);
+    }
+
+  sf = symfile_init (sym_bfd);
+  realname = bfd_get_filename (sym_bfd);
+  realname = savestring (realname, strlen (realname));
+  /* FIXME, this probably creates a storage leak... */
+
+  if (mainline) 
+    {
+      /* Since no error yet, throw away the old symbol table.  */
+
+      if (symfile)
+       free (symfile);
+      symfile = 0;
+      free_all_symtabs ();
+      free_all_psymtabs ();
+
+      (*sf->sym_new_init) ();
+
+      /* For mainline, caller didn't know the specified address of the
+         text section.  We fix that here.  */
+      text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+      addr = bfd_section_vma (sym_bfd, text_sect);
+    }
+
+  clear_complaints();  /* Allow complaints to appear for this new file. */
+
+  (*sf->sym_read) (sf, addr, mainline);
+
+  /* Don't allow char * to have a typename (else would get caddr_t.)  */
+  /* Ditto void *.  FIXME should do this for all the builtin types.  */
+
+  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+  TYPE_NAME (lookup_pointer_type (builtin_type_void)) = 0;
+
+  if (mainline)
+    {
+      /* OK, make it the "real" symbol file.  */
+      symfile = realname;
+      symfile_fns = sf;
+    }
+
+  if (from_tty)
+    {
+      printf ("done.\n");
+      fflush (stdout);
+    }
+}
+
+/* This is the symbol-file command.  Read the file, analyze its symbols,
+   and add a struct symtab to symtab_list.  */
+
+void
+symbol_file_command (name, from_tty)
+     char *name;
+     int from_tty;
+{
+
+  dont_repeat ();
+
+  if (name == 0)
+    {
+      if ((symtab_list || partial_symtab_list)
+         && from_tty
+         && !query ("Discard symbol table from `%s'? ", symfile))
+       error ("Not confirmed.");
+      if (symfile)
+       free (symfile);
+      symfile = 0;
+      free_all_symtabs ();
+      free_all_psymtabs ();
+      /* FIXME, this does not account for the main file and subsequent
+         files (shared libs, dynloads, etc) having different formats. 
+         It only calls the cleanup routine for the main file's format.  */
+      (*symfile_fns->sym_new_init) ();
+      free (symfile_fns);
+      symfile_fns = 0;
+      return;
+    }
+
+  symbol_file_add (name, from_tty, (CORE_ADDR)0, 1);
+}
+
+/* Open NAME and hand it off to BFD for preliminary analysis.  Result
+   is a BFD *, which includes a new copy of NAME dynamically allocated
+   (which will be freed by the cleanup chain).  In case of trouble,
+   error() is called.  */
+
+static bfd *
+symfile_open (name)
+     char *name;
+{
+  bfd *sym_bfd;
+  int desc;
+  char *absolute_name;
+
+  name = tilde_expand (name);
+  make_cleanup (free, name);
+
+  desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
+  if (desc < 0)
+    perror_with_name (name);
+  else
+    {
+      make_cleanup (free, absolute_name);
+      name = absolute_name;
+    }
+
+  sym_bfd = bfd_fdopenr (name, NULL, desc);
+  if (!sym_bfd)
+    {
+      close (desc);
+      error ("Could not open `%s' to read symbols: %s",
+            name, bfd_errmsg (bfd_error));
+    }
+  make_cleanup (bfd_close, sym_bfd);
+
+  if (!bfd_check_format (sym_bfd, bfd_object))
+    error ("\"%s\": can't read symbols: %s.",
+          name, bfd_errmsg (bfd_error));
+
+  return sym_bfd;
+}
+
+/* Link a new symtab_fns into the global symtab_fns list.
+   Called by various _initialize routines.  */
+
+void
+add_symtab_fns (sf)
+     struct sym_fns *sf;
+{
+  sf->next = symtab_fns;
+  symtab_fns = sf;
+}
+
+
+/* Initialize to read symbols from the symbol file sym_bfd.  It either
+   returns or calls error().  The result is a malloc'd struct sym_fns
+   that contains cached information about the symbol file.  */
+
+static struct sym_fns *
+symfile_init (sym_bfd)
+     bfd *sym_bfd;
+{
+  struct sym_fns *sf, *sf2;
+
+  for (sf = symtab_fns; sf != NULL; sf = sf->next)
+    {
+      if (!strncmp (bfd_get_target (sym_bfd), sf->sym_name, sf->sym_namelen))
+       {
+         sf2 = (struct sym_fns *)xmalloc (sizeof (*sf2));      
+         /* FIXME, who frees this? */
+         *sf2 = *sf;
+         sf2->sym_bfd = sym_bfd;
+         sf2->sym_private = 0;                 /* Not alloc'd yet */
+         (*sf2->sym_init) (sf2);
+         return sf2;
+       }
+    }
+  error ("I'm sorry, Dave, I can't do that.  Symbol format unknown.");
+}
+\f
+/* This function runs the load command of our current target.  */
+
+void
+load_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  target_load (arg, from_tty);
+}
+
+/* This function runs the add_syms command of our current target.  */
+
+void
+add_syms_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  target_add_syms (args, from_tty);
+}
+
+/* This function allows the addition of incrementally linked object files.  */
+
+void
+add_syms_addr_command (arg_string, from_tty)
+     char* arg_string;
+     int from_tty;
+{
+  char *name;
+  CORE_ADDR text_addr;
+  
+  if (arg_string == 0)
+    error ("add-syms takes a file name and an address");
+
+  arg_string = tilde_expand (arg_string);
+  make_cleanup (free, arg_string);
+
+  for( ; *arg_string == ' '; arg_string++ );
+  name = arg_string;
+  for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
+  *arg_string++ = (char) 0;
+
+  if (name[0] == 0)
+    error ("add-syms takes a file name and an address");
+
+  text_addr = parse_and_eval_address (arg_string);
+
+  dont_repeat ();
+
+  if (!query ("add symbol table from file \"%s\" at text_addr = 0x%x\n",
+             name, text_addr))
+    error ("Not confirmed.");
+
+  symbol_file_add (name, 0, text_addr, 0);
+}
+\f
+/* Re-read symbols if the symbol-file has changed.  */
+void
+reread_symbols ()
+{
+  struct stat symstat;
+
+  /* With the addition of shared libraries, this should be modified,
+     the load time should be saved in the partial symbol tables, since
+     different tables may come from different source files.  FIXME.
+     This routine should then walk down each partial symbol table
+     and see if the symbol table that it originates from has been changed
+  */
+
+  if (stat (symfile, &symstat) < 0)
+    /* Can't read symbol-file.  Assume it is up to date.  */
+    return;
+
+  if (symstat.st_mtime > symfile_mtime)
+    {
+      printf_filtered ("Symbol file has changed; re-reading symbols.\n");
+      symbol_file_command (symfile, 0);
+      breakpoint_re_set ();
+    }
+}
+
+
+/* This function is really horrible, but to avoid it, there would need
+   to be more filling in of forward references.  */
+int
+fill_in_vptr_fieldno (type)
+     struct type *type;
+{
+  check_stub_type (type);
+  if (TYPE_VPTR_FIELDNO (type) < 0)
+    TYPE_VPTR_FIELDNO (type) =
+      fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1));
+  return TYPE_VPTR_FIELDNO (type);
+}
+\f
+/* Functions to handle complaints during symbol reading.  */
+
+/* How many complaints about a particular thing should be printed before
+   we stop whining about it?  */
+
+static unsigned stop_whining = 1;
+
+/* Print a complaint about the input symbols, and link the complaint block
+   into a chain for later handling.  Result is 1 if the complaint was
+   printed, 0 if it was suppressed.  */
+
+int
+complain (complaint, val)
+     struct complaint *complaint;
+     char *val;
+{
+  complaint->counter++;
+  if (complaint->next == 0) {
+    complaint->next = complaint_root->next;
+    complaint_root->next = complaint;
+  }
+  if (complaint->counter > stop_whining)
+    return 0;
+  wrap_here ("");
+  if (!info_verbose) {
+    puts_filtered ("During symbol reading...");
+  }
+  printf_filtered (complaint->message, val);
+  puts_filtered ("...");
+  wrap_here("");
+  if (!info_verbose)
+    puts_filtered ("\n");
+  return 1;
+}
+
+/* Clear out all complaint counters that have ever been incremented.  */
+
+void
+clear_complaints ()
+{
+  struct complaint *p;
+
+  for (p = complaint_root->next; p != complaint_root; p = p->next)
+    p->counter = 0;
+}
+\f
+void
+_initialize_symfile ()
+{
+
+  add_com ("symbol-file", class_files, symbol_file_command,
+          "Load symbol table from executable file FILE.\n\
+The `file' command can also load symbol tables, as well as setting the file\n\
+to execute.");
+
+  add_com ("add-syms", class_files, add_syms_command,
+   "Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\
+The second argument provides the starting address of the file's text.");
+
+  add_com ("load", class_files, load_command,
+   "Dynamically load FILE into the running program, and record its symbols\n\
+for access from GDB.");
+
+  add_show_from_set
+    (add_set_cmd ("complaints", class_support, var_uinteger,
+                 (char *)&stop_whining,
+         "Set max number of complaints about incorrect symbols.",
+                 &setlist),
+     &showlist);
+
+  obstack_init (symbol_obstack);
+  obstack_init (psymbol_obstack);
+}
diff --git a/gdb/symfile.h b/gdb/symfile.h
new file mode 100644 (file)
index 0000000..6785117
--- /dev/null
@@ -0,0 +1,170 @@
+/* Definitions for reading symbol files into GDB.
+   Copyright (C) 1990  Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This file requires that you first include "bfd.h".  */
+
+/* Data structures and function definitions for dealing with
+   symbol table reading from files.  */
+
+/* Structure to keep track of symbol reading functions for various
+   object file types.  */
+
+struct sym_fns {
+
+  /* sym_name
+     is the name, or name prefix, of the BFD "target type" that this
+     set of functions handles.  E.g. "a.out" or "sunOs" or "coff".  */
+
+  char *sym_name;
+
+  /* sym_namelen
+     counts how many bytes of sym_name should be checked against the
+     BFD target type of the file being read.  If an exact match is
+     desired, specify the number of characters in sym_name plus 1 for the
+     NUL.  If a prefix match is desired, specify the number of characters in
+     sym_name.  */
+
+  int sym_namelen;
+
+  /* sym_new_init
+     initializes anything that is global to the entire
+     symbol table.  It is called e.g. during symbol_file_command, when
+     we begin debugging an entirely new program.  */
+
+  void (*sym_new_init) ();
+
+  /* sym_init (sf)
+     reads any initial information from a symbol file, and
+     initializes the struct sym_fns SF in preparation for sym_read().
+     It is called every time we read a symbol file for any reason.  */
+
+  void (*sym_init) ();
+
+  /* sym_read (sf, addr, mainline)
+     reads a symbol file into a psymtab (or possibly a symtab).
+     SF is the struct sym_fns that sym_init initialized.  ADDR
+     is the offset between the file's specified start address and
+     its true address in memory.  MAINLINE is 1 if this is the
+     main symbol table being read, and 0 if a secondary
+     symbol file (e.g. shared library or dynamically loaded file)
+     is being read.  */
+
+  void (*sym_read) ();
+
+  /* sym_discard (sf)
+     discards any cached information from SF or elsewhere, that
+     was saved as part of reading a single symbol file.  */
+
+  void (*sym_discard) ();
+
+  /* sym_bfd
+     is the accessor for the symbol file being read.  */
+
+  bfd  *sym_bfd;
+
+  /* sym_private
+     is where information can be shared among sym_init, sym_read and
+     sym_discard.  It is typically a pointer to malloc'd memory.  */
+
+  char *sym_private;                   /* Should be void * */
+
+  /* next
+     finds the next struct sym_fns.  They are allocated and initialized
+     in whatever module implements the functions pointed to; an 
+     initializer calls add_symtab_fns to add them to the global chain.  */
+  struct sym_fns *next;
+};
+
+                       /*   Functions   */
+
+extern void free_named_symtab ();
+extern int  fill_in_vptr_fieldno ();
+extern void add_symtab_fns ();
+
+/* Functions for dealing with the misc "function" vector, really a misc
+   address<->symbol mapping vector for things we don't have debug symbols
+   for.  */
+
+extern void init_misc_bunches ();
+extern void prim_record_misc_function ();
+extern void discard_misc_bunches ();
+extern void condense_misc_bunches ();
+
+/* Sorting your symbols for fast lookup or alphabetical printing.  */
+
+extern void sort_block_syms ();
+extern void sort_symtab_syms ();
+extern void sort_all_symtab_syms ();
+extern void sort_block_syms ();
+
+/* Make a copy of the string at PTR with SIZE characters in the symbol obstack
+   (and add a null character at the end in the copy).
+   Returns the address of the copy.  */
+
+extern char *obsavestring ();
+
+/* Concatenate strings S1, S2 and S3; return the new string.
+   Space is found in the symbol_obstack.  */
+
+extern char *obconcat ();
+
+                       /*   Variables   */
+
+/* File name symbols were loaded from.  */
+
+extern char *symfile;
+
+/* The modification date of the file when they were loaded.  */
+
+extern int symfile_mtime;
+
+/* The BFD for this file -- only good while we're actively reading
+   symbols into a psymtab or a symtab.  */
+
+static bfd *symfile_bfd;
+
+/* Vectors of all partial symbols read in from file.  */
+
+extern struct psymbol_allocation_list {
+  struct partial_symbol *list, *next;
+  int size;
+} global_psymbols, static_psymbols;
+
+/* Support for complaining about things in the symbol file that aren't
+   catastrophic.
+
+   Each such thing gets a counter.  The first time we have the problem,
+   during a symbol read, we report it.  At the end of symbol reading,
+   if verbose, we report how many of each problem we had.  */
+
+struct complaint {
+  char *message;
+  unsigned counter;
+  struct complaint *next;
+};
+
+/* Root of the chain of complaints that have at some point been issued. 
+   This is used to reset the counters, and/or report the total counts.  */
+
+extern struct complaint complaint_root[1];
+
+/* Functions that handle complaints.  (in symfile.c)  */
+
+int complain();
+void clear_complaints();
diff --git a/gdb/symmetry-tdep.c b/gdb/symmetry-tdep.c
new file mode 100755 (executable)
index 0000000..aba21c3
--- /dev/null
@@ -0,0 +1,494 @@
+/* Sequent Symmetry target interface, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "gdbcore.h"
+#include <fcntl.h>
+
+static long i386_get_frame_setup ();
+static i386_follow_jump ();
+
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+exec_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+
+  /* Eliminate all traces of old exec file.
+     Mark text segment as empty.  */
+
+  if (execfile)
+    free (execfile);
+  execfile = 0;
+  data_start = 0;
+  data_end -= exec_data_start;
+  text_start = 0;
+  text_end = 0;
+  exec_data_start = 0;
+  exec_data_end = 0;
+  if (execchan >= 0)
+    close (execchan);
+  execchan = -1;
+
+  /* Now open and digest the file the user requested, if any.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+                       &execfile);
+      if (execchan < 0)
+       perror_with_name (filename);
+
+#ifdef COFF_FORMAT
+      {
+       int aout_hdrsize;
+       int num_sections;
+
+       if (read_file_hdr (execchan, &file_hdr) < 0)
+         error ("\"%s\": not in executable format.", execfile);
+
+       aout_hdrsize = file_hdr.f_opthdr;
+       num_sections = file_hdr.f_nscns;
+
+       if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
+         error ("\"%s\": can't read optional aouthdr", execfile);
+
+       if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
+                             aout_hdrsize) < 0)
+         error ("\"%s\": can't read text section header", execfile);
+
+       if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
+                             aout_hdrsize) < 0)
+         error ("\"%s\": can't read data section header", execfile);
+
+       text_start = exec_aouthdr.text_start;
+       text_end = text_start + exec_aouthdr.tsize;
+       text_offset = text_hdr.s_scnptr;
+       exec_data_start = exec_aouthdr.data_start;
+       exec_data_end = exec_data_start + exec_aouthdr.dsize;
+       exec_data_offset = data_hdr.s_scnptr;
+       data_start = exec_data_start;
+       data_end += exec_data_start;
+       exec_mtime = file_hdr.f_timdat;
+      }
+#else /* not COFF_FORMAT */
+      {
+       struct stat st_exec;
+
+       val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
+
+       if (val < 0)
+         perror_with_name (filename);
+
+       text_start = N_ADDRADJ(exec_aouthdr);
+        exec_data_start = round(exec_aouthdr.a_text, NBPG*CLSIZE);
+       text_offset = N_TXTOFF (exec_aouthdr);
+       exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+       text_end = exec_aouthdr.a_text;
+        exec_data_end = exec_data_start + exec_aouthdr.a_data;
+       data_start = exec_data_start;
+       data_end = data_start + exec_aouthdr.a_data;
+       exec_data_offset = N_TXTOFF(exec_aouthdr);
+       fstat (execchan, &st_exec);
+       exec_mtime = st_exec.st_mtime;
+      }
+#endif /* not COFF_FORMAT */
+
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No exec file now.\n");
+
+  /* Tell display code (if any) about the changed file name.  */
+  if (exec_file_display_hook)
+    (*exec_file_display_hook) (filename);
+}
+
+/* rounds 'one' up to divide evenly by 'two' */
+
+int
+round(one,two)
+register int one, two;
+
+{
+    register int temp;
+    temp = (one/two)*two;
+    if (one != temp) {
+       temp += two;
+    }
+    return temp;
+}
+
+
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[sizeof (int)];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() (codestream_addr + codestream_off)
+#define codestream_peek() (codestream_cnt == 0 ? \
+                          codestream_fill(1): codestream_buf[codestream_off])
+#define codestream_get() (codestream_cnt-- == 0 ? \
+                        codestream_fill(0) : codestream_buf[codestream_off++])
+
+
+static unsigned char 
+codestream_fill (peek_flag)
+{
+  codestream_addr = codestream_next_addr;
+  codestream_next_addr += sizeof (int);
+  codestream_off = 0;
+  codestream_cnt = sizeof (int);
+  read_memory (codestream_addr,
+              (unsigned char *)codestream_buf,
+              sizeof (int));
+  
+  if (peek_flag)
+    return (codestream_peek());
+  else
+    return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+{
+  codestream_next_addr = place & -sizeof (int);
+  codestream_cnt = 0;
+  codestream_fill (1);
+  while (codestream_tell() != place)
+    codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+     unsigned char *buf;
+{
+  unsigned char *p;
+  int i;
+  p = buf;
+  for (i = 0; i < count; i++)
+    *p++ = codestream_get ();
+}
+
+/*
+ * Following macro translates i386 opcode register numbers to Symmetry
+ * register numbers.  This is used by FRAME_FIND_SAVED_REGS.
+ *
+ *           %eax  %ecx  %edx  %ebx  %esp  %ebp  %esi  %edi
+ * i386        0     1     2     3     4     5     6     7
+ * Symmetry    0     2     1     5    14    15     6     7
+ *
+ */
+#define I386_REGNO_TO_SYMMETRY(n) \
+((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
+
+/* from i386-dep.c */
+i386_frame_find_saved_regs (fip, fsrp)
+     struct frame_info *fip;
+     struct frame_saved_regs *fsrp;
+{
+  unsigned long locals;
+  unsigned char *p;
+  unsigned char op;
+  CORE_ADDR dummy_bottom;
+  CORE_ADDR adr;
+  int i;
+  
+  bzero (fsrp, sizeof *fsrp);
+  
+  /* if frame is the end of a dummy, compute where the
+   * beginning would be
+   */
+  dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
+  
+  /* check if the PC is in the stack, in a dummy frame */
+  if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) 
+    {
+      /* all regs were saved by push_call_dummy () */
+      adr = fip->frame - 4;
+      for (i = 0; i < NUM_REGS; i++) 
+       {
+         fsrp->regs[i] = adr;
+         adr -= 4;
+       }
+      return;
+    }
+  
+  locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
+  
+  if (locals >= 0) 
+    {
+      adr = fip->frame - 4 - locals;
+      for (i = 0; i < 8; i++) 
+       {
+         op = codestream_get ();
+         if (op < 0x50 || op > 0x57)
+           break;
+         fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
+         adr -= 4;
+       }
+    }
+  
+  fsrp->regs[PC_REGNUM] = fip->frame + 4;
+  fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+static long
+i386_get_frame_setup (pc)
+{
+  unsigned char op;
+  
+  codestream_seek (pc);
+  
+  i386_follow_jump ();
+  
+  op = codestream_get ();
+  
+  if (op == 0x58) /* popl %eax */
+    {
+      /*
+       * this function must start with
+       * 
+       *    popl %eax            0x58
+       *    xchgl %eax, (%esp)  0x87 0x04 0x24
+       * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
+       *
+       * (the system 5 compiler puts out the second xchg
+       * inst, and the assembler doesn't try to optimize it,
+       * so the 'sib' form gets generated)
+       * 
+       * this sequence is used to get the address of the return
+       * buffer for a function that returns a structure
+       */
+      int pos;
+      unsigned char buf[4];
+      static unsigned char proto1[3] = { 0x87,0x04,0x24 };
+      static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
+      pos = codestream_tell ();
+      codestream_read (buf, 4);
+      if (bcmp (buf, proto1, 3) == 0)
+       pos += 3;
+      else if (bcmp (buf, proto2, 4) == 0)
+       pos += 4;
+      
+      codestream_seek (pos);
+      op = codestream_get (); /* update next opcode */
+    }
+  
+  if (op == 0x55)                      /* pushl %esp */
+    {
+      if (codestream_get () != 0x8b)   /* movl %esp, %ebp (2bytes) */
+       return (-1);
+      if (codestream_get () != 0xec)
+       return (-1);
+      /*
+       * check for stack adjustment 
+       *
+       *  subl $XXX, %esp
+       *
+       * note: you can't subtract a 16 bit immediate
+       * from a 32 bit reg, so we don't have to worry
+       * about a data16 prefix 
+       */
+      op = codestream_peek ();
+      if (op == 0x83)  /* subl with 8 bit immed */
+       {
+         codestream_get ();
+         if (codestream_get () != 0xec)
+           return (-1);
+         /* subl with signed byte immediate 
+          * (though it wouldn't make sense to be negative)
+          */
+         return (codestream_get());
+       }
+      else if (op == 0x81)  /* subl with 32 bit immed */
+       {
+         int locals;
+         if (codestream_get () != 0xec)
+           return (-1);
+         /* subl with 32 bit immediate */
+         codestream_read ((unsigned char *)&locals, 4);
+         return (locals);
+       } 
+      else 
+       {
+         return (0);
+       }
+    } 
+  else if (op == 0xc8) 
+    {
+      /* enter instruction: arg is 16 unsigned immed */
+      unsigned short slocals;
+      codestream_read ((unsigned char *)&slocals, 2);
+      codestream_get (); /* flush final byte of enter instruction */
+      return (slocals);
+    }
+  return (-1);
+}
+
+/* next instruction is a jump, move to target */
+static
+i386_follow_jump ()
+{
+  int long_delta;
+  short short_delta;
+  char byte_delta;
+  int data16;
+  int pos;
+  
+  pos = codestream_tell ();
+  
+  data16 = 0;
+  if (codestream_peek () == 0x66)
+    {
+      codestream_get ();
+      data16 = 1;
+    }
+  
+  switch (codestream_get ())
+    {
+    case 0xe9:
+      /* relative jump: if data16 == 0, disp32, else disp16 */
+      if (data16)
+       {
+         codestream_read ((unsigned char *)&short_delta, 2);
+         pos += short_delta + 3; /* include size of jmp inst */
+       }
+      else
+       {
+         codestream_read ((unsigned char *)&long_delta, 4);
+         pos += long_delta + 5;
+       }
+      break;
+    case 0xeb:
+      /* relative jump, disp8 (ignore data16) */
+      codestream_read ((unsigned char *)&byte_delta, 1);
+      pos += byte_delta + 2;
+      break;
+    }
+  codestream_seek (pos + data16);
+}
+
+/* return pc of first real instruction */
+/* from i386-dep.c */
+
+i386_skip_prologue (pc)
+{
+  unsigned char op;
+  int i;
+  
+  if (i386_get_frame_setup (pc) < 0)
+    return (pc);
+  
+  /* found valid frame setup - codestream now points to 
+   * start of push instructions for saving registers
+   */
+  
+  /* skip over register saves */
+  for (i = 0; i < 8; i++)
+    {
+      op = codestream_peek ();
+      /* break if not pushl inst */
+      if (op < 0x50 || op > 0x57) 
+       break;
+      codestream_get ();
+    }
+  
+  i386_follow_jump ();
+  
+  return (codestream_tell ());
+}
+
+symmetry_extract_return_value(type, regbuf, valbuf)
+     struct type *type;
+     char *regbuf;
+     char *valbuf;
+{
+  union { 
+    double     d; 
+    int        l[2]; 
+  } xd; 
+  int i;
+  float f;
+
+  if (TYPE_CODE_FLT == TYPE_CODE(type)) { 
+    for (i = 0; i < misc_function_count; i++) {
+      if (!strcmp(misc_function_vector[i].name, "1167_flt"))
+       break;
+    }
+    if (i < misc_function_count) {
+      /* found "1167_flt" means 1167, %fp2-%fp3 */ 
+      /* float & double; 19= %fp2, 20= %fp3 */
+      /* no single precision on 1167 */
+      xd.l[1] = *((int *)&regbuf[REGISTER_BYTE(19)]);
+      xd.l[0] = *((int *)&regbuf[REGISTER_BYTE(20)]);
+      switch (TYPE_LENGTH(type)) {
+      case 4:
+       f = (float) xd.d;
+       bcopy(&f, valbuf, TYPE_LENGTH(type));
+       break;
+      case 8:
+       bcopy(&xd.d, valbuf, TYPE_LENGTH(type)); 
+       break;
+      default:
+       error("Unknown floating point size");
+       break;
+      }
+    } else { 
+      /* 387 %st(0), gcc uses this */ 
+      i387_to_double(((int *)&regbuf[REGISTER_BYTE(3)]),
+                    &xd.d); 
+      switch (TYPE_LENGTH(type)) {
+      case 4:                  /* float */
+       f = (float) xd.d;
+       bcopy(&f, valbuf, 4); 
+       break;
+      case 8:                  /* double */
+       bcopy(&xd.d, valbuf, 8);
+       break;
+      default:
+       error("Unknown floating point size");
+       break;
+      }
+    }
+  } else { 
+    bcopy (regbuf, valbuf, TYPE_LENGTH (type)); 
+  }
+}
diff --git a/gdb/symmetry-xdep.c b/gdb/symmetry-xdep.c
new file mode 100755 (executable)
index 0000000..3449678
--- /dev/null
@@ -0,0 +1,557 @@
+/* Sequent Symmetry host interface, for GDB when running under Unix.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "gdbcore.h"
+#include <fcntl.h>
+
+static long i386_get_frame_setup ();
+static i386_follow_jump ();
+
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+store_inferior_registers(regno)
+int regno;
+{
+  struct pt_regset regs;
+  int reg_tmp, i;
+  extern char registers[];
+  
+#if 0
+  /* PREPARE_TO_STORE deals with this.  */
+  if (-1 == regno)
+    {
+#endif
+      regs.pr_eax = *(int *)&registers[REGISTER_BYTE(0)];
+      regs.pr_ebx = *(int *)&registers[REGISTER_BYTE(5)];
+      regs.pr_ecx = *(int *)&registers[REGISTER_BYTE(2)];
+      regs.pr_edx = *(int *)&registers[REGISTER_BYTE(1)];
+      regs.pr_esi = *(int *)&registers[REGISTER_BYTE(6)];
+      regs.pr_edi = *(int *)&registers[REGISTER_BYTE(7)];
+      regs.pr_esp = *(int *)&registers[REGISTER_BYTE(14)];
+      regs.pr_ebp = *(int *)&registers[REGISTER_BYTE(15)];
+      regs.pr_eip = *(int *)&registers[REGISTER_BYTE(16)];
+      regs.pr_flags = *(int *)&registers[REGISTER_BYTE(17)];
+      for (i = 0; i < 31; i++) {
+       regs.pr_fpa.fpa_regs[i] =
+         *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)];
+      }
+#if 0
+    }
+  else
+    {
+      reg_tmp = *(int *)&registers[REGISTER_BYTE(regno)];
+      ptrace(XPT_RREGS, inferior_pid, &regs, 0);
+      switch (regno)
+       {
+       case 0:
+         regs.pr_eax = *(int *)&registers[REGISTER_BYTE(0)];
+         break;
+       case 5:
+         regs.pr_ebx = *(int *)&registers[REGISTER_BYTE(5)];
+         break;
+       case 2:
+         regs.pr_ecx = *(int *)&registers[REGISTER_BYTE(2)];
+         break;
+       case 1:
+         regs.pr_edx = *(int *)&registers[REGISTER_BYTE(1)];
+         break;
+       case 6:
+         regs.pr_esi = *(int *)&registers[REGISTER_BYTE(6)];
+         break;
+       case 7:
+         regs.pr_edi = *(int *)&registers[REGISTER_BYTE(7)];
+         break;
+       case 15:
+         regs.pr_ebp = *(int *)&registers[REGISTER_BYTE(15)];
+         break;
+       case 14:
+         regs.pr_esp = *(int *)&registers[REGISTER_BYTE(14)];
+         break;
+       case 16:
+         regs.pr_eip = *(int *)&registers[REGISTER_BYTE(16)];
+         break;
+       case 17:
+         regs.pr_flags = *(int *)&registers[REGISTER_BYTE(17)];
+         break;
+       }
+    }
+#endif /* 0 */
+  ptrace(XPT_WREGS, inferior_pid, &regs, 0);
+}
+
+void
+fetch_inferior_registers()
+{
+    int i;
+    struct pt_regset regs;
+    extern char registers[];
+
+    registers_fetched ();
+    
+    ptrace(XPT_RREGS, inferior_pid, &regs, 0);
+    *(int *)&registers[REGISTER_BYTE(0)] = regs.pr_eax;
+    *(int *)&registers[REGISTER_BYTE(5)] = regs.pr_ebx;
+    *(int *)&registers[REGISTER_BYTE(2)] = regs.pr_ecx;
+    *(int *)&registers[REGISTER_BYTE(1)] = regs.pr_edx;
+    *(int *)&registers[REGISTER_BYTE(6)] = regs.pr_esi;
+    *(int *)&registers[REGISTER_BYTE(7)] = regs.pr_edi;
+    *(int *)&registers[REGISTER_BYTE(15)] = regs.pr_ebp;
+    *(int *)&registers[REGISTER_BYTE(14)] = regs.pr_esp;
+    *(int *)&registers[REGISTER_BYTE(16)] = regs.pr_eip;
+    *(int *)&registers[REGISTER_BYTE(17)] = regs.pr_flags;
+    for (i = 0; i < FPA_NREGS; i++) {
+       *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)] = regs.pr_fpa.fpa_regs[i];
+    }
+    bcopy(regs.pr_fpu.fpu_stack[0], &registers[REGISTER_BYTE(3)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[1], &registers[REGISTER_BYTE(4)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[2], &registers[REGISTER_BYTE(8)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[3], &registers[REGISTER_BYTE(9)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[4], &registers[REGISTER_BYTE(10)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[5], &registers[REGISTER_BYTE(11)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[6], &registers[REGISTER_BYTE(12)], 10);
+    bcopy(regs.pr_fpu.fpu_stack[7], &registers[REGISTER_BYTE(13)], 10);
+}
+
+\f
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+#include "gdbcore.h"
+
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+       struct user u;
+       int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name (filename);
+       data_start = exec_data_start;
+
+       data_end = data_start + NBPG * (u.u_dsize - u.u_tsize);
+       stack_start = stack_end - NBPG * u.u_ssize;
+       data_offset = NBPG * UPAGES;
+       stack_offset = ctob(UPAGES + u.u_dsize - u.u_tsize);
+       reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+printf("u.u_tsize= %#x, u.u_dsize= %#x, u.u_ssize= %#x, stack_off= %#x\n",
+       u.u_tsize, u.u_dsize, u.u_ssize, stack_offset);
+
+       core_aouthdr.a_magic = 0;
+
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < NUM_REGS; regno++)
+           {
+             char buf[MAX_REGISTER_RAW_SIZE];
+
+             val = lseek (corechan, register_addr (regno, reg_offset), 0);
+             if (val < 0)
+               perror_with_name (filename);
+
+             val = myread (corechan, buf, sizeof buf);
+             if (val < 0)
+               perror_with_name (filename);
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame(create_new_frame(read_register(FP_REGNUM),
+                                        read_pc()));
+/*      set_current_frame (read_register (FP_REGNUM));*/
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
+
+/* from i386-dep.c */
+static
+print_387_control_word (control)
+unsigned short control;
+{
+  printf ("control 0x%04x: ", control);
+  printf ("compute to ");
+  switch ((control >> 8) & 3) 
+    {
+    case 0: printf ("24 bits; "); break;
+    case 1: printf ("(bad); "); break;
+    case 2: printf ("53 bits; "); break;
+    case 3: printf ("64 bits; "); break;
+    }
+  printf ("round ");
+  switch ((control >> 10) & 3) 
+    {
+    case 0: printf ("NEAREST; "); break;
+    case 1: printf ("DOWN; "); break;
+    case 2: printf ("UP; "); break;
+    case 3: printf ("CHOP; "); break;
+    }
+  if (control & 0x3f) 
+    {
+      printf ("mask:");
+      if (control & 0x0001) printf (" INVALID");
+      if (control & 0x0002) printf (" DENORM");
+      if (control & 0x0004) printf (" DIVZ");
+      if (control & 0x0008) printf (" OVERF");
+      if (control & 0x0010) printf (" UNDERF");
+      if (control & 0x0020) printf (" LOS");
+      printf (";");
+    }
+  printf ("\n");
+  if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
+                               control & 0xe080);
+}
+
+static
+print_387_status_word (status)
+     unsigned short status;
+{
+  printf ("status %#04x: ", status);
+  if (status & 0xff) {
+      printf ("exceptions:");  /* exception names match <machine/fpu.h> */
+      if (status & 0x0001) printf (" FLTINV");
+      if (status & 0x0002) printf (" FLTDEN");
+      if (status & 0x0004) printf (" FLTDIV");
+      if (status & 0x0008) printf (" FLTOVF");
+      if (status & 0x0010) printf (" FLTUND");
+      if (status & 0x0020) printf (" FLTPRE");
+      if (status & 0x0040) printf (" FLTSTK");
+      printf ("; ");
+    }
+  printf ("flags: %d%d%d%d; ",
+         (status & 0x4000) != 0,
+         (status & 0x0400) != 0,
+         (status & 0x0200) != 0,
+         (status & 0x0100) != 0);
+  
+  printf ("top %d\n", (status >> 11) & 7);
+}
+
+static
+print_fpu_status(ep)
+struct pt_regset ep;
+
+{
+    int i;
+    int bothstatus;
+    int top;
+    int fpreg;
+    unsigned char *p;
+    
+    printf("80387:");
+    if (ep.pr_fpu.fpu_ip == 0) {
+       printf(" not in use.\n");
+       return;
+    } else {
+       printf("\n");
+    }
+    if (ep.pr_fpu.fpu_status != 0) {
+       print_387_status_word (ep.pr_fpu.fpu_status);
+    }
+    print_387_control_word (ep.pr_fpu.fpu_control);
+    printf ("last exception: ");
+    printf ("opcode 0x%x; ", ep.pr_fpu.fpu_rsvd4);
+    printf ("pc 0x%x:0x%x; ", ep.pr_fpu.fpu_cs, ep.pr_fpu.fpu_ip);
+    printf ("operand 0x%x:0x%x\n", ep.pr_fpu.fpu_data_offset, ep.pr_fpu.fpu_op_sel);
+    
+    top = (ep.pr_fpu.fpu_status >> 11) & 7;
+    
+    printf ("regno  tag  msb              lsb  value\n");
+    for (fpreg = 7; fpreg >= 0; fpreg--) 
+       {
+           double val;
+           
+           printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
+           
+           switch ((ep.pr_fpu.fpu_tag >> (fpreg * 2)) & 3) 
+               {
+               case 0: printf ("valid "); break;
+               case 1: printf ("zero  "); break;
+               case 2: printf ("trap  "); break;
+               case 3: printf ("empty "); break;
+               }
+           for (i = 9; i >= 0; i--)
+               printf ("%02x", ep.pr_fpu.fpu_stack[fpreg][i]);
+           
+           i387_to_double (ep.pr_fpu.fpu_stack[fpreg], (char *)&val);
+           printf ("  %g\n", val);
+       }
+    if (ep.pr_fpu.fpu_rsvd1)
+       printf ("warning: rsvd1 is 0x%x\n", ep.pr_fpu.fpu_rsvd1);
+    if (ep.pr_fpu.fpu_rsvd2)
+       printf ("warning: rsvd2 is 0x%x\n", ep.pr_fpu.fpu_rsvd2);
+    if (ep.pr_fpu.fpu_rsvd3)
+       printf ("warning: rsvd3 is 0x%x\n", ep.pr_fpu.fpu_rsvd3);
+    if (ep.pr_fpu.fpu_rsvd5)
+       printf ("warning: rsvd5 is 0x%x\n", ep.pr_fpu.fpu_rsvd5);
+}
+
+
+print_1167_control_word(pcr)
+unsigned int pcr;
+
+{
+    int pcr_tmp;
+
+    pcr_tmp = pcr & FPA_PCR_MODE;
+    printf("\tMODE= %#x; RND= %#x ", pcr_tmp, pcr_tmp & 12);
+    switch (pcr_tmp & 12) {
+    case 0:
+       printf("RN (Nearest Value)");
+       break;
+    case 1:
+       printf("RZ (Zero)");
+       break;
+    case 2:
+       printf("RP (Positive Infinity)");
+       break;
+    case 3:
+       printf("RM (Negative Infinity)");
+       break;
+    }
+    printf("; IRND= %d ", pcr_tmp & 2);
+    if (0 == pcr_tmp & 2) {
+       printf("(same as RND)\n");
+    } else {
+       printf("(toward zero)\n");
+    }
+    pcr_tmp = pcr & FPA_PCR_EM;
+    printf("\tEM= %#x", pcr_tmp);
+    if (pcr_tmp & FPA_PCR_EM_DM) printf(" DM");
+    if (pcr_tmp & FPA_PCR_EM_UOM) printf(" UOM");
+    if (pcr_tmp & FPA_PCR_EM_PM) printf(" PM");
+    if (pcr_tmp & FPA_PCR_EM_UM) printf(" UM");
+    if (pcr_tmp & FPA_PCR_EM_OM) printf(" OM");
+    if (pcr_tmp & FPA_PCR_EM_ZM) printf(" ZM");
+    if (pcr_tmp & FPA_PCR_EM_IM) printf(" IM");
+    printf("\n");
+    pcr_tmp = FPA_PCR_CC;
+    printf("\tCC= %#x", pcr_tmp);
+    if (pcr_tmp & FPA_PCR_20MHZ) printf(" 20MHZ");
+    if (pcr_tmp & FPA_PCR_CC_Z) printf(" Z");
+    if (pcr_tmp & FPA_PCR_CC_C2) printf(" C2");
+    if (pcr_tmp & FPA_PCR_CC_C1) printf(" C1");
+    switch (pcr_tmp) {
+    case FPA_PCR_CC_Z:
+       printf(" (Equal)");
+       break;
+    case FPA_PCR_CC_C1:
+       printf(" (Less than)");
+       break;
+    case 0:
+       printf(" (Greater than)");
+       break;
+    case FPA_PCR_CC_Z | FPA_PCR_CC_C1 | FPA_PCR_CC_C2:
+       printf(" (Unordered)");
+       break;
+    default:
+       printf(" (Undefined)");
+       break;
+    }
+    printf("\n");
+    pcr_tmp = pcr & FPA_PCR_AE;
+    printf("\tAE= %#x", pcr_tmp);
+    if (pcr_tmp & FPA_PCR_AE_DE) printf(" DE");
+    if (pcr_tmp & FPA_PCR_AE_UOE) printf(" UOE");
+    if (pcr_tmp & FPA_PCR_AE_PE) printf(" PE");
+    if (pcr_tmp & FPA_PCR_AE_UE) printf(" UE");
+    if (pcr_tmp & FPA_PCR_AE_OE) printf(" OE");
+    if (pcr_tmp & FPA_PCR_AE_ZE) printf(" ZE");
+    if (pcr_tmp & FPA_PCR_AE_EE) printf(" EE");
+    if (pcr_tmp & FPA_PCR_AE_IE) printf(" IE");
+    printf("\n");
+}
+
+print_1167_regs(regs)
+long regs[FPA_NREGS];
+
+{
+    int i;
+
+    union {
+       double  d;
+       long    l[2];
+    } xd;
+    union {
+       float   f;
+       long    l;
+    } xf;
+
+
+    for (i = 0; i < FPA_NREGS; i++) {
+       xf.l = regs[i];
+       printf("%%fp%d: raw= %#x, single= %f", i+1, regs[i], xf.f);
+       if (!(i & 1)) {
+           printf("\n");
+       } else {
+           xd.l[1] = regs[i];
+           xd.l[0] = regs[i+1];
+           printf(", double= %f\n", xd.d);
+       }
+    }
+}
+
+print_fpa_status(ep)
+struct pt_regset ep;
+
+{
+
+    printf("WTL 1167:");
+    if (ep.pr_fpa.fpa_pcr !=0) {
+       printf("\n");
+       print_1167_control_word(ep.pr_fpa.fpa_pcr);
+       print_1167_regs(ep.pr_fpa.fpa_regs);
+    } else {
+       printf(" not in use.\n");
+    }
+}
+
+i386_float_info ()
+
+{
+    char ubuf[UPAGES*NBPG];
+    struct pt_regset regset;
+    extern int corechan;
+    
+    if (have_inferior_p()) {
+       call_ptrace(XPT_RREGS, inferior_pid, &regset, 0);
+    } else {
+       if (lseek (corechan, 0, 0) < 0) {
+           perror ("seek on core file");
+       }
+       if (myread (corechan, ubuf, UPAGES*NBPG) < 0) {
+           perror ("read on core file");
+       }
+       /* only interested in the floating point registers */
+       regset.pr_fpu = ((struct user *) ubuf)->u_fpusave;
+       regset.pr_fpa = ((struct user *) ubuf)->u_fpasave;
+    }
+    print_fpu_status(regset);
+    print_fpa_status(regset);
+}
+
+i387_to_double (from, to)
+     char *from;
+     char *to;
+{
+  long *lp;
+  /* push extended mode on 387 stack, then pop in double mode
+   *
+   * first, set exception masks so no error is generated -
+   * number will be rounded to inf or 0, if necessary 
+   */
+  asm ("pushl %eax");          /* grab a stack slot */
+  asm ("fstcw (%esp)");                /* get 387 control word */
+  asm ("movl (%esp),%eax");    /* save old value */
+  asm ("orl $0x3f,%eax");              /* mask all exceptions */
+  asm ("pushl %eax");
+  asm ("fldcw (%esp)");                /* load new value into 387 */
+  
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldt (%eax)");         /* push extended number on 387 stack */
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpl (%eax)");                /* pop double */
+  asm ("fwait");
+  
+  asm ("popl %eax");           /* flush modified control word */
+  asm ("fnclex");                      /* clear exceptions */
+  asm ("fldcw (%esp)");                /* restore original control word */
+  asm ("popl %eax");           /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+     char *from;
+     char *to;
+{
+  /* push double mode on 387 stack, then pop in extended mode
+   * no errors are possible because every 64-bit pattern
+   * can be converted to an extended
+   */
+  asm ("movl 8(%ebp),%eax");
+  asm ("fldl (%eax)");
+  asm ("fwait");
+  asm ("movl 12(%ebp),%eax");
+  asm ("fstpt (%eax)");
+  asm ("fwait");
+}
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
new file mode 100644 (file)
index 0000000..2aead6e
--- /dev/null
@@ -0,0 +1,442 @@
+/* Do various things to symbol tables (other than lookup)), for GDB.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "command.h"
+
+#include <stdio.h>
+#include <obstack.h>
+
+static void free_symtab ();
+
+\f
+/* Free all the symtabs that are currently installed,
+   and all storage associated with them.
+   Leaves us in a consistent state with no symtabs installed.  */
+
+void
+free_all_symtabs ()
+{
+  register struct symtab *s, *snext;
+
+  /* All values will be invalid because their types will be!  */
+
+  clear_value_history ();
+  clear_displays ();
+  clear_internalvars ();
+#if defined (CLEAR_SOLIB)
+  CLEAR_SOLIB ();
+#endif
+  set_default_breakpoint (0, 0, 0, 0);
+
+  current_source_symtab = 0;
+
+  for (s = symtab_list; s; s = snext)
+    {
+      snext = s->next;
+      free_symtab (s);
+    }
+  symtab_list = 0;
+  obstack_free (symbol_obstack, 0);
+  obstack_init (symbol_obstack);
+
+  if (misc_function_vector)
+    free (misc_function_vector);
+  misc_function_count = 0;
+  misc_function_vector = 0;
+  clear_pc_function_cache();
+}
+
+/* Free a struct block <- B and all the symbols defined in that block.  */
+
+static void
+free_symtab_block (b)
+     struct block *b;
+{
+  register int i, n;
+  n = BLOCK_NSYMS (b);
+  for (i = 0; i < n; i++)
+    {
+      free (SYMBOL_NAME (BLOCK_SYM (b, i)));
+      free (BLOCK_SYM (b, i));
+    }
+  free (b);
+}
+
+/* Free all the storage associated with the struct symtab <- S.
+   Note that some symtabs have contents malloc'ed structure by structure,
+   while some have contents that all live inside one big block of memory,
+   and some share the contents of another symbol table and so you should
+   not free the contents on their behalf (except sometimes the linetable,
+   which maybe per symtab even when the rest is not).
+   It is s->free_code that says which alternative to use.  */
+
+static void
+free_symtab (s)
+     register struct symtab *s;
+{
+  register int i, n;
+  register struct blockvector *bv;
+  register struct typevector *tv;
+
+  switch (s->free_code)
+    {
+    case free_nothing:
+      /* All the contents are part of a big block of memory
+        and some other symtab is in charge of freeing that block.
+        Therefore, do nothing.  */
+      break;
+
+    case free_contents:
+      /* Here all the contents were malloc'ed structure by structure
+        and must be freed that way.  */
+      /* First free the blocks (and their symbols.  */
+      bv = BLOCKVECTOR (s);
+      n = BLOCKVECTOR_NBLOCKS (bv);
+      for (i = 0; i < n; i++)
+       free_symtab_block (BLOCKVECTOR_BLOCK (bv, i));
+      /* Free the blockvector itself.  */
+      free (bv);
+      /* Free the type vector.  */
+      tv = TYPEVECTOR (s);
+      free (tv);
+      /* Also free the linetable.  */
+      
+    case free_linetable:
+      /* Everything will be freed either by our `free_ptr'
+        or by some other symbatb, except for our linetable.
+        Free that now.  */
+      free (LINETABLE (s));
+      break;
+    }
+
+  /* If there is a single block of memory to free, free it.  */
+  if (s->free_ptr)
+    free (s->free_ptr);
+
+  /* Free source-related stuff */
+  if (s->line_charpos)
+    free (s->line_charpos);
+  if (s->fullname)
+    free (s->fullname);
+  free (s);
+}
+
+/* If a symtab for filename NAME is found, free it along
+   with any dependent breakpoints, displays, etc.
+   Used when loading new versions of object modules with the "add-file"
+   command.
+   
+   FIXME.  I think this is not the right way to do this.  It needs further
+   investigation, though.  -- gnu@cygnus  */
+
+void
+free_named_symtab (name)
+     char *name;
+{
+  register struct symtab *s;
+  register struct symtab *prev;
+  struct blockvector *bv;
+
+#if 0  /* FIXME */
+  /* Look for a symtab with the specified name.
+     We can't use lookup_symtab () for this, since it 
+     might generate a recursive call to psymtab_to_symtab ().  */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      if (!strcmp (name, s->filename))
+       break;
+      prev = s;
+    }
+
+  if (s)
+    {
+      if (s == symtab_list)
+       symtab_list = s->next;
+      else
+       prev->next = s->next;
+
+      /* For now, delete all breakpoints, displays, etc., whether or
+        not they depend on the symtab being freed.  This should be
+        changed so that only those data structures affected are deleted.  */
+
+      /* But don't delete anything if the symtab is empty.
+        This test is necessary due to a bug in "dbxread.c" that
+        causes empty symtabs to be created for N_SO symbols that
+        contain the pathname of the object file.  (This problem
+        has been fixed in GDB 3.9x).  */
+
+      bv = BLOCKLIST (s);
+      if (BLOCKLIST_NBLOCKS (bv) > 2
+         || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, 0))
+         || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, 1)))
+       {
+         /* Took the following line out because GDB ends up printing it
+            many times when a given module is loaded, because each module
+            contains many symtabs.  */
+         /*
+         printf ("Clearing breakpoints and resetting debugger state.\n");
+         */
+
+         clear_value_history ();
+         clear_displays ();
+         clear_internalvars ();
+         clear_breakpoints ();
+         set_default_breakpoint (0, 0, 0, 0);
+         current_source_symtab = 0;
+       }
+
+      free_symtab (s);
+    }
+  else
+    /* It is still possible that some breakpoints will be affected
+       even though no symtab was found, since the file might have
+       been compiled without debugging, and hence not be associated
+       with a symtab.  In order to handle this correctly, we would need
+       to keep a list of text address ranges for undebuggable files.
+       For now, we do nothing, since this is a fairly obscure case.  */
+    ;
+#endif  /* FIXME */
+}
+
+\f
+static int block_depth ();
+static void print_symbol ();
+
+void
+print_symtabs (filename)
+     char *filename;
+{
+  FILE *outfile;
+  register struct symtab *s;
+  register int i, j;
+  int len, blen;
+  register struct linetable *l;
+  struct blockvector *bv;
+  register struct block *b;
+  int depth;
+  struct cleanup *cleanups;
+  extern int fclose();
+
+  if (filename == 0)
+    error_no_arg ("file to write symbol data in");
+
+  filename = tilde_expand (filename);
+  make_cleanup (free, filename);
+  
+  outfile = fopen (filename, "w");
+  if (outfile == 0)
+    perror_with_name (filename);
+
+  cleanups = make_cleanup (fclose, outfile);
+  immediate_quit++;
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      /* First print the line table.  */
+      fprintf (outfile, "Symtab for file %s\n\n", s->filename);
+      fprintf (outfile, "Line table:\n\n");
+      l = LINETABLE (s);
+      len = l->nitems;
+      for (i = 0; i < len; i++)
+       fprintf (outfile, " line %d at %x\n", l->item[i].line,
+                l->item[i].pc);
+      /* Now print the block info.  */
+      fprintf (outfile, "\nBlockvector:\n\n");
+      bv = BLOCKVECTOR (s);
+      len = BLOCKVECTOR_NBLOCKS (bv);
+      for (i = 0; i < len; i++)
+       {
+         b = BLOCKVECTOR_BLOCK (bv, i);
+         depth = block_depth (b) * 2;
+         print_spaces (depth, outfile);
+         fprintf (outfile, "block #%03d (object 0x%x) ", i, b);
+         fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b));
+         if (BLOCK_SUPERBLOCK (b))
+           fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b));
+         if (BLOCK_FUNCTION (b))
+           fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
+         fputc ('\n', outfile);
+         blen = BLOCK_NSYMS (b);
+         for (j = 0; j < blen; j++)
+           {
+             print_symbol (BLOCK_SYM (b, j), depth + 1, outfile);
+           }
+       }
+
+      fprintf (outfile, "\n\n");
+    }
+
+  immediate_quit--;
+  do_cleanups (cleanups);
+}
+
+static void
+print_symbol (symbol, depth, outfile)
+     struct symbol *symbol;
+     int depth;
+     FILE *outfile;
+{
+  print_spaces (depth, outfile);
+  if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
+    {
+      fprintf (outfile, "label %s at 0x%x\n", SYMBOL_NAME (symbol),
+              SYMBOL_VALUE_ADDRESS (symbol));
+      return;
+    }
+  if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
+    {
+      if (TYPE_NAME (SYMBOL_TYPE (symbol)))
+       {
+         type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+       }
+      else
+       {
+         fprintf (outfile, "%s %s = ",
+              (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
+               ? "enum"
+               : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
+                  ? "struct" : "union")),
+              SYMBOL_NAME (symbol));
+         type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+       }
+      fprintf (outfile, ";\n");
+    }
+  else
+    {
+      if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
+       fprintf (outfile, "typedef ");
+      if (SYMBOL_TYPE (symbol))
+       {
+         type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol),
+                       outfile, 1, depth);
+         fprintf (outfile, "; ");
+       }
+      else
+       fprintf (outfile, "%s ", SYMBOL_NAME (symbol));
+
+      switch (SYMBOL_CLASS (symbol))
+       {
+       case LOC_CONST:
+         fprintf (outfile, "const %ld (0x%lx),",
+                  SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_CONST_BYTES:
+         fprintf (outfile, "const %u hex bytes:",
+                  TYPE_LENGTH (SYMBOL_TYPE (symbol)));
+         {
+           unsigned i;
+           for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
+             fprintf (outfile, " %2x",
+                        (unsigned)SYMBOL_VALUE_BYTES (symbol) [i]);
+           fprintf (outfile, ",");
+         }
+         break;
+
+       case LOC_STATIC:
+         fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE_ADDRESS (symbol));
+         break;
+
+       case LOC_REGISTER:
+         fprintf (outfile, "register %ld,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_ARG:
+         fprintf (outfile, "arg at 0x%lx,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_LOCAL_ARG:
+         fprintf (outfile, "arg at offset 0x%x from fp,",
+                  SYMBOL_VALUE (symbol));
+
+       case LOC_REF_ARG:
+         fprintf (outfile, "reference arg at 0x%lx,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_REGPARM:
+         fprintf (outfile, "parameter register %ld,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_LOCAL:
+         fprintf (outfile, "local at 0x%lx,", SYMBOL_VALUE (symbol));
+         break;
+
+       case LOC_TYPEDEF:
+         break;
+
+       case LOC_LABEL:
+         fprintf (outfile, "label at 0x%lx", SYMBOL_VALUE_ADDRESS (symbol));
+         break;
+
+       case LOC_BLOCK:
+         fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
+                  SYMBOL_BLOCK_VALUE (symbol),
+                  BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
+         break;
+
+       case LOC_EXTERNAL:
+         fprintf (outfile, "external at 0x%x", SYMBOL_VALUE_ADDRESS (symbol));
+         break;
+
+        default:
+         fprintf (outfile, "botched symbol class %x", SYMBOL_CLASS (symbol));
+         break;
+       }
+    }
+  fprintf (outfile, "\n");
+}
+
+/* Return the nexting depth of a block within other blocks in its symtab.  */
+
+static int
+block_depth (block)
+     struct block *block;
+{
+  register int i = 0;
+  while (block = BLOCK_SUPERBLOCK (block)) i++;
+  return i;
+}
+\f
+/*
+ * Free all partial_symtab storage.
+ */
+void
+free_all_psymtabs()
+{
+  obstack_free (psymbol_obstack, 0);
+  obstack_init (psymbol_obstack);
+  partial_symtab_list = (struct partial_symtab *) 0;
+}
+\f
+void
+_initialize_symmisc ()
+{
+  symtab_list = (struct symtab *) 0;
+  partial_symtab_list = (struct partial_symtab *) 0;
+  
+  add_com ("printsyms", class_obscure, print_symtabs,
+          "Print dump of current symbol definitions to file OUTFILE.");
+}
+
diff --git a/gdb/symtab.c b/gdb/symtab.c
new file mode 100644 (file)
index 0000000..09f3282
--- /dev/null
@@ -0,0 +1,2622 @@
+/* Symbol table lookup for the GNU debugger, GDB.
+   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "symtab.h"
+#include "param.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "target.h"
+#include "value.h"
+#include "symfile.h"
+#include "gdbcmd.h"
+
+#include <obstack.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+
+extern int close ();
+extern void qsort ();
+extern char *getenv ();
+
+extern char *cplus_demangle ();
+extern struct value *value_of_this ();
+extern void break_command ();
+extern void select_source_symtab ();
+
+/* Functions this file defines */
+static int find_line_common ();
+struct partial_symtab *lookup_partial_symtab ();
+static struct partial_symbol *lookup_partial_symbol ();
+
+/* These variables point to the objects
+   representing the predefined C data types.  */
+
+struct type *builtin_type_void;
+struct type *builtin_type_char;
+struct type *builtin_type_short;
+struct type *builtin_type_int;
+struct type *builtin_type_long;
+#ifdef LONG_LONG
+struct type *builtin_type_long_long;
+#endif
+struct type *builtin_type_unsigned_char;
+struct type *builtin_type_unsigned_short;
+struct type *builtin_type_unsigned_int;
+struct type *builtin_type_unsigned_long;
+#ifdef LONG_LONG
+struct type *builtin_type_unsigned_long_long;
+#endif
+struct type *builtin_type_float;
+struct type *builtin_type_double;
+struct type *builtin_type_error;
+
+/* Block in which the most recently searched-for symbol was found.
+   Might be better to make this a parameter to lookup_symbol and 
+   value_of_this. */
+struct block *block_found;
+
+char no_symtab_msg[] = "No symbol table is loaded.  Use the \"file\" command.";
+
+/* Check for a symtab of a specific name; first in symtabs, then in
+   psymtabs.  *If* there is no '/' in the name, a match after a '/'
+   in the symtab filename will also work.  */
+
+static struct symtab *
+lookup_symtab_1 (name)
+     char *name;
+{
+  register struct symtab *s;
+  register struct partial_symtab *ps;
+  register char *slash = strchr (name, '/');
+  register int len = strlen (name);
+
+  for (s = symtab_list; s; s = s->next)
+    if (!strcmp (name, s->filename))
+      return s;
+
+  for (ps = partial_symtab_list; ps; ps = ps->next)
+    if (!strcmp (name, ps->filename))
+      {
+       if (ps->readin)
+         fatal ("Internal: readin pst found when no symtab found.");
+       return PSYMTAB_TO_SYMTAB (ps);
+      }
+
+  if (!slash)
+    {
+      for (s = symtab_list; s; s = s->next)
+       {
+         int l = strlen (s->filename);
+
+         if (s->filename[l - len -1] == '/'
+             && !strcmp (s->filename + l - len, name))
+           return s;
+       }
+
+      for (ps = partial_symtab_list; ps; ps = ps->next)
+       {
+         int l = strlen (ps->filename);
+
+         if (ps->filename[l - len - 1] == '/'
+             && !strcmp (ps->filename + l - len, name))
+           {
+             if (ps->readin)
+               fatal ("Internal: readin pst found when no symtab found.");
+             return PSYMTAB_TO_SYMTAB (ps);
+           }
+       }
+    }
+  return 0;
+}
+
+/* Lookup the symbol table of a source file named NAME.  Try a couple
+   of variations if the first lookup doesn't work.  */
+
+struct symtab *
+lookup_symtab (name)
+     char *name;
+{
+  register struct symtab *s;
+  register char *copy;
+
+  s = lookup_symtab_1 (name);
+  if (s) return s;
+
+  /* If name not found as specified, see if adding ".c" helps.  */
+
+  copy = (char *) alloca (strlen (name) + 3);
+  strcpy (copy, name);
+  strcat (copy, ".c");
+  s = lookup_symtab_1 (copy);
+  if (s) return s;
+
+  /* We didn't find anything; die.  */
+  return 0;
+}
+
+/* Lookup the partial symbol table of a source file named NAME.  This
+   only returns true on an exact match (ie. this semantics are
+   different from lookup_symtab.  */
+
+struct partial_symtab *
+lookup_partial_symtab (name)
+char *name;
+{
+  register struct partial_symtab *s;
+  
+  for (s = partial_symtab_list; s; s = s->next)
+    if (!strcmp (name, s->filename))
+      return s;
+  
+  return 0;
+}
+\f
+/* Return a typename for a struct/union/enum type
+   without the tag qualifier.  If the type has a NULL name,
+   NULL is returned.  */
+char *
+type_name_no_tag (type)
+     register struct type *type;
+{
+  register char *name = TYPE_NAME (type);
+  char *strchr ();
+  if (name == 0)
+    return 0;
+
+#if 0
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_STRUCT:
+      return name + 7;
+    case TYPE_CODE_UNION:
+      return name + 6;
+    case TYPE_CODE_ENUM:
+      return name + 5;
+    }
+#endif
+
+  name = strchr (name, ' ');
+  if (name)
+    return name + 1;
+
+  return TYPE_NAME (type);
+}
+
+/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
+
+   If this is a stubbed struct (i.e. declared as struct foo *), see if
+   we can find a full definition in some other file. If so, copy this
+   definition, so we can use it in future.  If not, set a flag so we 
+   don't waste too much time in future.
+
+   This used to be coded as a macro, but I don't think it is called 
+   often enough to merit such treatment.
+*/
+
+struct complaint stub_noname_complaint =
+  {"stub type has NULL name", 0, 0};
+
+void 
+check_stub_type(type)
+     struct type *type;
+{
+  if (TYPE_FLAGS(type) & TYPE_FLAG_STUB)
+    {
+      char* name= type_name_no_tag (type);
+      struct symbol *sym;
+      if (name == 0)
+       {
+         complain (&stub_noname_complaint, 0, 0);
+         return;
+       }
+      if (sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, 
+                              (struct symtab **)NULL) )
+       bcopy (SYMBOL_TYPE(sym), type, sizeof (struct type));
+    }
+}
+
+/* Demangle a GDB method stub type.  */
+char *
+gdb_mangle_typename (type)
+     struct type *type;
+{
+  static struct type *last_type;
+  static char *mangled_typename;
+
+  if (type != last_type)
+    {
+      /* Need a new type prefix.  */
+      char *strchr ();
+      char *newname = type_name_no_tag (type);
+      char buf[20];
+      int len;
+
+      if (mangled_typename)
+       free (mangled_typename);
+
+      len = strlen (newname);
+      sprintf (buf, "__%d", len);
+      mangled_typename = (char *)xmalloc (strlen (buf) + len + 1);
+      strcpy (mangled_typename, buf);
+      strcat (mangled_typename, newname);
+      /* Now we have built "__#newname".  */
+    }
+  return mangled_typename;
+}
+
+/* Lookup a primitive type named NAME. 
+   Return zero if NAME is not a primitive type.*/
+
+struct type *
+lookup_primitive_typename (name)
+     char *name;
+{
+  if (!strcmp (name, "int"))
+    return builtin_type_int;
+  if (!strcmp (name, "long"))
+    return builtin_type_long;
+  if (!strcmp (name, "short"))
+    return builtin_type_short;
+  if (!strcmp (name, "char"))
+    return builtin_type_char;
+  if (!strcmp (name, "float"))
+    return builtin_type_float;
+  if (!strcmp (name, "double"))
+    return builtin_type_double;
+  if (!strcmp (name, "void"))
+    return builtin_type_void;
+  return 0;
+}
+
+/* Lookup a typedef or primitive type named NAME,
+   visible in lexical block BLOCK.
+   If NOERR is nonzero, return zero if NAME is not suitably defined.  */
+
+struct type *
+lookup_typename (name, block, noerr)
+     char *name;
+     struct block *block;
+     int noerr;
+{
+  register struct symbol *sym =
+    lookup_symbol (name, block, VAR_NAMESPACE, 0, (struct symtab **)NULL);
+  if (sym == 0 || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+    {
+      struct type *tmp;
+      tmp = lookup_primitive_typename (name);
+      if (!tmp && noerr)
+       return 0;
+      error ("No type named %s.", name);
+    }
+  return SYMBOL_TYPE (sym);
+}
+
+struct type *
+lookup_unsigned_typename (name)
+     char *name;
+{
+  if (!strcmp (name, "int"))
+    return builtin_type_unsigned_int;
+  if (!strcmp (name, "long"))
+    return builtin_type_unsigned_long;
+  if (!strcmp (name, "short"))
+    return builtin_type_unsigned_short;
+  if (!strcmp (name, "char"))
+    return builtin_type_unsigned_char;
+  error ("No type named unsigned %s.", name);
+  return (struct type *)-1;  /* for lint */
+}
+
+/* Lookup a structure type named "struct NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_struct (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym 
+    = lookup_symbol (name, block, STRUCT_NAMESPACE, 0, (struct symtab **)NULL);
+
+  if (sym == 0)
+    error ("No struct type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
+    error ("This context has class, union or enum %s, not a struct.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* Lookup a union type named "union NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_union (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym 
+    = lookup_symbol (name, block, STRUCT_NAMESPACE, 0, (struct symtab **)NULL);
+
+  if (sym == 0)
+    error ("No union type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
+    error ("This context has class, struct or enum %s, not a union.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* Lookup an enum type named "enum NAME",
+   visible in lexical block BLOCK.  */
+
+struct type *
+lookup_enum (name, block)
+     char *name;
+     struct block *block;
+{
+  register struct symbol *sym 
+    = lookup_symbol (name, block, STRUCT_NAMESPACE, 0, (struct symtab **)NULL);
+  if (sym == 0)
+    error ("No enum type named %s.", name);
+  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
+    error ("This context has class, struct or union %s, not an enum.", name);
+  return SYMBOL_TYPE (sym);
+}
+
+/* Given a type TYPE, lookup the type of the component of type named
+   NAME.  */
+
+struct type *
+lookup_struct_elt_type (type, name)
+     struct type *type;
+     char *name;
+{
+  int i;
+
+  if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+      && TYPE_CODE (type) != TYPE_CODE_UNION)
+    {
+      target_terminal_ours ();
+      fflush (stdout);
+      fprintf (stderr, "Type ");
+      type_print (type, "", stderr, -1);
+      error (" is not a structure or union type.");
+    }
+
+  for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+    if (!strcmp (TYPE_FIELD_NAME (type, i), name))
+      return TYPE_FIELD_TYPE (type, i);
+
+  target_terminal_ours ();
+  fflush (stdout);
+  fprintf (stderr, "Type ");
+  type_print (type, "", stderr, -1);
+  fprintf (stderr, " has no component named ");
+  fputs_filtered (name, stderr);
+  error (".");
+  return (struct type *)-1;    /* For lint */
+}
+
+/* Given a type TYPE, return a type of pointers to that type.
+   May need to construct such a type if this is the first use.
+
+   C++: use TYPE_MAIN_VARIANT and TYPE_CHAIN to keep pointer
+   to member types under control.  */
+
+struct type *
+lookup_pointer_type (type)
+     struct type *type;
+{
+  register struct type *ptype = TYPE_POINTER_TYPE (type);
+  if (ptype) return TYPE_MAIN_VARIANT (ptype);
+
+  /* This is the first time anyone wanted a pointer to a TYPE.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    ptype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    ptype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (ptype, sizeof (struct type));
+  TYPE_MAIN_VARIANT (ptype) = ptype;
+  TYPE_TARGET_TYPE (ptype) = type;
+  TYPE_POINTER_TYPE (type) = ptype;
+  /* New type is permanent if type pointed to is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+  /* We assume the machine has only one representation for pointers!  */
+  TYPE_LENGTH (ptype) = sizeof (char *);
+  TYPE_CODE (ptype) = TYPE_CODE_PTR;
+  return ptype;
+}
+
+struct type *
+lookup_reference_type (type)
+     struct type *type;
+{
+  register struct type *rtype = TYPE_REFERENCE_TYPE (type);
+  if (rtype) return TYPE_MAIN_VARIANT (rtype);
+
+  /* This is the first time anyone wanted a pointer to a TYPE.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    rtype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    rtype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (rtype, sizeof (struct type));
+  TYPE_MAIN_VARIANT (rtype) = rtype;
+  TYPE_TARGET_TYPE (rtype) = type;
+  TYPE_REFERENCE_TYPE (type) = rtype;
+  /* New type is permanent if type pointed to is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (rtype) |= TYPE_FLAG_PERM;
+  /* We assume the machine has only one representation for pointers!  */
+  TYPE_LENGTH (rtype) = sizeof (char *);
+  TYPE_CODE (rtype) = TYPE_CODE_REF;
+  return rtype;
+}
+
+
+/* Implement direct support for MEMBER_TYPE in GNU C++.
+   May need to construct such a type if this is the first use.
+   The TYPE is the type of the member.  The DOMAIN is the type
+   of the aggregate that the member belongs to.  */
+
+struct type *
+lookup_member_type (type, domain)
+     struct type *type, *domain;
+{
+  register struct type *mtype = TYPE_MAIN_VARIANT (type);
+  struct type *main_type;
+
+  main_type = mtype;
+  while (mtype)
+    {
+      if (TYPE_DOMAIN_TYPE (mtype) == domain)
+       return mtype;
+      mtype = TYPE_NEXT_VARIANT (mtype);
+    }
+
+  /* This is the first time anyone wanted this member type.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    mtype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    mtype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (mtype, sizeof (struct type));
+  if (main_type == 0)
+    main_type = mtype;
+  else
+    {
+      TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
+      TYPE_NEXT_VARIANT (main_type) = mtype;
+    }
+  TYPE_MAIN_VARIANT (mtype) = main_type;
+  TYPE_TARGET_TYPE (mtype) = type;
+  TYPE_DOMAIN_TYPE (mtype) = domain;
+  /* New type is permanent if type pointed to is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
+
+  /* In practice, this is never used.  */
+  TYPE_LENGTH (mtype) = 1;
+  TYPE_CODE (mtype) = TYPE_CODE_MEMBER;
+
+#if 0
+  /* Now splice in the new member pointer type.  */
+  if (main_type)
+    {
+      /* This type was not "smashed".  */
+      TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
+      TYPE_CHAIN (main_type) = mtype;
+    }
+#endif
+
+  return mtype;
+}
+
+struct type *
+lookup_method_type (type, domain, args)
+     struct type *type, *domain, **args;
+{
+  register struct type *mtype = TYPE_MAIN_VARIANT (type);
+  struct type *main_type;
+
+  main_type = mtype;
+  while (mtype)
+    {
+      if (TYPE_DOMAIN_TYPE (mtype) == domain)
+       {
+         struct type **t1 = args;
+         struct type **t2 = TYPE_ARG_TYPES (mtype);
+         if (t2)
+           {
+             int i;
+             for (i = 0; t1[i] != 0 && t1[i]->code != TYPE_CODE_VOID; i++)
+               if (t1[i] != t2[i])
+                 break;
+             if (t1[i] == t2[i])
+               return mtype;
+           }
+       }
+      mtype = TYPE_NEXT_VARIANT (mtype);
+    }
+
+  /* This is the first time anyone wanted this member type.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    mtype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    mtype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (mtype, sizeof (struct type));
+  if (main_type == 0)
+    main_type = mtype;
+  else
+    {
+      TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
+      TYPE_NEXT_VARIANT (main_type) = mtype;
+    }
+  TYPE_MAIN_VARIANT (mtype) = main_type;
+  TYPE_TARGET_TYPE (mtype) = type;
+  TYPE_DOMAIN_TYPE (mtype) = domain;
+  TYPE_ARG_TYPES (mtype) = args;
+  /* New type is permanent if type pointed to is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
+
+  /* In practice, this is never used.  */
+  TYPE_LENGTH (mtype) = 1;
+  TYPE_CODE (mtype) = TYPE_CODE_METHOD;
+
+#if 0
+  /* Now splice in the new member pointer type.  */
+  if (main_type)
+    {
+      /* This type was not "smashed".  */
+      TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
+      TYPE_CHAIN (main_type) = mtype;
+    }
+#endif
+
+  return mtype;
+}
+
+#if 0
+/* Given a type TYPE, return a type which has offset OFFSET,
+   via_virtual VIA_VIRTUAL, and via_public VIA_PUBLIC.
+   May need to construct such a type if none exists.  */
+struct type *
+lookup_basetype_type (type, offset, via_virtual, via_public)
+     struct type *type;
+     int offset;
+     int via_virtual, via_public;
+{
+  register struct type *btype = TYPE_MAIN_VARIANT (type);
+  struct type *main_type;
+
+  if (offset != 0)
+    {
+      printf ("Internal error: type offset non-zero in lookup_basetype_type");
+      offset = 0;
+    }
+
+  main_type = btype;
+  while (btype)
+    {
+      if (/* TYPE_OFFSET (btype) == offset
+         && */ TYPE_VIA_PUBLIC (btype) == via_public
+         && TYPE_VIA_VIRTUAL (btype) == via_virtual)
+       return btype;
+      btype = TYPE_NEXT_VARIANT (btype);
+    }
+
+  /* This is the first time anyone wanted this member type.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    btype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    btype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  if (main_type == 0)
+    {
+      main_type = btype;
+      bzero (btype, sizeof (struct type));
+      TYPE_MAIN_VARIANT (btype) = main_type;
+    }
+  else
+    {
+      bcopy (main_type, btype, sizeof (struct type));
+      TYPE_NEXT_VARIANT (main_type) = btype;
+    }
+/* TYPE_OFFSET (btype) = offset; */
+  if (via_public)
+    TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_PUBLIC;
+  if (via_virtual)
+    TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_VIRTUAL;
+  /* New type is permanent if type pointed to is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (btype) |= TYPE_FLAG_PERM;
+
+  /* In practice, this is never used.  */
+  TYPE_LENGTH (btype) = 1;
+  TYPE_CODE (btype) = TYPE_CODE_STRUCT;
+
+  return btype;
+}
+#endif
+
+/* Given a type TYPE, return a type of functions that return that type.
+   May need to construct such a type if this is the first use.  */
+
+struct type *
+lookup_function_type (type)
+     struct type *type;
+{
+  register struct type *ptype = TYPE_FUNCTION_TYPE (type);
+  if (ptype) return ptype;
+
+  /* This is the first time anyone wanted a function returning a TYPE.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    ptype  = (struct type *) xmalloc (sizeof (struct type));
+  else
+    ptype  = (struct type *) obstack_alloc (symbol_obstack,
+                                           sizeof (struct type));
+
+  bzero (ptype, sizeof (struct type));
+  TYPE_TARGET_TYPE (ptype) = type;
+  TYPE_FUNCTION_TYPE (type) = ptype;
+  /* New type is permanent if type returned is permanent.  */
+  if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+    TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+  TYPE_LENGTH (ptype) = 1;
+  TYPE_CODE (ptype) = TYPE_CODE_FUNC;
+  TYPE_NFIELDS (ptype) = 0;
+  return ptype;
+}
+\f
+/* Create an array type.  Elements will be of type TYPE, and there will
+   be NUM of them.
+
+   Eventually this should be extended to take two more arguments which
+   specify the bounds of the array and the type of the index.
+   It should also be changed to be a "lookup" function, with the
+   appropriate data structures added to the type field.
+   Then read array type should call here.  */
+
+struct type *
+create_array_type (element_type, number)
+     struct type *element_type;
+     int number;
+{
+  struct type *result_type = (struct type *)
+    obstack_alloc (symbol_obstack, sizeof (struct type));
+
+  bzero (result_type, sizeof (struct type));
+
+  TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
+  TYPE_TARGET_TYPE (result_type) = element_type;
+  TYPE_LENGTH (result_type) = number * TYPE_LENGTH (element_type);
+  TYPE_NFIELDS (result_type) = 1;
+  TYPE_FIELDS (result_type) =
+    (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field));
+  TYPE_FIELD_TYPE (result_type, 0) = builtin_type_int;
+  TYPE_VPTR_FIELDNO (result_type) = -1;
+
+  return result_type;
+}
+
+\f
+/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE.  */
+
+void
+smash_to_member_type (type, domain, to_type)
+     struct type *type, *domain, *to_type;
+{
+  bzero (type, sizeof (struct type));
+  TYPE_TARGET_TYPE (type) = to_type;
+  TYPE_DOMAIN_TYPE (type) = domain;
+
+  /* In practice, this is never needed.  */
+  TYPE_LENGTH (type) = 1;
+  TYPE_CODE (type) = TYPE_CODE_MEMBER;
+
+  TYPE_MAIN_VARIANT (type) = lookup_member_type (domain, to_type);
+}
+
+/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE.  */
+
+void
+smash_to_method_type (type, domain, to_type, args)
+     struct type *type, *domain, *to_type, **args;
+{
+  bzero (type, sizeof (struct type));
+  TYPE_TARGET_TYPE (type) = to_type;
+  TYPE_DOMAIN_TYPE (type) = domain;
+  TYPE_ARG_TYPES (type) = args;
+
+  /* In practice, this is never needed.  */
+  TYPE_LENGTH (type) = 1;
+  TYPE_CODE (type) = TYPE_CODE_METHOD;
+
+  TYPE_MAIN_VARIANT (type) = lookup_method_type (domain, to_type, args);
+}
+\f
+/* Find which partial symtab on the partial_symtab_list contains
+   PC.  Return 0 if none.  */
+
+struct partial_symtab *
+find_pc_psymtab (pc)
+     register CORE_ADDR pc;
+{
+  register struct partial_symtab *ps;
+
+  for (ps = partial_symtab_list; ps; ps = ps->next)
+    if (pc >= ps->textlow && pc < ps->texthigh)
+      return ps;
+
+  return 0;
+}
+
+/* Find which partial symbol within a psymtab contains PC.  Return 0
+   if none.  Check all psymtabs if PSYMTAB is 0.  */
+struct partial_symbol *
+find_pc_psymbol (psymtab, pc)
+     struct partial_symtab *psymtab;
+     CORE_ADDR pc;
+{
+  struct partial_symbol *best, *p;
+  CORE_ADDR best_pc;
+  
+  if (!psymtab)
+    psymtab = find_pc_psymtab (pc);
+  if (!psymtab)
+    return 0;
+
+  best_pc = psymtab->textlow - 1;
+
+  for (p = static_psymbols.list + psymtab->statics_offset;
+       (p - (static_psymbols.list + psymtab->statics_offset)
+       < psymtab->n_static_syms);
+       p++)
+    if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
+       && SYMBOL_CLASS (p) == LOC_BLOCK
+       && pc >= SYMBOL_VALUE_ADDRESS (p)
+       && SYMBOL_VALUE_ADDRESS (p) > best_pc)
+      {
+       best_pc = SYMBOL_VALUE_ADDRESS (p);
+       best = p;
+      }
+  if (best_pc == psymtab->textlow - 1)
+    return 0;
+  return best;
+}
+
+\f
+/* Find the definition for a specified symbol name NAME
+   in namespace NAMESPACE, visible from lexical block BLOCK.
+   Returns the struct symbol pointer, or zero if no symbol is found.
+   If SYMTAB is non-NULL, store the symbol table in which the
+   symbol was found there, or NULL if not found.
+   C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
+   NAME is a field of the current implied argument `this'.  If so set
+   *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero. 
+   BLOCK_FOUND is set to the block in which NAME is found (in the case of
+   a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
+
+struct symbol *
+lookup_symbol (name, block, namespace, is_a_field_of_this, symtab)
+     char *name;
+     register struct block *block;
+     enum namespace namespace;
+     int *is_a_field_of_this;
+     struct symtab **symtab;
+{
+  register struct symbol *sym;
+  register struct symtab *s;
+  register struct partial_symtab *ps;
+  struct blockvector *bv;
+
+  /* Search specified block and its superiors.  */
+
+  while (block != 0)
+    {
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) 
+       {
+         block_found = block;
+         if (symtab != NULL)
+           {
+             /* Search the list of symtabs for one which contains the
+                address of the start of this block.  */
+             struct block *b;
+             for (s = symtab_list; s; s = s->next)
+               {
+                 bv = BLOCKVECTOR (s);
+                 b = BLOCKVECTOR_BLOCK (bv, 0);
+                 if (BLOCK_START (b) <= BLOCK_START (block)
+                     && BLOCK_END (b) > BLOCK_START (block))
+                   break;
+               }
+             *symtab = s;
+           }
+
+         return sym;
+       }
+      block = BLOCK_SUPERBLOCK (block);
+    }
+
+  /* C++: If requested to do so by the caller, 
+     check to see if NAME is a field of `this'. */
+  if (is_a_field_of_this)
+    {
+      struct value *v = value_of_this (0);
+      
+      *is_a_field_of_this = 0;
+      if (v && check_field (v, name))
+       {
+         *is_a_field_of_this = 1;
+         if (symtab != NULL)
+           *symtab = NULL;
+         return 0;
+       }
+    }
+
+  /* Now search all global blocks.  Do the symtab's first, then
+     check the psymtab's */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, 0);
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) 
+       {
+         block_found = block;
+         if (symtab != NULL)
+           *symtab = s;
+         return sym;
+       }
+    }
+
+  /* Check for the possibility of the symbol being a global function
+     that is stored on the misc function vector.  Eventually, all
+     global symbols might be resolved in this way.  */
+  
+  if (namespace == VAR_NAMESPACE)
+    {
+      int ind = lookup_misc_func (name);
+
+      /* Look for a mangled C++ name for NAME. */
+      if (ind == -1)
+       {
+         int name_len = strlen (name);
+
+         for (ind = misc_function_count; --ind >= 0; )
+             /* Assume orginal name is prefix of mangled name. */
+             if (!strncmp (misc_function_vector[ind].name, name, name_len))
+               {
+                 char *demangled =
+                     cplus_demangle(misc_function_vector[ind].name, -1);
+                 if (demangled != NULL)
+                   {
+                     int cond = strcmp (demangled, name);
+                     free (demangled);
+                     if (!cond)
+                         break;
+                   }
+               }
+         /* Loop terminates on no match with ind == -1. */
+        }
+
+      if (ind != -1)
+       {
+         s = find_pc_symtab (misc_function_vector[ind].address);
+         if (s)
+           {
+             bv = BLOCKVECTOR (s);
+             block = BLOCKVECTOR_BLOCK (bv, 0);
+             sym = lookup_block_symbol (block, misc_function_vector[ind].name,
+                                        namespace);
+             /* sym == 0 if symbol was found in the misc_function_vector
+                but not in the symtab.
+                Return 0 to use the misc_function definition of "foo_".
+
+                This happens for Fortran  "foo_" symbols,
+                which are "foo" in the symtab.
+
+                This can also happen if "asm" is used to make a
+                regular symbol but not a debugging symbol, e.g.
+                asm(".globl _main");
+                asm("_main:");
+                */
+
+             if (symtab != NULL)
+               *symtab = s;
+             return sym;
+           }
+       }
+    }
+      
+  for (ps = partial_symtab_list; ps; ps = ps->next)
+    if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace))
+      {
+       s = PSYMTAB_TO_SYMTAB(ps);
+       bv = BLOCKVECTOR (s);
+       block = BLOCKVECTOR_BLOCK (bv, 0);
+       sym = lookup_block_symbol (block, name, namespace);
+       if (!sym)
+         fatal ("Internal: global symbol found in psymtab but not in symtab");
+       if (symtab != NULL)
+         *symtab = s;
+       return sym;
+      }
+
+  /* Now search all per-file blocks.
+     Not strictly correct, but more useful than an error.
+     Do the symtabs first, then check the psymtabs */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, 1);
+      sym = lookup_block_symbol (block, name, namespace);
+      if (sym) 
+       {
+         block_found = block;
+         if (symtab != NULL)
+           *symtab = s;
+         return sym;
+       }
+    }
+
+  for (ps = partial_symtab_list; ps; ps = ps->next)
+    if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace))
+      {
+       s = PSYMTAB_TO_SYMTAB(ps);
+       bv = BLOCKVECTOR (s);
+       block = BLOCKVECTOR_BLOCK (bv, 1);
+       sym = lookup_block_symbol (block, name, namespace);
+       if (!sym)
+         fatal ("Internal: static symbol found in psymtab but not in symtab");
+       if (symtab != NULL)
+         *symtab = s;
+       return sym;
+      }
+
+  if (symtab != NULL)
+    *symtab = NULL;
+  return 0;
+}
+
+/* Look, in partial_symtab PST, for symbol NAME.  Check the global
+   symbols if GLOBAL, the static symbols if not */
+
+static struct partial_symbol *
+lookup_partial_symbol (pst, name, global, namespace)
+     struct partial_symtab *pst;
+     char *name;
+     int global;
+     enum namespace namespace;
+{
+  struct partial_symbol *start, *psym;
+  int length = (global ? pst->n_global_syms : pst->n_static_syms);
+
+  if (!length)
+    return (struct partial_symbol *) 0;
+  
+  start = (global ?
+          global_psymbols.list + pst->globals_offset :
+          static_psymbols.list + pst->statics_offset  );
+
+  if (global)                  /* This means we can use a binary */
+                               /* search.  */
+    {
+      struct partial_symbol *top, *bottom, *center;
+
+      /* Binary search.  This search is guaranteed to end with center
+         pointing at the earliest partial symbol with the correct
+        name.  At that point *all* partial symbols with that name
+        will be checked against the correct namespace. */
+      bottom = start;
+      top = start + length - 1;
+      while (top > bottom)
+       {
+         center = bottom + (top - bottom) / 2;
+
+         assert (center < top);
+         
+         if (strcmp (SYMBOL_NAME (center), name) >= 0)
+           top = center;
+         else
+           bottom = center + 1;
+       }
+      assert (top == bottom);
+      
+      while (!strcmp (SYMBOL_NAME (top), name))
+       {
+         if (SYMBOL_NAMESPACE (top) == namespace)
+           return top;
+         top ++;
+       }
+    }
+  else
+    {
+      /* Can't use a binary search */
+      for (psym = start; psym < start + length; psym++)
+       if (namespace == SYMBOL_NAMESPACE (psym)
+           && !strcmp (name, SYMBOL_NAME (psym)))
+         return psym;
+    }
+
+  return (struct partial_symbol *) 0;
+}
+
+/* Look for a symbol in block BLOCK.  */
+
+struct symbol *
+lookup_block_symbol (block, name, namespace)
+     register struct block *block;
+     char *name;
+     enum namespace namespace;
+{
+  register int bot, top, inc;
+  register struct symbol *sym, *parameter_sym;
+
+  top = BLOCK_NSYMS (block);
+  bot = 0;
+
+  /* If the blocks's symbols were sorted, start with a binary search.  */
+
+  if (BLOCK_SHOULD_SORT (block))
+    {
+      /* First, advance BOT to not far before
+        the first symbol whose name is NAME.  */
+
+      while (1)
+       {
+         inc = (top - bot + 1);
+         /* No need to keep binary searching for the last few bits worth.  */
+         if (inc < 4)
+           break;
+         inc = (inc >> 1) + bot;
+         sym = BLOCK_SYM (block, inc);
+         if (SYMBOL_NAME (sym)[0] < name[0])
+           bot = inc;
+         else if (SYMBOL_NAME (sym)[0] > name[0])
+           top = inc;
+         else if (strcmp (SYMBOL_NAME (sym), name) < 0)
+           bot = inc;
+         else
+           top = inc;
+       }
+
+      /* Now scan forward until we run out of symbols,
+        find one whose name is greater than NAME,
+        or find one we want.
+        If there is more than one symbol with the right name and namespace,
+        we return the first one.  dbxread.c is careful to make sure
+        that if one is a register then it comes first.  */
+
+      top = BLOCK_NSYMS (block);
+      while (bot < top)
+       {
+         sym = BLOCK_SYM (block, bot);
+         inc = SYMBOL_NAME (sym)[0] - name[0];
+         if (inc == 0)
+           inc = strcmp (SYMBOL_NAME (sym), name);
+         if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
+           return sym;
+         if (inc > 0)
+           return 0;
+         bot++;
+       }
+      return 0;
+    }
+
+  /* Here if block isn't sorted.
+     This loop is equivalent to the loop above,
+     but hacked greatly for speed.
+
+     Note that parameter symbols do not always show up last in the
+     list; this loop makes sure to take anything else other than
+     parameter symbols first; it only uses parameter symbols as a
+     last resort.  Note that this only takes up extra computation
+     time on a match.  */
+
+  parameter_sym = (struct symbol *) 0;
+  top = BLOCK_NSYMS (block);
+  inc = name[0];
+  while (bot < top)
+    {
+      sym = BLOCK_SYM (block, bot);
+      if (SYMBOL_NAME (sym)[0] == inc
+         && !strcmp (SYMBOL_NAME (sym), name)
+         && SYMBOL_NAMESPACE (sym) == namespace)
+       {
+         if (SYMBOL_CLASS (sym) == LOC_ARG
+             || SYMBOL_CLASS (sym) == LOC_LOCAL_ARG
+             || SYMBOL_CLASS (sym) == LOC_REF_ARG
+             || SYMBOL_CLASS (sym) == LOC_REGPARM)
+           parameter_sym = sym;
+         else
+           return sym;
+       }
+      bot++;
+    }
+  return parameter_sym;                /* Will be 0 if not found. */
+}
+\f
+/* Return the symbol for the function which contains a specified
+   lexical block, described by a struct block BL.  */
+
+struct symbol *
+block_function (bl)
+     struct block *bl;
+{
+  while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
+    bl = BLOCK_SUPERBLOCK (bl);
+
+  return BLOCK_FUNCTION (bl);
+}
+
+/* Subroutine of find_pc_line */
+
+struct symtab *
+find_pc_symtab (pc)
+     register CORE_ADDR pc;
+{
+  register struct block *b;
+  struct blockvector *bv;
+  register struct symtab *s;
+  register struct partial_symtab *ps;
+
+  /* Search all symtabs for one whose file contains our pc */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      bv = BLOCKVECTOR (s);
+      b = BLOCKVECTOR_BLOCK (bv, 0);
+      if (BLOCK_START (b) <= pc
+         && BLOCK_END (b) > pc)
+       break;
+    }
+
+  if (!s)
+    {
+      ps = find_pc_psymtab (pc);
+      if (ps && ps->readin)
+       fatal ("Internal error: pc in read in psymtab, but not in symtab.");
+
+      if (ps)
+       s = PSYMTAB_TO_SYMTAB (ps);
+    }
+
+  return s;
+}
+
+/* Find the source file and line number for a given PC value.
+   Return a structure containing a symtab pointer, a line number,
+   and a pc range for the entire source line.
+   The value's .pc field is NOT the specified pc.
+   NOTCURRENT nonzero means, if specified pc is on a line boundary,
+   use the line that ends there.  Otherwise, in that case, the line
+   that begins there is used.  */
+
+struct symtab_and_line
+find_pc_line (pc, notcurrent)
+     CORE_ADDR pc;
+     int notcurrent;
+{
+  struct symtab *s;
+  register struct linetable *l;
+  register int len;
+  register int i;
+  register struct linetable_entry *item;
+  struct symtab_and_line val;
+  struct blockvector *bv;
+
+  /* Info on best line seen so far, and where it starts, and its file.  */
+
+  int best_line = 0;
+  CORE_ADDR best_pc = 0;
+  CORE_ADDR best_end = 0;
+  struct symtab *best_symtab = 0;
+
+  /* Store here the first line number
+     of a file which contains the line at the smallest pc after PC.
+     If we don't find a line whose range contains PC,
+     we will use a line one less than this,
+     with a range from the start of that file to the first line's pc.  */
+  int alt_line = 0;
+  CORE_ADDR alt_pc = 0;
+  struct symtab *alt_symtab = 0;
+
+  /* Info on best line seen in this file.  */
+
+  int prev_line;
+  CORE_ADDR prev_pc;
+
+  /* Info on first line of this file.  */
+
+  int first_line;
+  CORE_ADDR first_pc;
+
+  /* If this pc is not from the current frame,
+     it is the address of the end of a call instruction.
+     Quite likely that is the start of the following statement.
+     But what we want is the statement containing the instruction.
+     Fudge the pc to make sure we get that.  */
+
+  if (notcurrent) pc -= 1;
+
+  s = find_pc_symtab (pc);
+  if (s == 0)
+    {
+      val.symtab = 0;
+      val.line = 0;
+      val.pc = pc;
+      val.end = 0;
+      return val;
+    }
+
+  bv = BLOCKVECTOR (s);
+
+  /* Look at all the symtabs that share this blockvector.
+     They all have the same apriori range, that we found was right;
+     but they have different line tables.  */
+
+  for (; s && BLOCKVECTOR (s) == bv; s = s->next)
+    {
+      /* Find the best line in this symtab.  */
+      l = LINETABLE (s);
+      len = l->nitems;
+      prev_line = -1;
+      first_line = -1;
+      for (i = 0; i < len; i++)
+       {
+         item = &(l->item[i]);
+         
+         if (first_line < 0)
+           {
+             first_line = item->line;
+             first_pc = item->pc;
+           }
+         /* Return the last line that did not start after PC.  */
+         if (pc >= item->pc)
+           {
+             prev_line = item->line;
+             prev_pc = item->pc;
+           }
+         else
+           break;
+       }
+
+      /* Is this file's best line closer than the best in the other files?
+        If so, record this file, and its best line, as best so far.  */
+      if (prev_line >= 0 && prev_pc > best_pc)
+       {
+         best_pc = prev_pc;
+         best_line = prev_line;
+         best_symtab = s;
+         if (i < len)
+           best_end = item->pc;
+         else
+           best_end = 0;
+       }
+      /* Is this file's first line closer than the first lines of other files?
+        If so, record this file, and its first line, as best alternate.  */
+      if (first_line >= 0 && first_pc > pc
+         && (alt_pc == 0 || first_pc < alt_pc))
+       {
+         alt_pc = first_pc;
+         alt_line = first_line;
+         alt_symtab = s;
+       }
+    }
+  if (best_symtab == 0)
+    {
+      val.symtab = alt_symtab;
+      val.line = alt_line - 1;
+      val.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0));
+      val.end = alt_pc;
+    }
+  else
+    {
+      val.symtab = best_symtab;
+      val.line = best_line;
+      val.pc = best_pc;
+      val.end = (best_end ? best_end
+                  : (alt_pc ? alt_pc
+                     : BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0))));
+    }
+  return val;
+}
+\f
+/* Find the PC value for a given source file and line number.
+   Returns zero for invalid line number.
+   The source file is specified with a struct symtab.  */
+
+CORE_ADDR
+find_line_pc (symtab, line)
+     struct symtab *symtab;
+     int line;
+{
+  register struct linetable *l;
+  register int ind;
+  int dummy;
+
+  if (symtab == 0)
+    return 0;
+  l = LINETABLE (symtab);
+  ind = find_line_common(l, line, &dummy);
+  return ind ? l->item[ind].pc : 0;
+}
+
+/* Find the range of pc values in a line.
+   Store the starting pc of the line into *STARTPTR
+   and the ending pc (start of next line) into *ENDPTR.
+   Returns 1 to indicate success.
+   Returns 0 if could not find the specified line.  */
+
+int
+find_line_pc_range (symtab, thisline, startptr, endptr)
+     struct symtab *symtab;
+     int thisline;
+     CORE_ADDR *startptr, *endptr;
+{
+  register struct linetable *l;
+  register int ind;
+  int exact_match;             /* did we get an exact linenumber match */
+
+  if (symtab == 0)
+    return 0;
+
+  l = LINETABLE (symtab);
+  ind = find_line_common (l, thisline, &exact_match);
+  if (ind)
+    {
+      *startptr = l->item[ind].pc;
+      /* If we have not seen an entry for the specified line,
+        assume that means the specified line has zero bytes.  */
+      if (!exact_match || ind == l->nitems-1)
+       *endptr = *startptr;
+      else
+       /* Perhaps the following entry is for the following line.
+          It's worth a try.  */
+       if (ind+1 < l->nitems
+        && l->item[ind+1].line == thisline + 1)
+         *endptr = l->item[ind+1].pc;
+       else
+         *endptr = find_line_pc (symtab, thisline+1);
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Given a line table and a line number, return the index into the line
+   table for the pc of the nearest line whose number is >= the specified one.
+   Return 0 if none is found.  The value is never zero is it is an index.
+
+   Set *EXACT_MATCH nonzero if the value returned is an exact match.  */
+
+static int
+find_line_common (l, lineno, exact_match)
+     register struct linetable *l;
+     register int lineno;
+     int *exact_match;
+{
+  register int i;
+  register int len;
+
+  /* BEST is the smallest linenumber > LINENO so far seen,
+     or 0 if none has been seen so far.
+     BEST_INDEX identifies the item for it.  */
+
+  int best_index = 0;
+  int best = 0;
+
+  if (lineno <= 0)
+    return 0;
+
+  len = l->nitems;
+  for (i = 0; i < len; i++)
+    {
+      register struct linetable_entry *item = &(l->item[i]);
+
+      if (item->line == lineno)
+       {
+         *exact_match = 1;
+         return i;
+       }
+
+      if (item->line > lineno && (best == 0 || item->line < best))
+       {
+         best = item->line;
+         best_index = i;
+       }
+    }
+
+  /* If we got here, we didn't get an exact match.  */
+
+  *exact_match = 0;
+  return best_index;
+}
+
+int
+find_pc_line_pc_range (pc, startptr, endptr)
+     CORE_ADDR pc;
+     CORE_ADDR *startptr, *endptr;
+{
+  struct symtab_and_line sal;
+  sal = find_pc_line (pc, 0);
+  *startptr = sal.pc;
+  *endptr = sal.end;
+  return sal.symtab != 0;
+}
+\f
+/* Recursive helper function for decode_line_1.
+ * Look for methods named NAME in type T.
+ * Return number of matches.
+ * Put matches in PHYSNAMES and SYM_ARR (which better be big enough!).
+ * These allocations seem to define "big enough":
+ * sym_arr = (struct symbol **) alloca(TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*));
+ * physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*));
+ */
+
+int
+find_methods(t, name, physnames, sym_arr)
+     struct type *t;
+     char *name;
+     char **physnames;
+     struct symbol **sym_arr;
+{
+  int i1 = 0;
+  int ibase;
+  struct symbol *sym_class;
+  char *class_name = type_name_no_tag (t);
+  /* Ignore this class if it doesn't have a name.
+     This prevents core dumps, but is just a workaround
+     because we might not find the function in
+     certain cases, such as
+     struct D {virtual int f();}
+     struct C : D {virtual int g();}
+     (in this case g++ 1.35.1- does not put out a name
+     for D as such, it defines type 19 (for example) in
+     the same stab as C, and then does a
+     .stabs "D:T19" and a .stabs "D:t19".
+     Thus
+     "break C::f" should not be looking for field f in
+     the class named D, 
+     but just for the field f in the baseclasses of C
+     (no matter what their names).
+     
+     However, I don't know how to replace the code below
+     that depends on knowing the name of D.  */
+  if (class_name
+      && (sym_class = lookup_symbol (class_name,
+                                    (struct block *)NULL,
+                                    STRUCT_NAMESPACE,
+                                    (int *)NULL,
+                                    (struct symtab **)NULL)))
+    {
+      int method_counter;
+      t = SYMBOL_TYPE (sym_class);
+      for (method_counter = TYPE_NFN_FIELDS (t) - 1;
+          method_counter >= 0;
+          --method_counter)
+       {
+         int field_counter;
+         struct fn_field *f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+         char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
+         if (!strcmp (name, method_name))
+           /* Find all the fields with that name.  */
+           for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+                field_counter >= 0;
+                --field_counter)
+             {
+               char *phys_name;
+               if (TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, field_counter)) & TYPE_FLAG_STUB)
+                 check_stub_method (t, method_counter, field_counter);
+               phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+               physnames[i1] = (char*) alloca (strlen (phys_name) + 1);
+               strcpy (physnames[i1], phys_name);
+               sym_arr[i1] = lookup_symbol (phys_name,
+                                            SYMBOL_BLOCK_VALUE (sym_class),
+                                            VAR_NAMESPACE,
+                                            (int *) NULL,
+                                            (struct symtab **) NULL);
+               if (sym_arr[i1]) i1++;
+             }
+       }
+    }
+  /* Only search baseclasses if there is no match yet,
+   * since names in derived classes override those in baseclasses.
+   */
+  if (i1)
+    return i1;
+  for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
+    i1 += find_methods(TYPE_BASECLASS(t, ibase), name,
+                      physnames + i1, sym_arr + i1);
+  return i1;
+}
+
+/* Parse a string that specifies a line number.
+   Pass the address of a char * variable; that variable will be
+   advanced over the characters actually parsed.
+
+   The string can be:
+
+   LINENUM -- that line number in current file.  PC returned is 0.
+   FILE:LINENUM -- that line in that file.  PC returned is 0.
+   FUNCTION -- line number of openbrace of that function.
+      PC returned is the start of the function.
+   VARIABLE -- line number of definition of that variable.
+      PC returned is 0.
+   FILE:FUNCTION -- likewise, but prefer functions in that file.
+   *EXPR -- line in which address EXPR appears.
+
+   FUNCTION may be an undebuggable function found in misc_function_vector.
+
+   If the argument FUNFIRSTLINE is nonzero, we want the first line
+   of real code inside a function when a function is specified.
+
+   DEFAULT_SYMTAB specifies the file to use if none is specified.
+   It defaults to current_source_symtab.
+   DEFAULT_LINE specifies the line number to use for relative
+   line numbers (that start with signs).  Defaults to current_source_line.
+
+   Note that it is possible to return zero for the symtab
+   if no file is validly specified.  Callers must check that.
+   Also, the line number returned may be invalid.  */
+
+struct symtabs_and_lines
+decode_line_1 (argptr, funfirstline, default_symtab, default_line)
+     char **argptr;
+     int funfirstline;
+     struct symtab *default_symtab;
+     int default_line;
+{
+  struct symtabs_and_lines decode_line_2 ();
+  struct symtabs_and_lines values;
+  struct symtab_and_line val;
+  register char *p, *p1;
+  register struct symtab *s;
+
+  register struct symbol *sym;
+  /* The symtab that SYM was found in.  */
+  struct symtab *sym_symtab;
+
+  register CORE_ADDR pc;
+  register int i;
+  char *copy;
+  struct symbol *sym_class;
+  int i1;
+  struct symbol **sym_arr;
+  struct type *t;
+  char **physnames;
+  
+  /* Defaults have defaults.  */
+
+  if (default_symtab == 0)
+    {
+      default_symtab = current_source_symtab;
+      default_line = current_source_line;
+    }
+
+  /* See if arg is *PC */
+
+  if (**argptr == '*')
+    {
+      (*argptr)++;
+      pc = parse_and_eval_address_1 (argptr);
+      values.sals = (struct symtab_and_line *)
+       xmalloc (sizeof (struct symtab_and_line));
+      values.nelts = 1;
+      values.sals[0] = find_pc_line (pc, 0);
+      values.sals[0].pc = pc;
+      return values;
+    }
+
+  /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+
+  s = 0;
+
+  for (p = *argptr; *p; p++)
+    {
+      if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
+       break;
+    }
+  while (p[0] == ' ' || p[0] == '\t') p++;
+
+  if (p[0] == ':')
+    {
+
+      /*  C++  */
+      if (p[1] ==':')
+       {
+         /* Extract the class name.  */
+         p1 = p;
+         while (p != *argptr && p[-1] == ' ') --p;
+         copy = (char *) alloca (p - *argptr + 1);
+         bcopy (*argptr, copy, p - *argptr);
+         copy[p - *argptr] = 0;
+
+         /* Discard the class name from the arg.  */
+         p = p1 + 2;
+         while (*p == ' ' || *p == '\t') p++;
+         *argptr = p;
+
+         sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0, 
+                                    (struct symtab **)NULL);
+       
+         if (sym_class &&
+             (TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_STRUCT
+              || TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION))
+           {
+             /* Arg token is not digits => try it as a function name
+                Find the next token (everything up to end or next whitespace). */
+             p = *argptr;
+             while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++;
+             copy = (char *) alloca (p - *argptr + 1);
+             bcopy (*argptr, copy, p - *argptr);
+             copy[p - *argptr] = '\0';
+
+             /* no line number may be specified */
+             while (*p == ' ' || *p == '\t') p++;
+             *argptr = p;
+
+             sym = 0;
+             i1 = 0;           /*  counter for the symbol array */
+             t = SYMBOL_TYPE (sym_class);
+             sym_arr = (struct symbol **) alloca(TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*));
+             physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*));
+
+             if (destructor_name_p (copy, t))
+               {
+                 /* destructors are a special case.  */
+                 struct fn_field *f = TYPE_FN_FIELDLIST1 (t, 0);
+                 int len = TYPE_FN_FIELDLIST_LENGTH (t, 0) - 1;
+                 char *phys_name = TYPE_FN_FIELD_PHYSNAME (f, len);
+                 physnames[i1] = (char *)alloca (strlen (phys_name) + 1);
+                 strcpy (physnames[i1], phys_name);
+                 sym_arr[i1] =
+                   lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class),
+                                  VAR_NAMESPACE, 0, (struct symtab **)NULL);
+                 if (sym_arr[i1]) i1++;
+               }
+             else
+               i1 = find_methods (t, copy, physnames, sym_arr);
+             if (i1 == 1)
+               {
+                 /* There is exactly one field with that name.  */
+                 sym = sym_arr[0];
+
+                 if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+                   {
+                     /* Arg is the name of a function */
+                     pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+                     if (funfirstline)
+                       SKIP_PROLOGUE (pc);
+                     values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
+                     values.nelts = 1;
+                     values.sals[0] = find_pc_line (pc, 0);
+                     values.sals[0].pc = (values.sals[0].end && values.sals[0].pc != pc) ? values.sals[0].end : pc;
+                   }
+                 else
+                   {
+                     values.nelts = 0;
+                   }
+                 return values;
+               }
+             if (i1 > 0)
+               {
+                 /* There is more than one field with that name
+                    (overloaded).  Ask the user which one to use.  */
+                 return decode_line_2 (sym_arr, i1, funfirstline);
+               }
+             else
+               error ("that class does not have any method named %s",copy);
+           }
+         else
+           /* The quotes are important if copy is empty.  */
+           error("No class, struct, or union named \"%s\"", copy );
+       }
+      /*  end of C++  */
+
+
+      /* Extract the file name.  */
+      p1 = p;
+      while (p != *argptr && p[-1] == ' ') --p;
+      copy = (char *) alloca (p - *argptr + 1);
+      bcopy (*argptr, copy, p - *argptr);
+      copy[p - *argptr] = 0;
+
+      /* Find that file's data.  */
+      s = lookup_symtab (copy);
+      if (s == 0)
+       {
+         if (symtab_list == 0 && partial_symtab_list == 0)
+           error (no_symtab_msg);
+         error ("No source file named %s.", copy);
+       }
+
+      /* Discard the file name from the arg.  */
+      p = p1 + 1;
+      while (*p == ' ' || *p == '\t') p++;
+      *argptr = p;
+    }
+
+  /* S is specified file's symtab, or 0 if no file specified.
+     arg no longer contains the file name.  */
+
+  /* Check whether arg is all digits (and sign) */
+
+  p = *argptr;
+  if (*p == '-' || *p == '+') p++;
+  while (*p >= '0' && *p <= '9')
+    p++;
+
+  if (p != *argptr && (*p == 0 || *p == ' ' || *p == '\t' || *p == ','))
+    {
+      /* We found a token consisting of all digits -- at least one digit.  */
+      enum sign {none, plus, minus} sign = none;
+
+      /* This is where we need to make sure that we have good defaults.
+        We must guarantee that this section of code is never executed
+        when we are called with just a function name, since
+        select_source_symtab calls us with such an argument  */
+
+      if (s == 0 && default_symtab == 0)
+       {
+         if (symtab_list == 0 && partial_symtab_list == 0)
+           error (no_symtab_msg);
+         select_source_symtab (0);
+         default_symtab = current_source_symtab;
+         default_line = current_source_line;
+       }
+
+      if (**argptr == '+')
+       sign = plus, (*argptr)++;
+      else if (**argptr == '-')
+       sign = minus, (*argptr)++;
+      val.line = atoi (*argptr);
+      switch (sign)
+       {
+       case plus:
+         if (p == *argptr)
+           val.line = 5;
+         if (s == 0)
+           val.line = default_line + val.line;
+         break;
+       case minus:
+         if (p == *argptr)
+           val.line = 15;
+         if (s == 0)
+           val.line = default_line - val.line;
+         else
+           val.line = 1;
+         break;
+       case none:
+         break;        /* No need to adjust val.line.  */
+       }
+
+      while (*p == ' ' || *p == '\t') p++;
+      *argptr = p;
+      if (s == 0)
+       s = default_symtab;
+      val.symtab = s;
+      val.pc = 0;
+      values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
+      values.sals[0] = val;
+      values.nelts = 1;
+      return values;
+    }
+
+  /* Arg token is not digits => try it as a variable name
+     Find the next token (everything up to end or next whitespace).  */
+  p = *argptr;
+  while (*p && *p != ' ' && *p != '\t' && *p != ',') p++;
+  copy = (char *) alloca (p - *argptr + 1);
+  bcopy (*argptr, copy, p - *argptr);
+  copy[p - *argptr] = 0;
+  while (*p == ' ' || *p == '\t') p++;
+  *argptr = p;
+
+  /* Look up that token as a variable.
+     If file specified, use that file's per-file block to start with.  */
+
+  sym = lookup_symbol (copy,
+                      (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1)
+                       : get_selected_block ()),
+                      VAR_NAMESPACE, 0, &sym_symtab);
+
+  if (sym != NULL)
+    {
+      if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+       {
+         /* Arg is the name of a function */
+         pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+         if (funfirstline)
+           SKIP_PROLOGUE (pc);
+         val = find_pc_line (pc, 0);
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+         /* Convex: no need to suppress code on first line, if any */
+         val.pc = pc;
+#else
+         val.pc = (val.end && val.pc != pc) ? val.end : pc;
+#endif
+         values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
+         values.sals[0] = val;
+         values.nelts = 1;
+         
+         /* I think this is always the same as the line that
+            we calculate above, but the general principle is
+            "trust the symbols more than stuff like
+            SKIP_PROLOGUE".  */
+         if (SYMBOL_LINE (sym) != 0)
+           values.sals[0].line = SYMBOL_LINE (sym);
+         
+         return values;
+       }
+      else if (SYMBOL_LINE (sym) != 0)
+       {
+         /* We know its line number.  */
+         values.sals = (struct symtab_and_line *)
+           xmalloc (sizeof (struct symtab_and_line));
+         values.nelts = 1;
+         bzero (&values.sals[0], sizeof (values.sals[0]));
+         values.sals[0].symtab = sym_symtab;
+         values.sals[0].line = SYMBOL_LINE (sym);
+         return values;
+       }
+      else
+       /* This can happen if it is compiled with a compiler which doesn't
+          put out line numbers for variables.  */
+       error ("Line number not known for symbol \"%s\"", copy);
+    }
+
+  if (symtab_list == 0 && partial_symtab_list == 0)
+    error (no_symtab_msg);
+
+  if ((i = lookup_misc_func (copy)) >= 0)
+    {
+      val.symtab = 0;
+      val.line = 0;
+      val.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
+      if (funfirstline)
+       SKIP_PROLOGUE (val.pc);
+      values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
+      values.sals[0] = val;
+      values.nelts = 1;
+      return values;
+    }
+
+  error ("Function %s not defined.", copy);
+  return values;       /* for lint */
+}
+
+struct symtabs_and_lines
+decode_line_spec (string, funfirstline)
+     char *string;
+     int funfirstline;
+{
+  struct symtabs_and_lines sals;
+  if (string == 0)
+    error ("Empty line specification.");
+  sals = decode_line_1 (&string, funfirstline,
+                       current_source_symtab, current_source_line);
+  if (*string)
+    error ("Junk at end of line specification: %s", string);
+  return sals;
+}
+
+/* Given a list of NELTS symbols in sym_arr (with corresponding
+   mangled names in physnames), return a list of lines to operate on
+   (ask user if necessary).  */
+struct symtabs_and_lines
+decode_line_2 (sym_arr, nelts, funfirstline)
+     struct symbol *sym_arr[];
+     int nelts;
+     int funfirstline;
+{
+  char *getenv();
+  struct symtabs_and_lines values, return_values;
+  register CORE_ADDR pc;
+  char *args, *arg1, *command_line_input ();
+  int i;
+  char *prompt;
+
+  values.sals = (struct symtab_and_line *) alloca (nelts * sizeof(struct symtab_and_line));
+  return_values.sals = (struct symtab_and_line *) xmalloc (nelts * sizeof(struct symtab_and_line));
+
+  i = 0;
+  printf("[0] cancel\n[1] all\n");
+  while (i < nelts)
+    {
+      if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
+       {
+         /* Arg is the name of a function */
+         pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i])) 
+              + FUNCTION_START_OFFSET;
+         if (funfirstline)
+           SKIP_PROLOGUE (pc);
+         values.sals[i] = find_pc_line (pc, 0);
+         values.sals[i].pc = (values.sals[i].end && values.sals[i].pc != pc) ?
+                              values.sals[i].end                      :  pc;
+         printf("[%d] file:%s; line number:%d\n",
+                (i+2), values.sals[i].symtab->filename, values.sals[i].line);
+       }
+      else printf ("?HERE\n");
+      i++;
+    }
+  
+  if ((prompt = getenv ("PS2")) == NULL)
+    {
+      prompt = ">";
+    }
+  printf("%s ",prompt);
+  fflush(stdout);
+
+  args = command_line_input (0, 0);
+  
+  if (args == 0)
+    error_no_arg ("one or more choice numbers");
+
+  i = 0;
+  while (*args)
+    {
+      int num;
+
+      arg1 = args;
+      while (*arg1 >= '0' && *arg1 <= '9') arg1++;
+      if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
+       error ("Arguments must be choice numbers.");
+
+      num = atoi (args);
+
+      if (num == 0)
+       error ("cancelled");
+      else if (num == 1)
+       {
+         bcopy (values.sals, return_values.sals, (nelts * sizeof(struct symtab_and_line)));
+         return_values.nelts = nelts;
+         return return_values;
+       }
+
+      if (num > nelts + 2)
+       {
+         printf ("No choice number %d.\n", num);
+       }
+      else
+       {
+         num -= 2;
+         if (values.sals[num].pc)
+           {
+             return_values.sals[i++] = values.sals[num];
+             values.sals[num].pc = 0;
+           }
+         else
+           {
+             printf ("duplicate request for %d ignored.\n", num);
+           }
+       }
+
+      args = arg1;
+      while (*args == ' ' || *args == '\t') args++;
+    }
+  return_values.nelts = i;
+  return return_values;
+}
+
+/* Return the index of misc function named NAME.  */
+
+int
+lookup_misc_func (name)
+     register char *name;
+{
+  register int i;
+
+  for (i = 0; i < misc_function_count; i++)
+    if (!strcmp (misc_function_vector[i].name, name))
+      return i;
+  return -1;           /* not found */
+}
+\f
+/* Slave routine for sources_info.  Force line breaks at ,'s.
+   NAME is the name to print and *FIRST is nonzero if this is the first
+   name printed.  Set *FIRST to zero.  */
+static void
+output_source_filename (name, first)
+     char *name;
+     int *first;
+{
+  static int column;
+  /* Table of files printed so far.  Since a single source file can
+     result in several partial symbol tables, we need to avoid printing
+     it more than once.  Note: if some of the psymtabs are read in and
+     some are not, it gets printed both under "Source files for which
+     symbols have been read" and "Source files for which symbols will
+     be read in on demand".  I consider this a reasonable way to deal
+     with the situation.  I'm not sure whether this can also happen for
+     symtabs; it doesn't hurt to check.  */
+  static char **tab = NULL;
+  /* Allocated size of tab in elements.
+     Start with one 256-byte block (when using GNU malloc.c).
+     24 is the malloc overhead when range checking is in effect.  */
+  static int tab_alloc_size = (256 - 24) / sizeof (char *);
+  /* Current size of tab in elements.  */
+  static int tab_cur_size;
+
+  char **p;
+
+  if (*first)
+    {
+      if (tab == NULL)
+       tab = (char **) xmalloc (tab_alloc_size * sizeof (*tab));
+      tab_cur_size = 0;
+    }
+
+  /* Is NAME in tab?  */
+  for (p = tab; p < tab + tab_cur_size; p++)
+    if (strcmp (*p, name) == 0)
+      /* Yes; don't print it again.  */
+      return;
+  /* No; add it to tab.  */
+  if (tab_cur_size == tab_alloc_size)
+    {
+      tab_alloc_size *= 2;
+      tab = (char **) xrealloc (tab, tab_alloc_size * sizeof (*tab));
+    }
+  tab[tab_cur_size++] = name;
+
+  if (*first)
+    {
+      column = 0;
+      *first = 0;
+    }
+  else
+    {
+      printf_filtered (",");
+      column++;
+    }
+
+  if (column != 0 && column + strlen (name) >= 70)
+    {
+      printf_filtered ("\n");
+      column = 0;
+    }
+  else if (column != 0)
+    {
+      printf_filtered (" ");
+      column++;
+    }
+  fputs_filtered (name, stdout);
+  column += strlen (name);
+}  
+
+static void
+sources_info ()
+{
+  register struct symtab *s;
+  register struct partial_symtab *ps;
+  int first;
+  
+  if (symtab_list == 0 && partial_symtab_list == 0)
+    {
+      printf (no_symtab_msg);
+      return;
+    }
+  
+  printf_filtered ("Source files for which symbols have been read in:\n\n");
+
+  first = 1;
+  for (s = symtab_list; s; s = s->next)
+    output_source_filename (s->filename, &first);
+  printf_filtered ("\n\n");
+  
+  printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
+
+  first = 1;
+  for (ps = partial_symtab_list; ps; ps = ps->next)
+    if (!ps->readin)
+      output_source_filename (ps->filename, &first);
+  printf_filtered ("\n");
+}
+
+/* List all symbols (if REGEXP is 0) or all symbols matching REGEXP.
+   If CLASS is zero, list all symbols except functions and type names.
+   If CLASS is 1, list only functions.
+   If CLASS is 2, list only type names.
+
+   BPT is non-zero if we should set a breakpoint at the functions
+   we find.  */
+
+static void
+list_symbols (regexp, class, bpt)
+     char *regexp;
+     int class;
+     int bpt;
+{
+  register struct symtab *s;
+  register struct partial_symtab *ps;
+  register struct blockvector *bv;
+  struct blockvector *prev_bv = 0;
+  register struct block *b;
+  register int i, j;
+  register struct symbol *sym;
+  struct partial_symbol *psym;
+  char *val;
+  static char *classnames[]
+    = {"variable", "function", "type", "method"};
+  int found_in_file = 0;
+
+  if (regexp)
+    if (0 != (val = (char *) re_comp (regexp)))
+      error ("Invalid regexp (%s): %s", val, regexp);
+
+  /* Search through the partial_symtab_list *first* for all symbols
+     matching the regexp.  That way we don't have to reproduce all of
+     the machinery below. */
+  for (ps = partial_symtab_list; ps; ps = ps->next)
+    {
+      struct partial_symbol *bound, *gbound, *sbound;
+      int keep_going = 1;
+
+      if (ps->readin) continue;
+      
+      gbound = global_psymbols.list + ps->globals_offset + ps->n_global_syms;
+      sbound = static_psymbols.list + ps->statics_offset + ps->n_static_syms;
+      bound = gbound;
+
+      /* Go through all of the symbols stored in a partial
+        symtab in one loop. */
+      psym = global_psymbols.list + ps->globals_offset;
+      while (keep_going)
+       {
+         if (psym >= bound)
+           {
+             if (bound == gbound && ps->n_static_syms != 0)
+               {
+                 psym = static_psymbols.list + ps->statics_offset;
+                 bound = sbound;
+               }
+             else
+               keep_going = 0;
+           }
+         else
+           {
+             QUIT;
+
+             /* If it would match (logic taken from loop below)
+                load the file and go on to the next one */
+             if ((regexp == 0 || re_exec (SYMBOL_NAME (psym)))
+                 && ((class == 0 && SYMBOL_CLASS (psym) != LOC_TYPEDEF
+                      && SYMBOL_CLASS (psym) != LOC_BLOCK)
+                     || (class == 1 && SYMBOL_CLASS (psym) == LOC_BLOCK)
+                     || (class == 2 && SYMBOL_CLASS (psym) == LOC_TYPEDEF)
+                     || (class == 3 && SYMBOL_CLASS (psym) == LOC_BLOCK)))
+               {
+                 (void) PSYMTAB_TO_SYMTAB(ps);
+                 keep_going = 0;
+               }
+           }
+         psym++;
+       }
+    }
+
+  /* Here, *if* the class is correct (function only, right now), we
+     search through the misc function vector for symbols that
+     match, and call find_pc_symtab on them to force their symbols to
+     be read.  The symbol will then be found during the scan of symtabs
+     below.  */
+
+  if (class == 1)
+    {
+      for (i = 0; i < misc_function_count; i++)
+       if (regexp == 0 || re_exec (misc_function_vector[i].name))
+         {
+           (void) find_pc_symtab (misc_function_vector[i].address);
+         }
+    }
+
+  /* Printout here so as to get after the "Reading in symbols"
+     messages which will be generated above.  */
+  if (!bpt)
+    printf_filtered (regexp
+         ? "All %ss matching regular expression \"%s\":\n"
+         : "All defined %ss:\n",
+         classnames[class],
+         regexp);
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      found_in_file = 0;
+      bv = BLOCKVECTOR (s);
+      /* Often many files share a blockvector.
+        Scan each blockvector only once so that
+        we don't get every symbol many times.
+        It happens that the first symtab in the list
+        for any given blockvector is the main file.  */
+      if (bv != prev_bv)
+       for (i = 0; i < 2; i++)
+         {
+           b = BLOCKVECTOR_BLOCK (bv, i);
+           /* Skip the sort if this block is always sorted.  */
+           if (!BLOCK_SHOULD_SORT (b))
+             sort_block_syms (b);
+           for (j = 0; j < BLOCK_NSYMS (b); j++)
+             {
+               QUIT;
+               sym = BLOCK_SYM (b, j);
+               if ((regexp == 0 || re_exec (SYMBOL_NAME (sym)))
+                   && ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+                        && SYMBOL_CLASS (sym) != LOC_BLOCK)
+                       || (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
+                       || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+                       || (class == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
+                 {
+                   if (bpt)
+                     {
+                       /* Set a breakpoint here, if it's a function */
+                       if (class == 1)
+                         break_command (SYMBOL_NAME(sym), 0);
+                     }
+                   else if (!found_in_file)
+                     {
+                       fputs_filtered ("\nFile ", stdout);
+                       fputs_filtered (s->filename, stdout);
+                       fputs_filtered (":\n", stdout);
+                     }
+                   found_in_file = 1;
+
+                   if (class != 2 && i == 1)
+                     printf_filtered ("static ");
+                   if (class == 2
+                       && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+                     printf_filtered ("typedef ");
+
+                   if (class < 3)
+                     {
+                       type_print (SYMBOL_TYPE (sym),
+                                   (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                                    ? "" : SYMBOL_NAME (sym)),
+                                   stdout, 0);
+
+                       if (class == 2
+                           && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE
+                           && (TYPE_NAME ((SYMBOL_TYPE (sym))) == 0
+                               || 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (sym))),
+                                               SYMBOL_NAME (sym))))
+                         {
+                           fputs_filtered (" ", stdout);
+                           fprint_symbol (stdout, SYMBOL_NAME (sym));
+                         }
+
+                       printf_filtered (";\n");
+                     }
+                   else
+                     {
+# if 0
+                       char buf[1024];
+                       type_print_base (TYPE_FN_FIELD_TYPE(t, i), stdout, 0, 0); 
+                       type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), stdout, 0); 
+                       sprintf (buf, " %s::", type_name_no_tag (t));
+                       type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), buf, name, stdout);
+# endif
+                     }
+                 }
+             }
+         }
+      prev_bv = bv;
+    }
+}
+
+static void
+variables_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 0, 0);
+}
+
+static void
+functions_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 1, 0);
+}
+
+#if 0
+static void
+types_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 2, 0);
+}
+#endif
+
+#if 0
+/* Tiemann says: "info methods was never implemented."  */
+static void
+methods_info (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 3, 0);
+}
+#endif /* 0 */
+
+/* Breakpoint all functions matching regular expression. */
+static void
+rbreak_command (regexp)
+     char *regexp;
+{
+  list_symbols (regexp, 1, 1);
+}
+\f
+/* Initialize the standard C scalar types.  */
+
+static
+struct type *
+init_type (code, length, uns, name)
+     enum type_code code;
+     int length, uns;
+     char *name;
+{
+  register struct type *type;
+
+  type = (struct type *) xmalloc (sizeof (struct type));
+  bzero (type, sizeof *type);
+  TYPE_MAIN_VARIANT (type) = type;
+  TYPE_CODE (type) = code;
+  TYPE_LENGTH (type) = length;
+  TYPE_FLAGS (type) = uns ? TYPE_FLAG_UNSIGNED : 0;
+  TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
+  TYPE_NFIELDS (type) = 0;
+  TYPE_NAME (type) = name;
+
+  /* C++ fancies.  */
+  TYPE_NFN_FIELDS (type) = 0;
+  TYPE_N_BASECLASSES (type) = 0;
+  return type;
+}
+
+/* Return Nonzero if block a is lexically nested within block b,
+   or if a and b have the same pc range.
+   Return zero otherwise. */
+int
+contained_in (a, b)
+     struct block *a, *b;
+{
+  if (!a || !b)
+    return 0;
+  return BLOCK_START (a) >= BLOCK_START (b)
+      && BLOCK_END (a)   <= BLOCK_END (b);
+}
+
+\f
+/* Helper routine for make_symbol_completion_list.  */
+
+int return_val_size, return_val_index;
+char **return_val;
+
+void
+completion_list_add_symbol (symname)
+     char *symname;
+{
+  if (return_val_index + 3 > return_val_size)
+    return_val =
+      (char **)xrealloc (return_val,
+                        (return_val_size *= 2) * sizeof (char *));
+  
+  return_val[return_val_index] =
+    (char *)xmalloc (1 + strlen (symname));
+  
+  strcpy (return_val[return_val_index], symname);
+  
+  return_val[++return_val_index] = (char *)NULL;
+}
+
+/* Return a NULL terminated array of all symbols (regardless of class) which
+   begin by matching TEXT.  If the answer is no symbols, then the return value
+   is an array which contains only a NULL pointer.
+
+   Problem: All of the symbols have to be copied because readline
+   frees them.  I'm not going to worry about this; hopefully there
+   won't be that many.  */
+
+char **
+make_symbol_completion_list (text)
+  char *text;
+{
+  register struct symtab *s;
+  register struct partial_symtab *ps;
+  register struct block *b, *surrounding_static_block = 0;
+  extern struct block *get_selected_block ();
+  register int i, j;
+  struct partial_symbol *psym;
+
+  int text_len = strlen (text);
+  return_val_size = 100;
+  return_val_index = 0;
+  return_val =
+    (char **)xmalloc ((1 + return_val_size) *sizeof (char *));
+  return_val[0] = (char *)NULL;
+
+  /* Look through the partial symtabs for all symbols which begin
+     by matching TEXT.  Add each one that you find to the list.  */
+
+  for (ps = partial_symtab_list; ps; ps = ps->next)
+    {
+      /* If the psymtab's been read in we'll get it when we search
+        through the blockvector.  */
+      if (ps->readin) continue;
+
+      for (psym = global_psymbols.list + ps->globals_offset;
+          psym < (global_psymbols.list + ps->globals_offset
+                  + ps->n_global_syms);
+          psym++)
+       {
+         QUIT;                 /* If interrupted, then quit. */
+         if ((strncmp (SYMBOL_NAME (psym), text, text_len) == 0))
+           completion_list_add_symbol (SYMBOL_NAME (psym));
+       }
+      
+      for (psym = static_psymbols.list + ps->statics_offset;
+          psym < (static_psymbols.list + ps->statics_offset
+                  + ps->n_static_syms);
+          psym++)
+       {
+         QUIT;
+         if ((strncmp (SYMBOL_NAME (psym), text, text_len) == 0))
+           completion_list_add_symbol (SYMBOL_NAME (psym));
+       }
+    }
+
+  /* At this point scan through the misc function vector and add each
+     symbol you find to the list.  Eventually we want to ignore
+     anything that isn't a text symbol (everything else will be
+     handled by the psymtab code above).  */
+
+  for (i = 0; i < misc_function_count; i++)
+    if (!strncmp (text, misc_function_vector[i].name, text_len))
+      completion_list_add_symbol (misc_function_vector[i].name);
+
+  /* Search upwards from currently selected frame (so that we can
+     complete on local vars.  */
+  for (b = get_selected_block (); b; b = BLOCK_SUPERBLOCK (b))
+    {
+      if (!BLOCK_SUPERBLOCK (b))
+       surrounding_static_block = b; /* For elmin of dups */
+      
+      /* Also catch fields of types defined in this places which
+        match our text string.  Only complete on types visible
+        from current context.  */
+      for (i = 0; i < BLOCK_NSYMS (b); i++)
+       {
+         register struct symbol *sym = BLOCK_SYM (b, i);
+         
+         if (!strncmp (SYMBOL_NAME (sym), text, text_len))
+           completion_list_add_symbol (SYMBOL_NAME (sym));
+
+         if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+           {
+             struct type *t = SYMBOL_TYPE (sym);
+             enum type_code c = TYPE_CODE (t);
+
+             if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
+               for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
+                 if (TYPE_FIELD_NAME (t, j) &&
+                     !strncmp (TYPE_FIELD_NAME (t, j), text, text_len))
+                   completion_list_add_symbol (TYPE_FIELD_NAME (t, j));
+           }
+       }
+    }
+
+  /* Go through the symtabs and check the externs and statics for
+     symbols which match.  */
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 0);
+      
+      for (i = 0; i < BLOCK_NSYMS (b); i++)
+       if (!strncmp (SYMBOL_NAME (BLOCK_SYM (b, i)), text, text_len))
+         completion_list_add_symbol (SYMBOL_NAME (BLOCK_SYM (b, i)));
+    }
+
+  for (s = symtab_list; s; s = s->next)
+    {
+      b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1);
+
+      /* Don't do this block twice.  */
+      if (b == surrounding_static_block) continue;
+      
+      for (i = 0; i < BLOCK_NSYMS (b); i++)
+       if (!strncmp (SYMBOL_NAME (BLOCK_SYM (b, i)), text, text_len))
+         completion_list_add_symbol (SYMBOL_NAME (BLOCK_SYM (b, i)));
+    }
+
+  return (return_val);
+}
+\f
+void
+_initialize_symtab ()
+{
+  add_info ("variables", variables_info,
+           "All global and static variable names, or those matching REGEXP.");
+  add_info ("functions", functions_info,
+           "All function names, or those matching REGEXP.");
+#if 0
+  /* This command has at least the following problems:
+     1.  It prints builtin types (in a very strange and confusing fashion).
+     2.  It doesn't print right, e.g. with
+         typedef struct foo *FOO
+        type_print prints "FOO" when we want to make it (in this situation)
+        print "struct foo *".
+     I also think "ptype" or "whatis" is more likely to be useful (but if
+     there is much disagreement "info types" can be fixed).  */
+  add_info ("types", types_info,
+           "All types names, or those matching REGEXP.");
+#endif
+#if 0
+  add_info ("methods", methods_info,
+           "All method names, or those matching REGEXP::REGEXP.\n\
+If the class qualifier is ommited, it is assumed to be the current scope.\n\
+If the first REGEXP is ommited, then all methods matching the second REGEXP\n\
+are listed.");
+#endif
+  add_info ("sources", sources_info,
+           "Source files in the program.");
+
+  add_com ("rbreak", no_class, rbreak_command,
+           "Set a breakpoint for all functions matching REGEXP.");
+
+  /* FIXME:  The code below assumes that the sizes of the basic data
+     types are the same on the host and target machines!!!  */
+
+  builtin_type_void = init_type (TYPE_CODE_VOID, 1, 0, "void");
+
+  builtin_type_float = init_type (TYPE_CODE_FLT, sizeof (float), 0, "float");
+  builtin_type_double = init_type (TYPE_CODE_FLT, sizeof (double), 0, "double");
+
+  builtin_type_char = init_type (TYPE_CODE_INT, sizeof (char), 0, "char");
+  builtin_type_short = init_type (TYPE_CODE_INT, sizeof (short), 0, "short");
+  builtin_type_long = init_type (TYPE_CODE_INT, sizeof (long), 0, "long");
+  builtin_type_int = init_type (TYPE_CODE_INT, sizeof (int), 0, "int");
+
+  builtin_type_unsigned_char = init_type (TYPE_CODE_INT, sizeof (char), 1, "unsigned char");
+  builtin_type_unsigned_short = init_type (TYPE_CODE_INT, sizeof (short), 1, "unsigned short");
+  builtin_type_unsigned_long = init_type (TYPE_CODE_INT, sizeof (long), 1, "unsigned long");
+  builtin_type_unsigned_int = init_type (TYPE_CODE_INT, sizeof (int), 1, "unsigned int");
+#ifdef LONG_LONG
+  builtin_type_long_long =
+    init_type (TYPE_CODE_INT, sizeof (long long), 0, "long long");
+  builtin_type_unsigned_long_long = 
+    init_type (TYPE_CODE_INT, sizeof (long long), 1, "unsigned long long");
+#endif
+  builtin_type_error = init_type (TYPE_CODE_ERROR, 0, 0, "<unknown type>");
+}
+
diff --git a/gdb/symtab.h b/gdb/symtab.h
new file mode 100644 (file)
index 0000000..e63c879
--- /dev/null
@@ -0,0 +1,884 @@
+/* Symbol table definitions for GDB.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (SYMTAB_H)
+#define SYMTAB_H 1
+#include <obstack.h>
+
+/* An obstack to hold objects that should be freed
+   when we load a new symbol table.
+   This includes the symbols made by dbxread
+   and the types that are not permanent.  */
+
+extern struct obstack *symbol_obstack;
+extern struct obstack *psymbol_obstack;
+
+/* Some definitions and declarations to go with use of obstacks.  */
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+#ifdef __STDC__
+extern void *xmalloc ();
+#else
+extern char *xmalloc ();
+#endif
+extern void free ();
+
+/* Some macros for char-based bitfields.  */
+#define B_SET(a,x) (a[x>>3] |= (1 << (x&7)))
+#define B_CLR(a,x) (a[x>>3] &= ~(1 << (x&7)))
+#define B_TST(a,x) (a[x>>3] & (1 << (x&7)))
+#define B_TYPE         unsigned char
+#define        B_BYTES(x)      ( 1 + ((x)>>3) )
+#define        B_CLRALL(a,x) bzero (a, B_BYTES(x))
+
+/* gdb can know one or several symbol tables at the same time;
+   the ultimate intent is to have one for each separately-compiled module.
+   Each such symbol table is recorded by a struct symtab, and they
+   are all chained together.  */
+
+/* In addition, gdb can record any number of miscellaneous undebuggable
+   functions' addresses.  In a system that appends _ to function names,
+   the _'s are removed from the names stored in this table.  */
+
+/* Actually, the misc function list is used to store *all* of the
+   global symbols (text, data, bss, and abs).  It is sometimes used
+   to figure out what symtabs to read in.  The "type" field is used
+   occasionally.
+
+   The misc_info field is available for machine-specific information
+   that can be cached along with a misc function vector entry.  The
+   AMD 29000 tdep.c uses it to remember things it has decoded from the
+   instructions in the function header, so it doesn't have to rederive
+   the info constantly (over a serial line).  It is initialized to zero
+   and stays that way until target-dependent code sets it.  */
+
+enum misc_function_type {mf_unknown = 0, mf_text, mf_data, mf_bss, mf_abs};
+
+struct misc_function
+{
+  char *name;
+  CORE_ADDR address;
+  char *misc_info;     /* Random pointer to misc info.  void * but for old C */
+  enum misc_function_type type;
+};
+
+/* Address and length of the vector recording all misc function names/addresses.  */
+
+struct misc_function *misc_function_vector;
+int misc_function_count;
+\f
+enum language {language_unknown, language_c};
+
+/* All data types of symbols in the compiled program
+   are represented by `struct type' objects.
+   All of these objects are pointed to by the typevector.
+   The type vector may have empty slots that contain zero.  */
+
+struct typevector
+{
+  int length;                  /* Number of types described */
+  struct type *type[1];
+};
+
+/* Different kinds of data types are distinguished by the `code' field.  */
+
+enum type_code
+{
+  TYPE_CODE_UNDEF,             /* Not used; catches errors */
+  TYPE_CODE_PTR,               /* Pointer type */
+  TYPE_CODE_ARRAY,             /* Array type, lower bound zero */
+  TYPE_CODE_STRUCT,            /* C struct or Pascal record */
+  TYPE_CODE_UNION,             /* C union or Pascal variant part */
+  TYPE_CODE_ENUM,              /* Enumeration type */
+  TYPE_CODE_FUNC,              /* Function type */
+  TYPE_CODE_INT,               /* Integer type */
+  TYPE_CODE_FLT,               /* Floating type */
+  TYPE_CODE_VOID,              /* Void type (values zero length) */
+  TYPE_CODE_SET,               /* Pascal sets */
+  TYPE_CODE_RANGE,             /* Range (integers within spec'd bounds) */
+  TYPE_CODE_PASCAL_ARRAY,      /* Array with explicit type of index */
+  TYPE_CODE_ERROR,              /* Unknown type */
+
+  /* C++ */
+  TYPE_CODE_MEMBER,            /* Member type */
+  TYPE_CODE_METHOD,            /* Method type */
+  TYPE_CODE_REF,               /* C++ Reference types */
+};
+
+/* This appears in a type's flags word for an unsigned integer type.  */
+#define TYPE_FLAG_UNSIGNED 1
+/* This appears in a type's flags word
+   if it is a (pointer to a|function returning a)* built in scalar type.
+   These types are never freed.  */
+#define TYPE_FLAG_PERM 4
+/* This appears in a type's flags word if it is a stub type (eg. if
+   someone referenced a type that wasn't definined in a source file
+   via (struct sir_not_appearing_in_this_film *)).  */
+#define TYPE_FLAG_STUB 8
+/* Set when a class has a constructor defined */
+#define        TYPE_FLAG_HAS_CONSTRUCTOR       256
+/* Set when a class has a destructor defined */
+#define        TYPE_FLAG_HAS_DESTRUCTOR        512
+
+struct type
+{
+  /* Code for kind of type */
+  enum type_code code;
+  /* Name of this type, or zero if none.
+     This is used for printing only, except by poorly designed C++ code.
+     Type names specified as input are defined by symbols.  */
+  char *name;
+  /* Length in bytes of storage for a value of this type */
+  unsigned length;
+  /* For a pointer type, describes the type of object pointed to.
+     For an array type, describes the type of the elements.
+     For a function or method type, describes the type of the value.
+     For a range type, describes the type of the full range.
+     Unused otherwise.  */
+  struct type *target_type;
+  /* Type that is a pointer to this type.
+     Zero if no such pointer-to type is known yet.
+     The debugger may add the address of such a type
+     if it has to construct one later.  */ 
+  struct type *pointer_type;
+  /* C++: also need a reference type.  */
+  struct type *reference_type;
+  struct type **arg_types;
+  
+  /* Type that is a function returning this type.
+     Zero if no such function type is known here.
+     The debugger may add the address of such a type
+     if it has to construct one later.  */
+  struct type *function_type;
+
+/* Handling of pointers to members:
+   TYPE_MAIN_VARIANT is used for pointer and pointer
+   to member types.  Normally it the value of the address of its
+   containing type.  However, for pointers to members, we must be
+   able to allocate pointer to member types and look them up
+   from some place of reference.
+   NEXT_VARIANT is the next element in the chain.
+
+   A long time ago (Jul 88; GDB 2.5) Tiemann said that main_variant
+   may no longer be necessary and that he might eliminate it.  I don't
+   know whether this is still true (or ever was).  */
+  struct type *main_variant, *next_variant;
+
+  /* Flags about this type.  */
+  short flags;
+  /* Number of fields described for this type */
+  short nfields;
+  /* For structure and union types, a description of each field.
+     For set and pascal array types, there is one "field",
+     whose type is the domain type of the set or array.
+     For range types, there are two "fields",
+     the minimum and maximum values (both inclusive).
+     For enum types, each possible value is described by one "field".
+
+     Using a pointer to a separate array of fields
+     allows all types to have the same size, which is useful
+     because we can allocate the space for a type before
+     we know what to put in it.  */
+  struct field
+    {
+      /* Position of this field, counting in bits from start of
+        containing structure.  For a function type, this is the
+        position in the argument list of this argument.
+        For a range bound or enum value, this is the value itself.  */
+      int bitpos;
+      /* Size of this field, in bits, or zero if not packed.
+        For an unpacked field, the field's type's length
+        says how many bytes the field occupies.  */
+      int bitsize;
+      /* In a struct or enum type, type of this field.
+        In a function type, type of this argument.
+        In an array type, the domain-type of the array.  */
+      struct type *type;
+      /* Name of field, value or argument.
+        Zero for range bounds and array domains.  */
+      char *name;
+    } *fields;
+
+  /* C++ */
+  B_TYPE *virtual_field_bits; /* if base class is virtual */
+  B_TYPE *private_field_bits;
+  B_TYPE *protected_field_bits;
+
+  /* Number of methods described for this type */
+  short nfn_fields;
+  /* Number of base classes this type derives from. */
+  short n_baseclasses;
+
+  /* Number of methods described for this type plus all the
+     methods that it derives from.  */
+  int nfn_fields_total;
+
+  /* For classes, structures, and unions, a description of each field,
+     which consists of an overloaded name, followed by the types of
+     arguments that the method expects, and then the name after it
+     has been renamed to make it distinct.  */
+  struct fn_fieldlist
+    {
+      /* The overloaded name.  */
+      char *name;
+      /* The number of methods with this name.  */
+      int length;
+      /* The list of methods.  */
+      struct fn_field
+       {
+#if 0
+         /* The overloaded name */
+         char *name;
+#endif
+         /* The return value of the method */
+         struct type *type;
+         /* The argument list */
+         struct type **args;
+         /* The name after it has been processed */
+         char *physname;
+
+         /* For virtual functions.   */
+         /* First baseclass that defines this virtual function.   */
+         struct type *fcontext;
+         /* Index into that baseclass's virtual function table,
+            minus 1; else if static: VOFFSET_STATIC; else: 0.  */
+         int voffset;
+#        define VOFFSET_STATIC (-1)
+       } *fn_fields;
+
+      B_TYPE *private_fn_field_bits;
+      B_TYPE *protected_fn_field_bits;
+
+    } *fn_fieldlists;
+
+  unsigned char via_protected;
+  unsigned char via_public;
+
+  /* For types with virtual functions, VPTR_BASETYPE is the base class which
+     defined the virtual function table pointer.  VPTR_FIELDNO is
+     the field number of that pointer in the structure.
+
+     For types that are pointer to member types, VPTR_BASETYPE
+     ifs the type that this pointer is a member of.
+
+     Unused otherwise.  */
+  struct type *vptr_basetype;
+
+  int vptr_fieldno;
+};
+\f
+/* All of the name-scope contours of the program
+   are represented by `struct block' objects.
+   All of these objects are pointed to by the blockvector.
+
+   Each block represents one name scope.
+   Each lexical context has its own block.
+
+   The first two blocks in the blockvector are special.
+   The first one contains all the symbols defined in this compilation
+   whose scope is the entire program linked together.
+   The second one contains all the symbols whose scope is the
+   entire compilation excluding other separate compilations.
+   In C, these correspond to global symbols and static symbols.
+
+   Each block records a range of core addresses for the code that
+   is in the scope of the block.  The first two special blocks
+   give, for the range of code, the entire range of code produced
+   by the compilation that the symbol segment belongs to.
+
+   The blocks appear in the blockvector
+   in order of increasing starting-address,
+   and, within that, in order of decreasing ending-address.
+
+   This implies that within the body of one function
+   the blocks appear in the order of a depth-first tree walk.  */
+
+struct blockvector
+{
+  /* Number of blocks in the list.  */
+  int nblocks;
+  /* The blocks themselves.  */
+  struct block *block[1];
+};
+
+struct block
+{
+  /* Addresses in the executable code that are in this block.
+     Note: in an unrelocated symbol segment in a file,
+     these are always zero.  They can be filled in from the
+     N_LBRAC and N_RBRAC symbols in the loader symbol table.  */
+  CORE_ADDR startaddr, endaddr;
+  /* The symbol that names this block,
+     if the block is the body of a function;
+     otherwise, zero.
+     Note: In an unrelocated symbol segment in an object file,
+     this field may be zero even when the block has a name.
+     That is because the block is output before the name
+     (since the name resides in a higher block).
+     Since the symbol does point to the block (as its value),
+     it is possible to find the block and set its name properly.  */
+  struct symbol *function;
+  /* The `struct block' for the containing block, or 0 if none.  */
+  /* Note that in an unrelocated symbol segment in an object file
+     this pointer may be zero when the correct value should be
+     the second special block (for symbols whose scope is one compilation).
+     This is because the compiler ouptuts the special blocks at the
+     very end, after the other blocks.   */
+  struct block *superblock;
+  /* A flag indicating whether or not the fucntion corresponding
+     to this block was compiled with gcc or not.  If there is no
+     function corresponding to this block, this meaning of this flag
+     is undefined.  (In practice it will be 1 if the block was created
+     while processing a file compiled with gcc and 0 when not). */
+  unsigned char gcc_compile_flag;
+  /* Number of local symbols.  */
+  int nsyms;
+  /* The symbols.  */
+  struct symbol *sym[1];
+};
+\f
+/* Represent one symbol name; a variable, constant, function or typedef.  */
+
+/* Different name spaces for symbols.  Looking up a symbol specifies
+   a namespace and ignores symbol definitions in other name spaces.
+
+   VAR_NAMESPACE is the usual namespace.
+   In C, this contains variables, function names, typedef names
+   and enum type values.
+
+   STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
+   Thus, if `struct foo' is used in a C program,
+   it produces a symbol named `foo' in the STRUCT_NAMESPACE.
+
+   LABEL_NAMESPACE may be used for names of labels (for gotos);
+   currently it is not used and labels are not recorded at all.  */
+
+/* For a non-global symbol allocated statically,
+   the correct core address cannot be determined by the compiler.
+   The compiler puts an index number into the symbol's value field.
+   This index number can be matched with the "desc" field of
+   an entry in the loader symbol table.  */
+
+enum namespace
+{
+  UNDEF_NAMESPACE, VAR_NAMESPACE, STRUCT_NAMESPACE, LABEL_NAMESPACE,
+};
+
+/* An address-class says where to find the value of a symbol.  */
+
+enum address_class
+{
+  LOC_UNDEF,           /* Not used; catches errors */
+  LOC_CONST,           /* Value is constant int SYMBOL_VALUE, host byteorder */
+  LOC_STATIC,          /* Value is at fixed address SYMBOL_VALUE_ADDRESS */
+  LOC_REGISTER,                /* Value is in register */
+  LOC_ARG,             /* Value is at spec'd offset in arglist */
+  LOC_REF_ARG,         /* Value address is at spec'd offset in arglist. */
+  LOC_REGPARM,         /* Value is at spec'd offset in register window */
+  LOC_LOCAL,           /* Value is at spec'd offset in stack frame */
+  LOC_TYPEDEF,         /* Value not used; definition in SYMBOL_TYPE
+                          Symbols in the namespace STRUCT_NAMESPACE
+                          all have this class.  */
+  LOC_LABEL,           /* Value is address SYMBOL_VALUE_ADDRESS in the code */
+  LOC_BLOCK,           /* Value is address SYMBOL_VALUE_BLOCK of a
+                          `struct block'.  Function names have this class. */
+  LOC_EXTERNAL,                /* Value is at address SYMBOL_VALUE_ADDRESS not in
+                          this compilation.
+                          This is used only in psymtabs; in symtabs
+                          LOC_STATIC is used instead (since in that case
+                          we take the time to find the address).  */
+  LOC_CONST_BYTES,     /* Value is a constant byte-sequence pointed to by
+                          SYMBOL_VALUE_ADDRESS, in target byte order.  */
+  LOC_LOCAL_ARG,       /* Value is arg at spec'd offset in stack frame.
+                          Differs from LOC_LOCAL in that symbol is an
+                          argument; differs from LOC_ARG in that we find it
+                          in the frame (FRAME_LOCALS_ADDRESS), not in the
+                          arglist (FRAME_ARGS_ADDRESS).  Added for i960,
+                          which passes args in regs then copies to frame.  */
+};
+
+struct symbol
+{
+  /* Symbol name */
+  char *name;
+  /* Name space code.  */
+  enum namespace namespace;
+  /* Address class */
+  enum address_class class;
+  /* Data type of value */
+  struct type *type;
+
+  /* Line number of definition.  */
+  unsigned short line;
+  
+  /* constant value, or address if static, or register number,
+     or offset in arguments, or offset in stack frame.  All of
+     these are in host byte order (though what they point to might
+     be in target byte order, e.g. LOC_CONST_BYTES).  */
+  union
+    {
+      long value;              /* for LOC_CONST, LOC_REGISTER, LOC_ARG, 
+                                  LOC_REF_ARG, LOC_REGPARM, LOC_LOCAL */
+      struct block *block;      /* for LOC_BLOCK */
+      char *bytes;             /* for LOC_CONST_BYTES */
+      CORE_ADDR address;       /* for LOC_STATIC, LOC_LABEL, LOC_EXTERNAL */
+      struct symbol *chain;    /* for opaque typedef struct chain */
+    }
+  value;
+};
+
+
+/* A partial_symbol records the name, namespace, and address class of
+   symbols whose types we have not parsed yet.  For functions, it also
+   contains their memory address, so we can find them from a PC value.
+   Each partial_symbol sits in a partial_symtab, all of which are chained
+   on the partial_symtab_list and which points to the corresponding 
+   normal symtab once the partial_symtab has been referenced.  */
+
+struct partial_symbol
+{
+  /* Symbol name */
+  char *name;
+  /* Name space code.  */
+  enum namespace namespace;
+  /* Address class (for info_symbols) */
+  enum address_class class;
+  /* Value (only used for static functions currently).  Done this
+     way so that we can use the struct symbol macros.
+     Note that the address of a function is SYMBOL_VALUE_ADDRESS (pst)
+     in a partial symbol table, but BLOCK_START (SYMBOL_BLOCK_VALUE (st))
+     in a symbol table.  */
+  union
+    {
+      long value;
+      CORE_ADDR address;
+    }
+  value;
+};
+\f
+/* Source-file information.
+   This describes the relation between source files and line numbers
+   and addresses in the program text.  */
+
+struct sourcevector
+{
+  int length;                  /* Number of source files described */
+  struct source *source[1];    /* Descriptions of the files */
+};
+
+/* Each item represents a line-->pc (or the reverse) mapping.  This is
+   somewhat more wasteful of space than one might wish, but since only
+   the files which are actually debugged are read in to core, we don't
+   waste much space.
+
+   Each item used to be an int; either minus a line number, or a
+   program counter.  If it represents a line number, that is the line
+   described by the next program counter value.  If it is positive, it
+   is the program counter at which the code for the next line starts.  */
+
+struct linetable_entry
+{
+  int line;
+  CORE_ADDR pc;
+};
+
+struct linetable
+{
+  int nitems;
+  struct linetable_entry item[1];
+};
+
+/* All the information on one source file.  */
+
+struct source
+{
+  char *name;                  /* Name of file */
+  struct linetable contents;
+};
+
+/* Each source file is represented by a struct symtab. 
+   These objects are chained through the `next' field.  */
+
+struct symtab
+  {
+    /* Chain of all existing symtabs.  */
+    struct symtab *next;
+    /* List of all symbol scope blocks for this symtab.  */
+    struct blockvector *blockvector;
+    /* Table mapping core addresses to line numbers for this file.  */
+    struct linetable *linetable;
+    /* Vector containing all types defined for this symtab.  */
+    struct typevector *typevector;
+    /* Name of this source file.  */
+    char *filename;
+    /* Directory in which it was compiled, or NULL if we don't know.  */
+    char *dirname;
+    /* This component says how to free the data we point to:
+       free_contents => do a tree walk and free each object.
+       free_nothing => do nothing; some other symtab will free
+         the data this one uses.
+       free_linetable => free just the linetable.  */
+    enum free_code {free_nothing, free_contents, free_linetable}
+      free_code;
+    /* Pointer to one block of storage to be freed, if nonzero.  */
+    /* This is IN ADDITION to the action indicated by free_code.  */
+    char *free_ptr;
+    /* Total number of lines found in source file.  */
+    int nlines;
+    /* Array mapping line number to character position.  */
+    int *line_charpos;
+    /* Language of this source file.  */
+    enum language language;
+    /* String of version information.  May be zero.  */
+    char *version;
+    /* Full name of file as found by searching the source path.
+       0 if not yet known.  */
+    char *fullname;
+  };
+
+/* Each source file that has not been fully read in is represented by
+   a partial_symtab.  This contains the information on where in the
+   executable the debugging symbols for a specific file are, and a
+   list of names of global symbols which are located in this file.
+   They are all chained on partial_symtab_list.
+
+   Even after the source file has been read into a symtab, the
+   partial_symtab remains around.  They are allocated on an obstack,
+   psymbol_obstack.  FIXME, this is bad for dynamic linking or VxWorks-
+   style execution of a bunch of .o's.  */
+struct partial_symtab
+{
+  /* Chain of all existing partial symtabs.  */
+  struct partial_symtab *next;
+  /* Name of the source file which this partial_symtab defines */
+  char *filename;
+
+  /* Name of the symbol file from which symbols should be read.  */
+  char *symfile_name;
+  /* Address relative to which the symbols in this file are.  Need to
+     relocate by this amount when reading in symbols from the symbol
+     file.  */
+  CORE_ADDR addr;
+
+  /* Offset within loader symbol table of first local symbol for this
+     file and length (in bytes) of the section of the symbol table
+     devoted to this file's symbols (actually, the section bracketed
+     may contain more than just this files symbols
+     If ldsymlen is 0, the only reason for this things existence is
+     the dependency list below.  Nothing else will happen when it is
+     read in.  */
+  int ldsymoff, ldsymlen;
+  /* Range of text addresses covered by this file; texthigh is the
+     beginning of the next section. */
+  CORE_ADDR textlow, texthigh;
+  /* Array of pointers to all of the partial_symtab's which this one
+     depends on.  Since this array can only be set to previous or
+     the current (?) psymtab, this dependency tree is guaranteed not
+     to have any loops. */
+  struct partial_symtab **dependencies;
+  int number_of_dependencies;
+  /* Global symbol list.  This list will be sorted after readin to
+     improve access.  Binary search will be the usual method of
+     finding a symbol within it. globals_offset is an integer offset
+     within ps_globals */
+  int globals_offset, n_global_syms;
+  /* Static symbol list.  This list will *not* be sorted after readin;
+     to find a symbol in it, exhaustive search must be used.  This is
+     reasonable because searches through this list will eventually
+     lead to either the read in of a files symbols for real (assumed
+     to take a *lot* of time; check) or an error (and we don't care
+     how long errors take). */
+  int statics_offset, n_static_syms;
+  /* Pointer to symtab eventually allocated for this source file, 0 if
+     !readin or if we haven't looked for the symtab after it was readin.  */
+  struct symtab *symtab;
+  /* Pointer to function which will read in the symtab corresponding to
+     this psymtab.  */
+  void (*read_symtab) ();
+  /* Non-zero if the symtab corresponding to this psymtab has been
+     readin */
+  unsigned char readin;
+};
+
+/* A fast way to get from a psymtab to its symtab (after the first time).  */
+#define        PSYMTAB_TO_SYMTAB(pst)  ((pst)->symtab?                 \
+                                (pst)->symtab:                 \
+                                psymtab_to_symtab (pst) )
+
+/* This is the list of struct symtab's that gdb considers current.  */
+
+struct symtab *symtab_list;
+
+/* This is the list of struct partial_symtab's that gdb may need to access */
+
+struct partial_symtab *partial_symtab_list;
+
+/* This symtab variable specifies the current file for printing source lines */
+
+struct symtab *current_source_symtab;
+
+/* This is the next line to print for listing source lines.  */
+
+int current_source_line;
+
+#define BLOCKLIST(symtab) (symtab)->blockvector
+#define BLOCKVECTOR(symtab) (symtab)->blockvector
+
+#define TYPEVECTOR(symtab) (symtab)->typevector
+
+#define LINELIST(symtab) (symtab)->linetable
+#define LINETABLE(symtab) (symtab)->linetable
+\f
+/* Macros normally used to access components of symbol table structures.  */
+
+#define BLOCKLIST_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKLIST_BLOCK(blocklist,n) (blocklist)->block[n]
+#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
+
+#define TYPEVECTOR_NTYPES(typelist) (typelist)->length
+#define TYPEVECTOR_TYPE(typelist,n) (typelist)->type[n]
+
+#define BLOCK_START(bl) (bl)->startaddr
+#define BLOCK_END(bl) (bl)->endaddr
+#define BLOCK_NSYMS(bl) (bl)->nsyms
+#define BLOCK_SYM(bl, n) (bl)->sym[n]
+#define BLOCK_FUNCTION(bl) (bl)->function
+#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
+#define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag
+
+/* Nonzero if symbols of block BL should be sorted alphabetically.  */
+#define BLOCK_SHOULD_SORT(bl) ((bl)->nsyms >= 40)
+
+#define SYMBOL_NAME(symbol) (symbol)->name
+#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
+#define SYMBOL_CLASS(symbol) (symbol)->class
+#define SYMBOL_VALUE(symbol) (symbol)->value.value
+#define SYMBOL_VALUE_ADDRESS(symbol) (symbol)->value.address
+#define SYMBOL_VALUE_BYTES(symbol) (symbol)->value.bytes
+#define SYMBOL_BLOCK_VALUE(symbol) (symbol)->value.block
+#define SYMBOL_VALUE_CHAIN(symbol) (symbol)->value.chain
+#define SYMBOL_TYPE(symbol) (symbol)->type
+#define SYMBOL_LINE(symbol) (symbol)->line
+
+#define TYPE_NAME(thistype) (thistype)->name
+#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
+#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
+#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
+#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
+#define TYPE_MAIN_VARIANT(thistype) (thistype)->main_variant
+#define TYPE_NEXT_VARIANT(thistype) (thistype)->next_variant
+#define TYPE_LENGTH(thistype) (thistype)->length
+#define TYPE_FLAGS(thistype) (thistype)->flags
+#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
+#define TYPE_CODE(thistype) (thistype)->code
+#define TYPE_NFIELDS(thistype) (thistype)->nfields
+#define TYPE_FIELDS(thistype) (thistype)->fields
+/* C++ */
+#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
+#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
+#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
+#define TYPE_FN_FIELDS(thistype) (thistype)->fn_fields
+#define TYPE_NFN_FIELDS(thistype) (thistype)->nfn_fields
+#define TYPE_NFN_FIELDS_TOTAL(thistype) (thistype)->nfn_fields_total
+#define TYPE_ARG_TYPES(thistype) (thistype)->arg_types
+#define TYPE_BASECLASS(thistype,index) (thistype)->fields[index].type
+#define TYPE_N_BASECLASSES(thistype) (thistype)->n_baseclasses
+#define TYPE_BASECLASS_NAME(thistype,index) (thistype)->fields[index].name
+#define TYPE_BASECLASS_BITPOS(thistype,index) (thistype)->fields[index].bitpos
+#define BASETYPE_VIA_PUBLIC(thistype, index) (!TYPE_FIELD_PRIVATE(thistype, index))
+#define BASETYPE_VIA_VIRTUAL(thistype, index) B_TST((thistype)->virtual_field_bits, (index))
+
+#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
+#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
+#define TYPE_FIELD_NAME(thistype, n) (thistype)->fields[n].name
+#define TYPE_FIELD_VALUE(thistype, n) (* (int*) &(thistype)->fields[n].type)
+#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
+#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
+#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
+
+#define TYPE_FIELD_PRIVATE_BITS(thistype) (thistype)->private_field_bits
+#define TYPE_FIELD_PROTECTED_BITS(thistype) (thistype)->protected_field_bits
+#define TYPE_FIELD_VIRTUAL_BITS(thistype) (thistype)->virtual_field_bits
+#define SET_TYPE_FIELD_PRIVATE(thistype, n) B_SET ((thistype)->private_field_bits, (n))
+#define SET_TYPE_FIELD_PROTECTED(thistype, n) B_SET ((thistype)->protected_field_bits, (n))
+#define SET_TYPE_FIELD_VIRTUAL(thistype, n) B_SET ((thistype)->virtual_field_bits, (n))
+#define TYPE_FIELD_PRIVATE(thistype, n) B_TST((thistype)->private_field_bits, (n))
+#define TYPE_FIELD_PROTECTED(thistype, n) B_TST((thistype)->protected_field_bits, (n))
+#define TYPE_FIELD_VIRTUAL(thistype, n) B_TST((thistype)->virtual_field_bits, (n))
+
+#define TYPE_HAS_DESTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_DESTRUCTOR)
+#define TYPE_HAS_CONSTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_CONSTRUCTOR)
+
+#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1)
+#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize)
+
+#define TYPE_FN_FIELDLISTS(thistype) (thistype)->fn_fieldlists
+#define TYPE_FN_FIELDLIST(thistype, n) (thistype)->fn_fieldlists[n]
+#define TYPE_FN_FIELDLIST1(thistype, n) (thistype)->fn_fieldlists[n].fn_fields
+#define TYPE_FN_FIELDLIST_NAME(thistype, n) (thistype)->fn_fieldlists[n].name
+#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) (thistype)->fn_fieldlists[n].length
+
+#define TYPE_FN_FIELD(thistype, n) (thistype)[n]
+#define TYPE_FN_FIELD_NAME(thistype, n) (thistype)[n].name
+#define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type
+#define TYPE_FN_FIELD_ARGS(thistype, n) TYPE_ARG_TYPES ((thistype)[n].type)
+#define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname
+#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) ((thistype)[n].voffset > 0)
+#define TYPE_FN_FIELD_STATIC_P(thistype, n) ((thistype)[n].voffset == VOFFSET_STATIC)
+#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1)
+#define TYPE_FN_FIELD_FCONTEXT(thistype, n) ((thistype)[n].fcontext)
+
+#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits
+#define TYPE_FN_PROTECTED_BITS(thistype) (thistype).protected_fn_field_bits
+#define SET_TYPE_FN_PRIVATE(thistype, n) B_SET ((thistype).private_fn_field_bits, n)
+#define SET_TYPE_FN_PROTECTED(thistype, n) B_SET ((thistype).protected_fn_field_bits, n)
+#define TYPE_FN_PRIVATE(thistype, n) B_TST ((thistype).private_fn_field_bits, n)
+#define TYPE_FN_PROTECTED(thistype, n) B_TST ((thistype).protected_fn_field_bits, n)
+
+/* The virtual function table is now an array of structures
+   which have the form { int16 offset, delta; void *pfn; }. 
+   Gee, can we have more documentation than that?   FIXME.  -- gnu */
+  
+#define VTBL_FNADDR_OFFSET 2
+\f
+/* Functions that work on the objects described above */
+
+extern struct symtab *lookup_symtab ();
+extern struct symbol *lookup_symbol ();
+extern struct symbol *lookup_block_symbol ();
+extern int lookup_misc_func ();
+extern void check_stub_type ();
+extern void check_stub_method ();
+extern struct type *lookup_primitive_typename ();
+extern struct type *lookup_typename ();
+extern struct type *lookup_unsigned_typename ();
+extern struct type *lookup_struct ();
+extern struct type *lookup_union ();
+extern struct type *lookup_enum ();
+extern struct type *lookup_struct_elt_type ();
+extern struct type *lookup_pointer_type ();
+extern struct type *lookup_function_type ();
+extern struct type *lookup_basetype_type ();
+extern struct type *create_array_type ();
+extern struct symbol *block_function ();
+extern struct symbol *find_pc_function ();
+extern int find_pc_partial_function ();
+extern void clearpc_function_cache ();
+extern struct partial_symtab *lookup_partial_symtab ();
+extern struct partial_symtab *find_pc_psymtab ();
+extern struct symtab *find_pc_symtab ();
+extern struct partial_symbol *find_pc_psymbol ();
+extern int find_pc_misc_function ();
+extern int find_pc_line_pc_range ();
+extern char *type_name_no_tag ();
+extern int contained_in();
+
+/* C++ stuff.  */
+extern struct type *lookup_reference_type ();
+extern struct type *lookup_member_type ();
+extern struct type *lookup_class ();
+extern void smash_to_method_type ();
+/* end of C++ stuff.  */
+
+extern void free_all_symtabs ();
+extern void free_all_psymtabs ();
+extern void free_inclink_symtabs ();
+extern void reread_symbols ();
+
+extern struct type *builtin_type_void;
+extern struct type *builtin_type_char;
+extern struct type *builtin_type_short;
+extern struct type *builtin_type_int;
+extern struct type *builtin_type_long;
+extern struct type *builtin_type_unsigned_char;
+extern struct type *builtin_type_unsigned_short;
+extern struct type *builtin_type_unsigned_int;
+extern struct type *builtin_type_unsigned_long;
+extern struct type *builtin_type_float;
+extern struct type *builtin_type_double;
+/* This type represents a type that was unrecognized in symbol
+   read-in.  */
+extern struct type *builtin_type_error;
+
+#ifdef LONG_LONG
+extern struct type *builtin_type_long_long;
+extern struct type *builtin_type_unsigned_long_long;
+
+#define BUILTIN_TYPE_LONGEST builtin_type_long_long
+#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long_long
+/* This should not be a typedef, because "unsigned LONGEST" needs
+   to work.  */
+#define LONGEST long long
+
+#else /* not LONG_LONG.  */
+
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long
+#define LONGEST long
+
+#endif /* not LONG_LONG.  */
+
+struct symtab_and_line
+{
+  struct symtab *symtab;
+  int line;
+  CORE_ADDR pc;
+  CORE_ADDR end;
+};
+
+struct symtabs_and_lines
+{
+  struct symtab_and_line *sals;
+  int nelts;
+};
+
+/* Given a pc value, return line number it is in.
+   Second arg nonzero means if pc is on the boundary
+   use the previous statement's line number.  */
+
+struct symtab_and_line find_pc_line ();
+
+/* Given a symtab and line number, return the pc there.  */
+extern CORE_ADDR find_line_pc ();
+extern int find_line_pc_range ();
+
+/* Given a string, return the line specified by it.
+   For commands like "list" and "breakpoint".  */
+
+struct symtabs_and_lines decode_line_spec ();
+struct symtabs_and_lines decode_line_spec_1 ();
+struct symtabs_and_lines decode_line_1 ();
+
+/* Symbol-reading stuff in symfile.c and solib.c.  */
+struct symtab *psymtab_to_symtab ();
+void clear_solib ();
+void symbol_file_add ();
+
+/* source.c */
+int identify_source_line ();
+void print_source_lines ();
+
+char **make_symbol_completion_list ();
+
+/* The entry point of a file we are reading.  */
+extern CORE_ADDR entry_point;
+
+#endif /* symtab.h not already included.  */
diff --git a/gdb/target.c b/gdb/target.c
new file mode 100644 (file)
index 0000000..a58d0cd
--- /dev/null
@@ -0,0 +1,563 @@
+/* Select target systems and architectures at runtime for GDB.
+   Copyright (C) 1990 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include "defs.h"
+#include "target.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+
+extern int memory_insert_breakpoint(), memory_remove_breakpoint();
+extern void host_convert_to_virtual(), host_convert_from_virtual();
+
+static void cleanup_target ();
+
+/* Pointer to array of target architecture structures; the size of the
+   array; the current index into the array; the allocated size of the 
+   array.  */
+struct target_ops **target_structs;
+unsigned target_struct_size;
+unsigned target_struct_index;
+unsigned target_struct_allocsize;
+#define        DEFAULT_ALLOCSIZE       10
+
+/* The initial current target, so that there is always a semi-valid
+   current target.  */
+
+struct target_ops dummy_target = {"None", "None",
+    0, 0, 0, 0,                /* open, close, attach, detach */
+    0, 0,              /* resume, wait */
+    0, 0, 0, 0, 0,     /* registers */
+    0, 0,              /* memory */
+    0, 0,              /* bkpts */
+    0, 0, 0, 0, 0,     /* terminal */
+    0, 0, 0,           /* kill, load, add_syms */
+    0, 0,              /* call_function, lookup_symbol */
+    0, 0,              /* create_inferior, mourn_inferior */
+    dummy_stratum, 0,  /* stratum, next */
+    0, 0, 0, 0, 0,     /* all mem, mem, stack, regs, exec */
+    OPS_MAGIC,
+};
+
+/* The target structure we are currently using to talk to a process
+   or file or whatever "inferior" we have.  */
+
+struct target_ops *current_target;
+
+/* The stack of target structures that have been pushed.  */
+
+struct target_ops **current_target_stack;
+
+
+/* Add a possible target architecture to the list.  */
+
+void
+add_target (t)
+     struct target_ops *t;
+{
+  if (t->to_magic != OPS_MAGIC)
+    {
+      fprintf(stderr, "Magic number of %s target struct wrong\n", 
+       t->to_shortname);
+      abort();
+    }
+
+  if (!target_structs)
+    {
+      target_struct_allocsize = DEFAULT_ALLOCSIZE;
+      target_structs = (struct target_ops **) xmalloc
+       (target_struct_allocsize * sizeof (*target_structs));
+    }
+  if (target_struct_size >= target_struct_allocsize)
+    {
+      target_struct_allocsize *= 2;
+      target_structs = (struct target_ops **) xrealloc (target_structs, 
+       target_struct_allocsize * sizeof (*target_structs));
+    }
+  target_structs[target_struct_size++] = t;
+  cleanup_target (t);
+}
+
+/* Stub functions */
+
+static void
+ignore ()
+{
+}
+
+/* ARGSUSED */
+static int
+nomemory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  return 0;            /* No bytes handled */
+}
+
+static void
+tcomplain ()
+{
+  error ("You can't do that when your target is `%s'",
+        current_target->to_shortname);
+}
+
+static int
+noprocess ()
+{
+  error ("You can't do that without a process to debug");
+}
+
+static int
+nosymbol (name, addrp)
+     char *name;
+     CORE_ADDR *addrp;
+{
+  return 1;            /* Symbol does not exist in target env */
+}
+
+static void
+default_terminal_info (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  printf("No saved terminal information.\n");
+}
+
+#if 0
+/* With strata, this function is no longer needed.  FIXME.  */
+/* This is the default target_create_inferior function.  It looks up
+   the stack for some target that cares to create inferiors, then
+   calls it -- or complains if not found.  */
+
+static void
+upstack_create_inferior (exec, args, env)
+     char *exec;
+     char *args;
+     char **env;
+{
+  struct target_ops *t;
+
+  for (t = current_target;
+       t;
+       t = t->to_next)
+    {
+      if (t->to_create_inferior != upstack_create_inferior)
+       {
+          t->to_create_inferior (exec, args, env);
+         return;
+       }
+
+    }
+  tcomplain();
+}
+#endif
+
+/* This is the default target_create_inferior and target_attach function.
+   If the current target is executing, it asks whether to kill it off.
+   If this function returns without calling error(), it has killed off
+   the target, and the operation should be attempted.  */
+
+static void
+kill_or_be_killed (from_tty)
+     int from_tty;
+{
+  struct target_ops *savecur;
+
+  if (target_has_execution)
+    {
+      printf ("You are already running a program:\n");
+      target_files_info ();
+      if (query ("Kill it? ")) {
+       savecur = current_target;
+       target_kill (0, from_tty);
+       if (target_has_execution)
+         error ("Killing the program did not help.");
+       return;
+      } else {
+       error ("Program not killed.");
+      }
+    }
+  tcomplain();
+}
+
+static void
+maybe_kill_then_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  kill_or_be_killed (from_tty);
+  target_attach (args, from_tty);
+}
+
+static void
+maybe_kill_then_create_inferior (exec, args, env)
+     char *exec;
+     char *args;
+     char **env;
+{
+  kill_or_be_killed (0);
+  target_create_inferior (exec, args, env);
+}
+
+/* Clean up a target struct so it no longer has any zero pointers in it.
+   We default entries, at least to stubs that print error messages.  */
+
+static void
+cleanup_target (t)
+     struct target_ops *t;
+{
+
+  /* Check magic number.  If wrong, it probably means someone changed
+     the struct definition, but not all the places that initialize one.  */
+  if (t->to_magic != OPS_MAGIC)
+    {
+      fprintf(stderr, "Magic number of %s target struct wrong\n", 
+       t->to_shortname);
+      abort();
+    }
+
+#define de_fault(field, value) \
+  if (!t->field)       t->field = value
+
+  /*        FIELD                      DEFAULT VALUE        */
+
+  de_fault (to_open,                   tcomplain);
+  de_fault (to_close,                  (void (*)())ignore);
+  de_fault (to_attach,                         maybe_kill_then_attach);
+  de_fault (to_detach,                         (void (*)())ignore);
+  de_fault (to_resume,                         (void (*)())noprocess);
+  de_fault (to_wait,                   noprocess);
+  de_fault (to_fetch_registers,        noprocess);
+  de_fault (to_store_registers,                noprocess);
+  de_fault (to_prepare_to_store,       (void (*)())noprocess);
+  de_fault (to_convert_to_virtual,     host_convert_to_virtual);
+  de_fault (to_convert_from_virtual,   host_convert_from_virtual);
+  de_fault (to_xfer_memory,            nomemory);
+  de_fault (to_files_info,             ignore);
+  de_fault (to_insert_breakpoint,      memory_insert_breakpoint);
+  de_fault (to_remove_breakpoint,      memory_remove_breakpoint);
+  de_fault (to_terminal_init,          ignore);
+  de_fault (to_terminal_inferior,      ignore);
+  de_fault (to_terminal_ours_for_output,ignore);
+  de_fault (to_terminal_ours,          ignore);
+  de_fault (to_terminal_info,          default_terminal_info);
+  de_fault (to_kill,                   (void (*)())noprocess);
+  de_fault (to_load,                   tcomplain);
+  de_fault (to_add_syms,               tcomplain);
+  de_fault (to_call_function,          (struct value *(*)())noprocess);
+  de_fault (to_lookup_symbol,          nosymbol);
+  de_fault (to_create_inferior,                maybe_kill_then_create_inferior);
+  de_fault (to_mourn_inferior,         (void (*)())noprocess);
+  de_fault (to_next,                   0);
+  de_fault (to_has_all_memory,         0);
+  de_fault (to_has_memory,             0);
+  de_fault (to_has_stack,              0);
+  de_fault (to_has_registers,          0);
+  de_fault (to_has_execution,          0);
+
+#undef de_fault
+}
+
+/* Push a new target type into the stack of the existing target accessors,
+   possibly superseding some of the existing accessors.
+
+   Result is zero if the pushed target ended up on top of the stack,
+   nonzero if at least one target is on top of it.
+
+   Rather than allow an empty stack, we always have the dummy target at
+   the bottom stratum, so we can call the function vectors without
+   checking them.  */
+
+int
+push_target (t)
+     struct target_ops *t;
+{
+  struct target_ops *st, *prev;
+
+  for (prev = 0, st = current_target;
+       st;
+       prev = st, st = st->to_next) {
+    if ((int)(t->to_stratum) >= (int)(st->to_stratum))
+      break;
+  }
+
+  while (t->to_stratum == st->to_stratum) {
+    /* There's already something on this stratum.  Close it off.  */
+    (st->to_close) (0);
+    if (prev)
+      prev->to_next = st->to_next;     /* Unchain old target_ops */
+    else
+      current_target = st->to_next;    /* Unchain first on list */
+    st = st->to_next;
+  }
+
+  /* We have removed all targets in our stratum, now add ourself.  */
+  t->to_next = st;
+  if (prev)
+    prev->to_next = t;
+  else
+    current_target = t;
+
+  cleanup_target (current_target);
+  return prev != 0;
+}
+
+/* Remove a target_ops vector from the stack, wherever it may be. 
+   Return how many times it was removed (0 or 1 unless bug).  */
+
+int
+unpush_target (t)
+     struct target_ops *t;
+{
+  struct target_ops *u, *v;
+  int result = 0;
+
+  for (u = current_target, v = 0;
+       u;
+       v = u, u = u->to_next)
+    if (u == t)
+      {
+       if (v == 0)
+         pop_target();                 /* unchain top copy */
+       else {
+         (t->to_close)(0);             /* Let it clean up */
+         v->to_next = t->to_next;      /* unchain middle copy */
+       }
+       result++;
+      }
+  return result;
+}
+
+void
+pop_target ()
+{
+  (current_target->to_close)(0);       /* Let it clean up */
+  current_target = current_target->to_next;
+  if (!current_target)         /* At bottom, push dummy.  */
+    push_target (&dummy_target);
+}
+
+/* Print things about the whole set of targets and about the
+   current target stack.  */
+static void
+targets_info ()
+{
+  int i;
+
+  printf("Possible targets:\n\n");
+  for (i = 0; i < target_struct_size; i++)
+    printf ("%-15s %s\n",
+      target_structs[i]->to_shortname, 
+      target_structs[i]->to_longname);
+}
+
+/* Move memory to or from the targets.  Iterate until all of it has
+   been moved, if necessary.  The top target gets priority; anything
+   it doesn't want, is offered to the next one down, etc.  Note the
+   business with curlen:  if an early target says "no, but I have a
+   boundary overlapping this xfer" then we shorten what we offer to
+   the subsequent targets so the early guy will get a chance at the
+   tail before the subsequent ones do. 
+
+   Result is 0 or errno value.  */
+
+int
+target_read_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  return target_xfer_memory (memaddr, myaddr, len, 0);
+}
+
+int
+target_write_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  return target_xfer_memory (memaddr, myaddr, len, 1);
+}
+int
+target_xfer_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+  int curlen;
+  int res;
+  struct target_ops *t;
+  
+  /* The quick case is that the top target does it all.  */
+  res = current_target->to_xfer_memory(memaddr, myaddr, len, write);
+  if (res == len)
+    return 0;
+
+  if (res > 0)
+    goto bump;
+  /* If res <= 0 then we call it again in the loop.  Ah well.  */
+
+  for (; len > 0;)
+    {
+      curlen = len;            /* Want to do it all */
+      for (t = current_target;
+          t;
+          t = t->to_has_all_memory? 0: t->to_next)
+       {
+         res = t->to_xfer_memory(memaddr, myaddr, curlen, write);
+         if (res > 0) break;   /* Handled all or part of xfer */
+         if (res == 0) continue;       /* Handled none */
+         curlen = -res;        /* Could handle once we get past res bytes */
+       }
+      if (res <= 0)
+       {
+         /* If this address is for nonexistent memory,
+            read zeros if reading, or do nothing if writing.  Return error. */
+         if (!write)
+           bzero (myaddr, len);
+         return EIO;
+       }
+bump:
+      memaddr += res;
+      myaddr  += res;
+      len     -= res;
+    }
+  return 0;                    /* We managed to cover it all somehow. */
+}
+
+
+static void
+target_info (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  struct target_ops *t;
+  int has_all_mem = 0;
+  
+  if (symfile != 0)
+    printf ("Symbols from \"%s\".\n", symfile);
+
+#ifdef FILES_INFO_HOOK
+  if (FILES_INFO_HOOK ())
+    return;
+#endif
+
+  for (t = current_target;
+       t;
+       t = t->to_next)
+    {
+      if ((int)(t->to_stratum) <= (int)dummy_stratum)
+       continue;
+      if (has_all_mem)
+       printf("\tWhile running this, gdb does not access memory from...\n");
+      printf("%s:\n", t->to_longname);
+      (t->to_files_info)();
+      has_all_mem = t->to_has_all_memory;
+    }
+}
+
+/* The target command selects a target and calls its open routine.
+   The open routine takes the rest of the parameters from the command,
+   and (if successful) pushes a new target onto the stack.  */
+
+static void
+target_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  int i;
+  char *rest;
+
+  dont_repeat();
+
+  if (!args)
+    error (
+     "Argument required (target name).  `info targets' lists possible targets");
+
+  if (target_has_execution)
+    {   
+      if (query ("A program is being debugged already.  Kill it? "))
+        target_kill ((char *)0, from_tty);
+      else
+        error ("Program not killed.");
+    }
+        
+  /* Skip to first space, or end of args */
+  for (rest = args; *rest && !isspace(*rest); rest++) ;
+  if (*rest == '\0')
+    rest = 0;          /* Only one word in args */
+  else
+    {
+      *rest = '\0';    /* Terminate first word, scan for next */
+      for (rest++; isspace (*rest); rest++) ;
+      if (*rest == '\0')       /* Only one word w/trailing blanks */
+       rest = 0;
+    }
+
+  /* Search target list for a match */
+
+  for (i = 0; i < target_struct_size; i++)
+    {
+      if (!strcmp (args, target_structs[i]->to_shortname))
+       goto gotit;
+    }
+  error ("No such target.  `info targets' will list all targets");
+
+gotit:
+  (*target_structs[i]->to_open) (rest, from_tty);
+}
+
+static char targ_desc[] = 
+    "Names of targets and files being debugged.\n\
+Shows the entire stack of targets currently in use (including the exec-file,\n\
+core-file, and process, if any), as well as the symbol file name.";
+
+void
+_initialize_targets ()
+{
+  current_target = &dummy_target;
+  cleanup_target (current_target);
+
+  add_info ("targets", targets_info,
+    "Names of all possible targets.\n\
+A target is typically a protocol for talking to debugging facilities;\n\
+for example, `child' for Unix child processes, or `vxworks' for a\n\
+TCP/IP link to a VxWorks system.");
+
+  add_info ("target", target_info, targ_desc);
+  add_info ("files", target_info, targ_desc);
+
+  add_com ("target", class_run, target_command,
+"Connect to a target machine or process.\n\
+The first argument is the type or protocol of the target machine.  Remaining\n\
+arguments are interpreted by the target protocol, but typically include\n\
+things like device names or host names to connect with, process numbers,\n\
+baud rates, etc.  You can list all possible targets with the `info targets'\n\
+command.");
+}
diff --git a/gdb/target.h b/gdb/target.h
new file mode 100644 (file)
index 0000000..924f4aa
--- /dev/null
@@ -0,0 +1,406 @@
+/* Interface between GDB and target environments, including files and processes
+   Copyright 1990, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.  Written by John Gilmore.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This include file defines the interface between the main part
+   of the debugger, and the part which is target-specific, or
+   specific to the communications interface between us and the
+   target.
+
+   A TARGET is an interface between the debugger and a particular 
+   kind of file or process.  Targets can be STACKED in STRATA, 
+   so that more than one target can potentially respond to a request.
+   In particular, memory accesses will walk down the stack of targets
+   until they find a target that is interested in handling that particular
+   address.  STRATA are artificial boundaries on the stack, within
+   which particular kinds of targets live.  Strata exist so that
+   people don't get confused by pushing e.g. a process target and then
+   a file target, and wondering why they can't see the current values
+   of variables any more (the file target is handling them and they
+   never get to the process target).  So when you push a file target,
+   it goes into the file stratum, which is always below the process
+   stratum.  */
+
+enum strata {
+       dummy_stratum,          /* The lowest of the low */
+       file_stratum,           /* Executable files, etc */
+       core_stratum,           /* Core dump files */
+       process_stratum,        /* Executing processes */
+};
+
+struct target_ops {
+       char  *to_shortname;            /* Name this target type */
+       char  *to_longname;             /* Name for printing */
+#ifdef __STDC__
+       void (*to_open) (char *name, int from_tty);
+       void (*to_close) (int quitting);
+       void (*to_attach) (char *name, int from_tty);
+       void (*to_detach) (char *args, int from_tty);
+       void (*to_resume) (int step, int siggnal);
+       int  (*to_wait)   (int *status);
+       int  (*to_fetch_registers) (int regno);
+       int  (*to_store_registers) (int regno);
+       void (*to_prepare_to_store) ();
+       void (*to_convert_to_virtual) (int regnum, char *from, char *to);
+       void (*to_convert_from_virtual) (int regnum, char *from, char *to);
+       int  (*to_xfer_memory) (CORE_ADDR memaddr, char *myaddr, int len, int w);
+       void (*to_files_info) ();
+       int  (*to_insert_breakpoint) (CORE_ADDR addr, char *save);
+       int  (*to_remove_breakpoint) (CORE_ADDR addr, char *save);
+       void  (*to_terminal_init) ();
+       void  (*to_terminal_inferior) ();
+       void  (*to_terminal_ours_for_output) ();
+       void  (*to_terminal_ours) ();
+       void  (*to_terminal_info) (char *arg, int from_tty);
+       void  (*to_kill) (char *arg, int from_tty);
+       void  (*to_load) (char *arg, int from_tty);
+       void  (*to_add_syms) (char *arg, int from_tty);
+struct value *(*to_call_function) (struct value *function,
+                                  int nargs, struct value **args);
+       int   (*to_lookup_symbol) (char *name, CORE_ADDR *addrp);
+       void  (*to_create_inferior) (char *exec, char *args, char **env);
+       void  (*to_mourn_inferior) ();
+    enum strata to_stratum;
+struct target_ops *to_next;
+       int     to_has_all_memory;
+       int     to_has_memory;
+       int     to_has_stack;
+       int     to_has_registers;
+       int     to_has_execution;
+       int     to_magic;
+/* Need sub-structure for target machine related rather than comm related? */
+#else  /* STDC */
+       void (*to_open) ();
+       void (*to_close) ();
+       void (*to_attach) ();
+       void (*to_detach) ();
+       void (*to_resume) ();
+       int  (*to_wait)   ();
+       int  (*to_fetch_registers) ();
+       int  (*to_store_registers) ();
+       void (*to_prepare_to_store) ();
+       void (*to_convert_to_virtual) ();
+       void (*to_convert_from_virtual) ();
+       int  (*to_xfer_memory) ();
+       void (*to_files_info) ();
+       int  (*to_insert_breakpoint) ();
+       int  (*to_remove_breakpoint) ();
+       void  (*to_terminal_init) ();
+       void  (*to_terminal_inferior) ();
+       void  (*to_terminal_ours_for_output) ();
+       void  (*to_terminal_ours) ();
+       void  (*to_terminal_info) ();
+       void  (*to_kill) ();
+       void  (*to_load) ();
+       void  (*to_add_syms) ();
+struct value *(*to_call_function) ();
+       int   (*to_lookup_symbol) ();
+       void  (*to_create_inferior) ();
+       void  (*to_mourn_inferior) ();
+    enum strata to_stratum;
+struct target_ops *to_next;
+       int     to_has_all_memory;
+       int     to_has_memory;
+       int     to_has_stack;
+       int     to_has_registers;
+       int     to_has_execution;
+       int     to_magic;
+/* Need sub-structure for target machine related rather than comm related? */
+#endif
+};
+
+/* Magic number for checking ops size.  If a struct doesn't end with this
+   number, somebody changed the declaration but didn't change all the
+   places that initialize one.  */
+
+#define        OPS_MAGIC       3840
+
+/* The ops structure for our "current" target process.  */
+
+extern struct target_ops       *current_target;
+
+/* Define easy words for doing these operations on our current target.  */
+
+#define        target_shortname        (current_target->to_shortname)
+#define        target_longname         (current_target->to_longname)
+
+#define        target_open(name, from_tty)     \
+       (*current_target->to_open) (name, from_tty)
+
+/* Does whatever cleanup is required for a target that we are no longer
+   going to be calling.  Argument says whether we are quitting gdb and
+   should not get hung in case of errors, or whether we want a clean
+   termination even if it takes a while.  This routine is automatically
+   always called just before a routine is popped off the target stack.
+   Closing file descriptors and freeing memory are typical things it should
+   do.  */
+
+#define        target_close(quitting)  \
+       (*current_target->to_close) (quitting)
+
+/* Attaches to a process on the target side.  */
+
+#define        target_attach(args, from_tty)   \
+       (*current_target->to_attach) (args, from_tty)
+
+/* Takes a program previously attached to and detaches it.
+   The program may resume execution (some targets do, some don't) and will
+   no longer stop on signals, etc.  We better not have left any breakpoints
+   in the program or it'll die when it hits one.  ARGS is arguments
+   typed by the user (e.g. a signal to send the process).  FROM_TTY
+   says whether to be verbose or not.  */
+
+#define        target_detach(args, from_tty)           \
+       (*current_target->to_detach) (args, from_tty)
+
+/* Resume execution of the target process.  STEP says whether to single-step
+   or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
+   to the target, or zero for no signal.  */
+
+#define        target_resume(step, siggnal)    \
+       (*current_target->to_resume) (step, siggnal)
+
+/* Wait for inferior process to do something.  Return pid of child,
+   or -1 in case of error; store status through argument pointer STATUS.  */
+
+#define        target_wait(status)             \
+       (*current_target->to_wait) (status)
+
+/* Fetch register REGNO, or all regs if regno == -1.  Result is 0
+   for success, -1 for problems.  */
+
+#define        target_fetch_registers(regno)   \
+       (*current_target->to_fetch_registers) (regno)
+
+/* Store at least register REGNO, or all regs if REGNO == -1.
+   It can store as many registers as it wants to, so the entire registers
+   array must be valid.  Result is 0 for success, -1 for problems.  */
+
+#define        target_store_registers(regs)    \
+       (*current_target->to_store_registers) (regs)
+
+/* Get ready to modify the registers array.  On machines which store
+   individual registers, this doesn't need to do anything.  On machines
+   which store all the registers in one fell swoop, this makes sure
+   that REGISTERS contains all the registers from the program being
+   debugged.  */
+
+#define        target_prepare_to_store()       \
+       (*current_target->to_prepare_to_store) ()
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define        target_convert_to_virtual(regnum, from, to)     \
+       (*current_target->to_convert_to_virtual) (regnum, from, to)
+       
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define        target_convert_from_virtual(regnum, from, to)   \
+       (*current_target->to_convert_from_virtual) (regnum, from, to)
+
+/* Reading and writing memory actually happens through a glue
+   function which iterates across the various targets.  Result is
+   0 for success, or an errno value.  */
+
+#ifdef __STDC__
+/* Needs defs.h for CORE_ADDR */
+extern int target_read_memory(CORE_ADDR memaddr, char *myaddr, int len);
+extern int target_write_memory(CORE_ADDR memaddr, char *myaddr, int len);
+extern int target_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len,
+                             int write);
+#else
+extern int target_read_memory();
+extern int target_write_memory();
+extern int target_xfer_memory();
+#endif
+
+/* Print a line about the current target.  */
+
+#define        target_files_info()     \
+       (*current_target->to_files_info) ()
+
+/* Insert a breakpoint at address ADDR in the target machine.
+   SAVE is a pointer to memory allocated for saving the
+   target contents.  It is guaranteed by the caller to be long enough
+   to save "sizeof BREAKPOINT" bytes.  Result is 0 for success, or
+   an errno value.  */
+
+#define        target_insert_breakpoint(addr, save)    \
+       (*current_target->to_insert_breakpoint) (addr, save)
+
+/* Remove a breakpoint at address ADDR in the target machine.
+   SAVE is a pointer to the same save area 
+   that was previously passed to target_insert_breakpoint.  
+   Result is 0 for success, or an errno value.  */
+
+#define        target_remove_breakpoint(addr, save)    \
+       (*current_target->to_remove_breakpoint) (addr, save)
+
+/* Initialize the terminal settings we record for the inferior,
+   before we actually run the inferior.  */
+
+#define target_terminal_init() \
+       (*current_target->to_terminal_init) ()
+       
+/* Put the inferior's terminal settings into effect.
+   This is preparation for starting or resuming the inferior.  */
+
+#define target_terminal_inferior() \
+       (*current_target->to_terminal_inferior) ()
+
+/* Put some of our terminal settings into effect,
+   enough to get proper results from our output,
+   but do not change into or out of RAW mode
+   so that no input is discarded.
+
+   After doing this, either terminal_ours or terminal_inferior
+   should be called to get back to a normal state of affairs.  */
+
+#define target_terminal_ours_for_output() \
+       (*current_target->to_terminal_ours_for_output) ()
+
+/* Put our terminal settings into effect.
+   First record the inferior's terminal settings
+   so they can be restored properly later.  */
+
+#define target_terminal_ours() \
+       (*current_target->to_terminal_ours) ()
+
+/* Print useful information about our terminal status, if such a thing
+   exists.  */
+
+#define target_terminal_info(arg, from_tty) \
+       (*current_target->to_terminal_info) (arg, from_tty)
+
+/* Kill the inferior process.   Make it go away.  */
+
+#define target_kill(arg, from_tty) \
+       (*current_target->to_kill) (arg, from_tty)
+
+/* Load an executable file into the target process.  This is expected to
+   not only bring new code into the target process, but also to update
+   GDB's symbol tables to match.  */
+
+#define target_load(arg, from_tty) \
+       (*current_target->to_load) (arg, from_tty)
+
+/* Add the symbols from an executable file into GDB's symbol table, as if
+   the file had been loaded at a particular address (or set of addresses).
+   This does not change any state in the target system, only in GDB.  */
+
+#define target_add_syms(arg, from_tty) \
+       (*current_target->to_add_syms) (arg, from_tty)
+
+/* Perform a function call in the inferior.
+   ARGS is a vector of values of arguments (NARGS of them).
+   FUNCTION is a value, the function to be called.
+   Returns a value representing what the function returned.
+   May fail to return, if a breakpoint or signal is hit
+   during the execution of the function.  */
+
+#define target_call_function(function, nargs, args)    \
+  (*current_target->to_call_function) (function, nargs, args)
+
+/* Look up a symbol in the target's symbol table.  NAME is the symbol
+   name.  ADDRP is a CORE_ADDR * pointing to where the value of the symbol
+   should be returned.  The result is 0 if successful, nonzero if the
+   symbol does not exist in the target environment.  This function should
+   not call error() if communication with the target is interrupted, since
+   it is called from symbol reading, but should return nonzero, possibly
+   doing a complain().  */
+
+#define target_lookup_symbol(name, addrp)      \
+  (*current_target->to_lookup_symbol) (name, addrp)
+
+/* Start an inferior process and set inferior_pid to its pid.
+   EXEC_FILE is the file to run.
+   ALLARGS is a string containing the arguments to the program.
+   ENV is the environment vector to pass.  Errors reported with error().
+   On VxWorks and various standalone systems, we ignore exec_file.  */
+#define        target_create_inferior(exec_file, args, env)    \
+       (*current_target->to_create_inferior) (exec_file, args, env)
+
+/* The inferior process has died.  Do what is right.  */
+
+#define        target_mourn_inferior() \
+       (*current_target->to_mourn_inferior) ()
+
+/* Pointer to next target in the chain, e.g. a core file and an exec file.  */
+
+#define        target_next \
+       (current_target->to_next)
+
+/* Does the target include all of memory, or only part of it?  This
+   determines whether we look up the target chain for other parts of
+   memory if this target can't satisfy a request.  */
+
+#define        target_has_all_memory   \
+       (current_target->to_has_all_memory)
+
+/* Does the target include memory?  (Dummy targets don't.)  */
+
+#define        target_has_memory       \
+       (current_target->to_has_memory)
+
+/* Does the target have a stack?  (Exec files don't, VxWorks doesn't, until
+   we start a process.)  */
+   
+#define        target_has_stack        \
+       (current_target->to_has_stack)
+
+/* Does the target have registers?  (Exec files don't.)  */
+
+#define        target_has_registers    \
+       (current_target->to_has_registers)
+
+/* Does the target have execution?  Can we make it jump (through hoops),
+   or pop its stack a few times, or set breakpoints?  */
+
+#define        target_has_execution    \
+       (current_target->to_has_execution)
+
+/* Routines for maintenance of the target structures...
+
+   add_target:   Add a target to the list of all possible targets.
+
+   push_target:  Make this target the top of the stack of currently used
+                targets, within its particular stratum of the stack.  Result
+                is 0 if now atop the stack, nonzero if not on top (maybe
+                should warn user).
+
+   unpush_target: Remove this from the stack of currently used targets,
+                no matter where it is on the list.  Returns 0 if no
+                change, 1 if removed from stack.
+
+   pop_target:  Remove the top thing on the stack of current targets.  */
+
+#ifdef __STDC__
+void add_target (struct target_ops *);
+int push_target (struct target_ops *);
+int unpush_target (struct target_ops *);
+void pop_target ();
+#else
+void add_target ();
+int push_target ();
+int unpush_target ();
+void pop_target ();
+#endif
diff --git a/gdb/tdesc.c b/gdb/tdesc.c
new file mode 100755 (executable)
index 0000000..9a632e3
--- /dev/null
@@ -0,0 +1,1650 @@
+/* This file has been modified by Data General Corporation, November 1989. */
+
+/*
+This file provides an abstract interface to "tdesc" information.
+      It is designed to be used in a uniform manner by several kinds
+      of debuggers:
+         (1) code in live debugged process (e.g., a traceback routine)
+         (2) a separate-process debugger debugging a live process
+         (3) a separate-process debugger debugging a memory dump
+
+      Dcontext model notes
+         * captures machine context
+            * partial: excludes memory
+         * frames
+            * kinds
+         * make one for starters, chain in reverse order to previous ones
+         * representation: pointer to opaque
+            * alloc/free protocol
+
+      Overall model
+         * access functions
+         * handle
+         * error handling
+*/
+
+
+
+typedef int dc_boolean_t;   /* range 0 .. 1 */
+#define DC_FALSE 0
+#define DC_TRUE 1
+
+
+typedef int dc_tristate_t;  /* range 0 .. 2 */
+#define DC_NO 0
+#define DC_YES 1
+#define DC_MAYBE 2
+
+
+/*
+   A word is 32 bits of information.  In memory, a word is word-aligned.
+
+   A common and important use of dc_word_t is to represent values in the
+   target process, including (byte) addresses in the target process.
+   In this case, C arithmetic can be used to simulate machine address
+   arithmetic on the target.  (Unsigned arithmetic is actually modulus
+   arithmetic.)
+*/
+typedef unsigned int dc_word_t;
+
+
+/* These bit operations number bits from 0 at the least significant end. */
+#define bit_test(word,bit) ((word) & (1 << (bit)))    /* returns 0 or other */
+#define bit_value(word,bit) (((word) >> (bit)) & 1)   /* returns 0 or 1 */
+#define bit_set(word,bit) ((word) |= (1 << (bit)))
+#define bit_clear(word,bit) ((word) &= ~(1 << (bit)))
+#define bit_assign(word, bit, bool) \
+   if (bool) bit_set(word, bit); else bit_clear(word, bit)
+
+
+/*----------------*/
+
+
+/* The exactness of locations may not be certainly known. */
+typedef dc_tristate_t dc_exactness_t;
+
+
+/*
+   The model includes five kinds of contexts.  Because each context
+   has an associated region and frame, these describe region kinds
+   and frame kinds as well.
+   [more description needed]
+   Currently, only call contexts exist.
+*/
+
+typedef int dc_kind_t;   /* range 0 .. 4 */
+#define DC_CALL_KIND          0
+#define DC_SAVE_KIND          1
+#define DC_EXCEPTION_KIND     2
+#define DC_PROTECTION_KIND    3
+#define DC_SPECIAL_KIND       4
+#define DC_NUM_KINDS          5
+
+#define DC_MIO_ENTRY_POINT            (1<< 0)
+#define DC_MIO_PROLOGUE_END           (1<< 1)
+#define DC_MIO_EPILOGUE_START         (1<< 2)
+#define DC_MIO_IMPLICIT_PROLOGUE_END  (1<<16)
+#define DC_MIO_LITERAL_ENTRY_POINT    (1<<17)
+#define DC_MIO_LITERAL_EPILOGUE_START (1<<18)
+
+#define DC_MII_PRECEDING_TDESC_END   (1<<0)
+#define DC_MII_FOLLOWING_TDESC_START (1<<1)
+
+typedef struct dc_debug_info {
+   unsigned int         protocol;            /* 1 for this structure */
+   dc_word_t               tdesc_ptr;
+   unsigned int         text_words_count;
+   dc_word_t               text_words_ptr;
+   unsigned int         data_words_count;
+   dc_word_t               data_words_ptr;
+} dc_debug_info_t;
+
+
+typedef struct tdesc_hdr {
+   unsigned int         map_protocol;        /* 1 for this structure */
+   unsigned int         end;                 /* address beyond end */
+} tdesc_hdr_t;
+
+
+typedef struct tdesc_chunk_hdr {
+   int                  zeroes : 8;
+   int                  info_length : 22;
+   int                  info_alignment : 2;
+   unsigned int         info_protocol;
+   dc_word_t               start_address;
+   dc_word_t               end_address;
+} tdesc_chunk_hdr_t;
+
+
+typedef struct tdesc_chunk_info1 {
+   int                  variant : 8;         /* 1 for this structure */
+   int                  register_save_mask : 17;
+   int                  pad1 : 1;
+   int                  return_address_info_discriminant : 1;
+   int                  frame_address_register : 5;
+   unsigned int         frame_address_offset;
+   unsigned int         return_address_info;
+   unsigned int         register_save_offset;
+} tdesc_chunk_info1_t;
+
+
+typedef struct tdesc_chunk1 {
+   tdesc_chunk_hdr_t    hdr;
+   tdesc_chunk_info1_t  info;
+} tdesc_chunk1_t;
+
+
+typedef struct dc_mstate {
+   dc_word_t reg[32];                      /* general registers */
+   dc_word_t xip;
+   dc_word_t nip;
+   dc_word_t fip;
+   dc_word_t fpsr;
+   dc_word_t fpcr;
+   dc_word_t psr;
+} dc_mstate_t;
+
+
+typedef struct dc_map_info_in {
+   dc_word_t flags;
+   dc_word_t preceding_tdesc_end;
+   dc_word_t following_tdesc_start;
+} dc_map_info_in_t;
+
+
+typedef struct dc_map_info_out {
+   dc_word_t flags;
+   dc_word_t entry_point;
+   dc_word_t prologue_end;
+   dc_word_t epilogue_start;
+} dc_map_info_out_t;
+
+
+#if 0
+
+   void error_fcn (env, continuable, message)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_boolean_t continuable;            /* whether error function may return */
+      char *message;                    /* string (no trailing newline) */
+
+   /* In the future, we probably want the error_fcn to be: */
+   void error_fcn (env, continuable, code, ...)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_boolean_t continuable;            /* whether error function may return */
+      int code;                         /* error code */
+      ...                               /* parameters to message associated
+                                           with the code */
+
+   void read_fcn (env, memory, length, buffer)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_word_t memory;                    /* start address in image */
+      int length;                       /* in bytes */
+      char *buffer;                     /* start address of buffer */
+      /* There are no alignment assumptions for the read function. */
+
+   void write_fcn (env, memory, length, buffer)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_word_t memory;                    /* start address in image */
+      int length;                       /* in bytes */
+      char *buffer;                     /* start address of buffer */
+      /* There are no alignment assumptions for the write function. */
+      /* The write function is optional.  It must be provided if changes
+         to writable registers are to be made. */
+
+   void exec_fcn (env, mstate)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_mstate_t *mstate;              /* machine state (read-write) */
+      /* The execute function is optional.  It would be used (in the future)
+         by the implementation of a procedurally specified tdesc mechanism. */
+
+#endif
+
+/*----------------*/
+
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+extern char *malloc();
+extern char *calloc();
+extern void qsort();
+
+
+/*
+   At initialization, create a tdesc table from the tdesc info.
+   A tdesc table is simply a sorted array of tdesc elements.
+   A tdesc element is the last 6 words of the tdesc chunk.
+   We require that all tdesc chunks have info protocol 1.
+*/
+
+typedef struct tdesc_elem {
+   dc_word_t start_address;
+   dc_word_t end_address;
+   tdesc_chunk_info1_t info;
+} tdesc_elem_t;
+
+typedef tdesc_elem_t *tdesc_table_t;
+
+void dc_correct_cr_data();
+
+int dc_compare_tdesc_elems (elem1, elem2)
+   char *elem1, *elem2;
+{
+   dc_word_t s1, s2, e1, e2;
+   s1 = ((tdesc_elem_t *) elem1)->start_address;
+   s2 = ((tdesc_elem_t *) elem2)->start_address;
+   if (s1 < s2) return -1;
+   if (s1 > s2) return +1;
+   e1 = ((tdesc_elem_t *) elem1)->end_address;
+   e2 = ((tdesc_elem_t *) elem2)->end_address;
+   if (e1 < e2) return -1;
+   if (e1 > e2) return +1;
+   return 0;
+}
+
+
+typedef struct handle_info {
+   dc_word_t debug_info_ptr;
+   void (*error_fcn)();
+   dc_word_t error_env;
+   void (*read_fcn)();
+   dc_word_t read_env;
+   void (*write_fcn)();                 /* NULL => absent */
+   dc_word_t write_env;
+   void (*exec_fcn)();                  /* NULL => absent */
+   dc_word_t exec_env;
+   void (*map_fcn)();                  /* NULL => absent */
+   dc_word_t map_env;
+   tdesc_table_t tdesc_table;
+   int tdesc_table_size;
+} handle_info_t;
+
+typedef handle_info_t *dc_handle_t;
+
+
+/*
+   Errors detected in this module are funnelled through dc_error or dc_warn,
+   as appropriate.  Both routines call dc_exception, which invokes the error
+   handler supplied by the user.
+
+   Currently, dc_exception substitutes parameters into the message given
+   it and passes the resulting string to the user error handler.
+   In the future, dc_exception should simply pass an error code and
+   the parameters on to the user error handler.
+*/
+
+#include <varargs.h>
+extern int vsprintf();
+
+/* Exit status for exception-processing machinery failure */
+#define DC_EXCEPTION_FAILURE    250
+
+void dc_exception(continuable, args)
+   dc_boolean_t continuable;
+   va_list args;
+{
+   dc_handle_t handle;
+   char *format;
+   char buffer[1024];
+
+   handle = va_arg(args, dc_handle_t);
+   format = va_arg(args, char *);
+   (void) vsprintf(buffer, format, args);
+   (*(handle->error_fcn)) (handle->error_env, continuable, buffer);
+   if (!continuable)
+      exit(DC_EXCEPTION_FAILURE);  /* User error handler should never return in this case. */
+}
+
+
+void dc_error(va_alist)  /* (handle, format, args... ) */
+   va_dcl
+{
+   va_list args;
+
+   va_start(args);
+   dc_exception(DC_FALSE, args);
+   va_end(args);
+}
+
+
+void dc_warn(va_alist)  /* (handle, format, args... ) */
+   va_dcl
+{
+   va_list args;
+
+   va_start(args);
+   dc_exception(DC_TRUE, args);
+   va_end(args);
+}
+
+
+
+#define MALLOC_FAILURE_MESSAGE "Heap space exhausted (malloc failed)."
+#define CALLOC_FAILURE_MESSAGE "Heap space exhausted (Calloc failed)."
+
+
+/* Commonize memory allocation call so failure diagnosis is easier */
+
+char* dc_malloc( handle, size )
+    dc_handle_t handle;
+    int         size;
+{
+    char* space = malloc( size );
+    if (space == (char *)NULL)
+        dc_error( handle, MALLOC_FAILURE_MESSAGE );
+
+    return space;
+}
+
+
+/* Commonize memory allocation call so failure diagnosis is easier */
+
+char* dc_calloc( handle,nelem, size )
+    dc_handle_t handle;
+    int         nelem;
+    int                size;
+{
+    char* space = calloc( nelem, size );
+    if (space == (char *)NULL)
+        dc_error( handle, CALLOC_FAILURE_MESSAGE );
+
+    return space;
+}
+
+
+dc_word_t dc_read_word (handle, address)
+   dc_handle_t handle;
+   dc_word_t address;
+{
+   dc_word_t word;
+   (*(handle->read_fcn)) (handle->read_env, address,
+                          sizeof(dc_word_t), (char *)(&(word)));
+   return word;
+}
+
+
+void dc_write_word (handle, address, value)
+   dc_handle_t handle;
+   dc_word_t address;
+   dc_word_t value;
+{
+   dc_word_t word;
+   word = value;
+   if (handle->write_fcn) {
+      (*(handle->write_fcn)) (handle->write_env, address,
+                              sizeof(dc_word_t), (char *)(&(word)));
+   } else {
+      dc_error (handle, "Writing is disabled.");
+   }
+}
+
+
+void dc_write_masked_word (handle, address, mask, value)
+   dc_handle_t handle;
+   dc_word_t address;
+   dc_word_t mask;
+   dc_word_t value;
+{
+   dc_write_word (handle, address,
+      (value & mask) | (dc_read_word(handle, address) & ~mask));
+}
+
+
+dc_handle_t dc_initiate (debug_info_ptr,
+                        error_fcn, error_env,
+                         read_fcn, read_env,
+                         write_fcn, write_env,
+                         exec_fcn, exec_env,
+                         map_fcn, map_env)
+   dc_word_t debug_info_ptr;
+   void (*error_fcn)();
+   dc_word_t error_env;
+   void (*read_fcn)();
+   dc_word_t read_env;
+   void (*write_fcn)();                 /* NULL => absent */
+   dc_word_t write_env;
+   void (*exec_fcn)();                  /* NULL => absent */
+   dc_word_t exec_env;
+   void (*map_fcn)();                  /* NULL => absent */
+   dc_word_t map_env;
+   /* write_fcn may be given as NULL if no writing is required. */
+   /* exec_fcn may be given as NULL if no execution is required.
+      Currently, no execution is required.  It would be if the
+      implementation needed to invoke procedures in the debugged process. */
+{
+   dc_handle_t handle;
+   unsigned int debug_info_protocol;
+   dc_debug_info_t debug_info;
+   unsigned int tdesc_map_protocol;
+   tdesc_hdr_t tdesc_hdr;
+   dc_word_t tdesc_info_start;
+   dc_word_t tdesc_info_end;
+   dc_word_t tdesc_info_length;
+
+   /* Set up handle enough for dc_error. */
+   handle = (dc_handle_t) malloc(sizeof(handle_info_t));
+   /* Cant use dc_malloc() as handle is being created ... */
+   /* if (handle == NULL) (*error_fcn)( error_env, MALLOC_FAILURE_MESSAGE ) */
+   handle->error_fcn = error_fcn;
+   handle->error_env = error_env;
+   handle->read_fcn = read_fcn;
+   handle->read_env = read_env;
+   handle->write_fcn = write_fcn;
+   handle->write_env = write_env;
+   handle->exec_fcn = exec_fcn;
+   handle->exec_env = exec_env;
+/****************************************************************/
+/* BUG 9/19/89 Found by hls.  Map functions not initialized.    */
+/****************************************************************/
+   handle->map_fcn = map_fcn;
+   handle->map_env = map_env;
+   handle->debug_info_ptr = debug_info_ptr;
+   handle->tdesc_table = (tdesc_table_t)NULL;
+
+   /* Find tdesc info. */
+   if (debug_info_ptr) {
+      (*read_fcn) (read_env, debug_info_ptr, sizeof(unsigned int),
+                  (char *)(&debug_info_protocol));
+      if (debug_info_protocol != 1)
+        dc_error (handle, "Unrecognized debug info protocol: %d",
+                  debug_info_protocol);
+      (*read_fcn) (read_env, debug_info_ptr, sizeof(dc_debug_info_t),
+                  (char *)(&debug_info));
+      (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(unsigned int),
+                  (char *)(&tdesc_map_protocol));
+      if (tdesc_map_protocol != 1)
+        dc_error (handle, "Unrecognized tdesc map protocol: %d",
+                  tdesc_map_protocol);
+      (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(tdesc_hdr_t),
+                  (char *)(&tdesc_hdr));
+      tdesc_info_start = debug_info.tdesc_ptr + sizeof(tdesc_hdr_t);
+      tdesc_info_end = tdesc_hdr.end;
+      tdesc_info_length = tdesc_info_end - tdesc_info_start;
+
+      /* Create tdesc table from tdesc info. */
+      {
+        /* Over-allocate in order to avoid second pass over tdesc info. */
+        tdesc_table_t tt = (tdesc_table_t) dc_malloc(handle, tdesc_info_length);
+        dc_word_t p = tdesc_info_start;
+        dc_word_t q = tdesc_info_end - sizeof(tdesc_chunk1_t);
+        int n = 0;
+        tdesc_chunk1_t chunk;
+        dc_word_t start_address, end_address;
+        int i;
+
+        for (; p <= q; ) {
+           (*read_fcn) (read_env, p, sizeof(tdesc_chunk1_t), (char *)(&chunk));
+           if (chunk.hdr.zeroes != 0) {
+              /* Skip padding. */
+              p += sizeof(dc_word_t);
+              continue;
+           }
+           if (chunk.hdr.info_protocol != 1) {
+              dc_warn (handle, "Unrecognized tdesc info protocol: %d",
+                        chunk.hdr.info_protocol);
+              goto next_chunk;
+           }
+           if (chunk.hdr.info_length != 16) {
+              dc_warn (handle, "Incorrect tdesc info length: %d",
+                        chunk.hdr.info_length);
+              goto next_chunk;
+           }
+           if (chunk.hdr.info_alignment > 2) {
+              dc_warn (handle, "Incorrect tdesc info alignment: %d",
+                        chunk.hdr.info_alignment);
+              goto next_chunk;
+           }
+           start_address = chunk.hdr.start_address;
+           end_address = chunk.hdr.end_address;
+           if ((start_address&3)!=0) {
+              dc_warn (handle,
+                 "Tdesc start address is not word-aligned: %#.8X",
+                 start_address);
+              goto next_chunk;
+           }
+           if ((end_address&3)!=0) {
+              dc_warn (handle,
+                 "Tdesc end address is not word-aligned: %#.8X",
+                 end_address);
+              goto next_chunk;
+           }
+           if (start_address > end_address) {
+                    /* Note that the range may be null. */
+              dc_warn (handle,
+                 "Tdesc start address (%#.8X) follows end address (%#.8X).",
+                 start_address, end_address);
+              goto next_chunk;
+           }
+           if (chunk.info.variant != 1) {
+              dc_warn (handle, "Invalid tdesc chunk variant: %d",
+                 chunk.info.variant);
+              goto next_chunk;
+           }
+           if (chunk.info.pad1 != 0) {
+              dc_warn (handle, "Tdesc chunk padding is not zero.");
+              goto next_chunk;
+           }
+           if (chunk.info.return_address_info_discriminant != 0) {
+              if ((chunk.info.return_address_info & 3) != 0) {
+                 dc_warn (handle,
+                    "Tdesc return address offset is not word-aligned: %#.8X",
+                    chunk.info.return_address_info);
+                 goto next_chunk;
+              }
+           } else {
+              if ((chunk.info.return_address_info & ~31) != 0) {
+                 dc_warn (handle,
+                    "Invalid tdesc return address register: %d",
+                    chunk.info.return_address_info);
+                 goto next_chunk;
+              }
+           }
+           if ((chunk.info.register_save_offset & 3) != 0) {
+              dc_warn (handle,
+                 "Tdesc register save offset is not word-aligned: %#.8X",
+                 chunk.info.register_save_offset);
+              goto next_chunk;
+           }
+
+           tt[n].start_address = start_address;
+           tt[n].end_address = end_address;
+           tt[n].info = chunk.info;
+           n++;
+
+   next_chunk:
+           p += sizeof(tdesc_chunk1_t);
+        }
+        /* Leftover (less than a tdesc_chunk1_t in size) is padding or
+           in error.  Ignore it in either case. */
+
+        if (n != 0) {
+
+                /* Sort table by start address. */
+                qsort ((char *)tt, n, sizeof(tdesc_elem_t), dc_compare_tdesc_elems);
+
+                /* Check for overlap among tdesc chunks. */
+                for (i=0; i<(n-1); i++) {
+                   if (tt[i].end_address > tt[i+1].start_address)
+                      dc_error (handle, "Text chunks overlap.");
+                }
+        }
+
+        /* Finish setting up handle. */
+        handle->tdesc_table = tt;
+        handle->tdesc_table_size = n;
+      }
+   } else {
+      handle->tdesc_table_size = 0;
+   }
+
+   return (dc_handle_t) handle;
+}
+
+
+void dc_terminate (handle)
+   dc_handle_t handle;
+{
+   if (((dc_handle_t)handle)->tdesc_table) {
+      free((char *)(((dc_handle_t)handle)->tdesc_table));
+   }
+   free((char *)handle);
+}
+
+
+
+/*
+
+   Dcontext Model
+
+   For each interesting register (word-sized piece of machine state),
+   a word of value information is kept.  This word may
+   be either the value of the register, or the address in
+   subject memory where the value can be found (and changed).  In
+   addition, the register may be invalid (in which case the value
+   information is undefined).  These three cases are encoded for
+   a given register in the same-numbered bit of two words of flags:
+
+      flags[0] bit  flags[1] bit  meaning
+      ------------  ------------  -------
+            0             0       register is invalid; info is undefined
+            0             1       register is readable; info is value
+            1             0       register is writable; info is address
+            1             1       (reserved)
+
+   The general registers (r0-r31) are handled by reg_info and
+   reg_flags.  The bit number for a register is that register's number.
+   The other registers are grouped together for convenience and are
+   handled by aux_info and aux_flags.  The bit numbers for these
+   registers are:
+
+      bit number     register
+      ----------     --------
+           0         location
+           1         SXIP
+           2         SNIP
+           3         SFIP
+           4         FPSR
+           5         FPCR
+
+   The SXIP, SNIP, and SFIP are the exception-time values of the
+   XIP, NIP, and FIP registers.  They are valid only in the topmost frame.
+   (That is, in any context obtained from dc_previous_context, they
+   are invalid.)
+
+   "location" is a pseudo-register of this model and represents the
+   location of the context.  It is always valid.  It also has an
+   exactness associated with it.  The location and its exactness of a
+   context obtained from dc_previous_context are taken from the
+   return address and its exactness of the context given as an argument
+   to dc_previous_context.
+
+   The following model is recommended for dealing with the partial
+   redundancy between location and the SXIP, SNIP, and SFIP values
+   in the topmost frame.  The location should be set to either the
+   SNIP or SXIP value, and its exactness should be set to DC_NO.  A
+   change to the register whose value the location is set to should
+   be accompanied by an identical change to the location.
+
+   The PSR is handled separately, because it is a diverse collection
+   of flags.  The PSR, as a whole, is always valid.  A separate
+   psr_ind flag tells whether the psr_info data is a value or
+   an address.  Each bit of the PSR has its own pair of flag bits to
+   mark validity and writability.
+
+*/
+
+
+/* The following value means "other", because state is stored in 2 bits. */
+#define DC_RESERVED 3
+
+
+#define RSTATE(flags, bit) \
+   ((bit_value((flags)[0], bit) << 1) + bit_value((flags)[1], bit))
+
+#define REG_STATE(dcontext, reg) RSTATE(dcontext->reg_flags, reg)
+#define AUX_STATE(dcontext, reg) RSTATE(dcontext->aux_flags, reg)
+#define PSR_STATE(dcontext, reg) RSTATE(dcontext->psr_flags, reg)
+
+
+#define SET_INVALID(flags, bit) \
+   { bit_clear ((flags)[0], bit); bit_clear ((flags)[1], bit); }
+
+#define SET_READABLE(flags, bit) \
+   { bit_clear ((flags)[0], bit); bit_set   ((flags)[1], bit); }
+
+#define SET_WRITABLE(flags, bit) \
+   { bit_set   ((flags)[0], bit); bit_clear ((flags)[1], bit); }
+
+#define ASSIGN_RSTATE(to_flags, to_bit, from_flags, from_bit) \
+   { bit_assign ((to_flags)[0], to_bit, bit_value((from_flags)[0], from_bit));\
+     bit_assign ((to_flags)[1], to_bit, bit_value((from_flags)[1], from_bit));}
+
+
+#define CHECK_REG_READ(dcontext, reg) \
+   if (REG_STATE(dcontext, reg) == DC_INVALID) \
+      dc_error (dcontext->handle, \
+         "General register %d is not readable.", reg)
+
+#define CHECK_REG_WRITE(dcontext, reg) \
+   if (REG_STATE(dcontext, reg) != DC_WRITABLE) \
+      dc_error (dcontext->handle, \
+         "General register %d is not writable.", reg)
+
+#define CHECK_AUX_READ(dcontext, reg) \
+   if (AUX_STATE(dcontext, reg) == DC_INVALID) \
+      dc_error (dcontext->handle, \
+         "Auxiliary register %d is not readable.", reg)
+
+#define CHECK_AUX_WRITE(dcontext, reg) \
+   if (AUX_STATE(dcontext, reg) != DC_WRITABLE) \
+      dc_error (dcontext->handle, \
+         "Auxiliary register %d is not writable.", reg)
+
+
+
+#define DC_REG_RA   1
+#define DC_REG_FP  30
+#define DC_REG_SP  31
+#define DC_NUM_REG 32
+
+#define DC_AUX_LOC  0
+   /* DC_AUX_LOC must be first, with value 0 */
+#define DC_AUX_SXIP 1
+#define DC_AUX_SNIP 2
+#define DC_AUX_SFIP 3
+#define DC_AUX_FPSR 4
+#define DC_AUX_FPCR 5
+#define DC_NUM_AUX  6
+
+
+
+#define CHECK_REG(dcontext, reg) \
+   if ((reg < 0) || (reg >= DC_NUM_REG)) \
+      dc_error (dcontext->handle, \
+         "Bad general register number: %d", reg)
+
+#define CHECK_AUX(dcontext, reg) \
+   if ((reg < 1) || (reg >= DC_NUM_AUX)) \
+      dc_error (dcontext->handle, \
+         "Bad auxiliary register number: %d", reg)
+   /* CHECK_AUX is not used for location pseudo-register. */
+
+#define CHECK_BIT(dcontext, bit) \
+   if ((bit < 0) || (bit >= 32)) \
+      dc_error (dcontext->handle, \
+         "Bad bit number: %d", bit)
+
+
+
+typedef struct cr_value {
+   int reg;
+   unsigned int off;
+ } dc_cr_value_t;
+
+#define DC_UNDEF 32
+
+/*
+   A "dc_cr_value" represents an execution-time value symbolically, in
+   terms of the initial value of a register (the value on entry to
+   the procedure being analyzed) and a known offset.  A value with
+   a 'reg' field value of 0 through 31 represents the value obtained
+   by summing (using 32-bit modulus arithmetic) the initial value of
+   register 'reg' and the value 'off'.  Note that the value (0,k)
+   represents the constant value k, that (31,0) represents the CFA, and
+   that (1,0) represents the return address.  A value with a 'reg' field
+   of DC_UNDEF represents an indeterminable value; in this case the
+   'off' field is undefined.  Other values of 'reg' are erroneous.
+*/
+
+typedef struct cr_data {
+   dc_cr_value_t reg_val[DC_NUM_REG];
+   dc_word_t saved;
+   dc_word_t how;
+   unsigned int where[DC_NUM_REG];
+} dc_cr_data_t;
+
+/*
+   'cr_data' collects all the information needed to represent the
+   symbolic machine state during code reading.
+
+   The 'reg_val' array gives the current dc_cr_value for each register.
+   
+   The 'saved', 'how', and 'where' fields combine to describe what
+   registers have been saved, and where.  The 'saved' and 'how' fields
+   are implicitly bit arrays over 0..31, where the numbering is from
+   0 on the right.  (Hence, 1<<r gives the mask for register r.)
+   If saved[r] is 0, the register is not saved, and how[r] and where[r]
+   are undefined.  If saved[r] is 1, then how[r] tells whether register r
+   was saved in another register (how[r]==0) or in the frame (how[r]==1).
+   In the former case, where[r] gives the register number; in the latter
+   case, where[r] gives the frame position.
+*/
+
+
+typedef int dc_register_state_t;    /* range 0 to 2 */
+
+#define DC_INVALID  0
+#define DC_READABLE 1
+#define DC_WRITABLE 2
+
+
+
+
+typedef struct dcontext_info {
+   dc_handle_t handle;                     /* environment of context */
+   dc_word_t reg_info[DC_NUM_REG];
+   dc_word_t reg_flags[2];
+   dc_word_t aux_info[DC_NUM_AUX];
+   dc_word_t aux_flags[2];
+   dc_exactness_t loc_exact;
+   dc_word_t psr_info;                     /* value or address */
+   dc_word_t psr_ind;                      /* DC_TRUE iff address */
+   dc_word_t psr_flags[2];                 /* per-PSR-bit flags */
+   unsigned int code_reading;                 /* no tdesc therefore must read code*/
+        union {
+          tdesc_elem_t *tdesc_elem_ptr;       /* locates tdesc chunk */
+          dc_cr_data_t *cr_data_ptr;          /* or code reading data */
+        } info_ptr;
+} dcontext_info_t;
+
+typedef dcontext_info_t *dc_dcontext_t;
+
+dc_word_t dc_get_value (handle, info, flags, pos)
+   dc_handle_t handle;
+   dc_word_t info[];
+   dc_word_t flags[2];
+   int pos;
+   /* Assumes either DC_READABLE or DC_WRITABLE. */
+{
+   if (bit_test(flags[0], pos)) {
+      /* DC_WRITABLE case */
+      return dc_read_word(handle, info[pos]);
+   } else {
+      /* DC_READABLE case */
+      return info[pos];
+   }
+}
+
+void dc_set_value (handle, info, flags, pos, value)
+   dc_handle_t handle;
+   dc_word_t info[];
+   dc_word_t flags[2];
+   int pos;
+   dc_word_t value;
+   /* Assumes DC_WRITABLE. */
+{
+   dc_write_word(handle, info[pos], value);
+}
+
+
+#define GET_REG_VALUE(dcontext, reg) \
+   dc_get_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg)
+
+#define SET_REG_VALUE(dcontext, reg, value) \
+   dc_set_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg, \
+      value)
+
+#define GET_AUX_VALUE(dcontext, reg) \
+   dc_get_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg)
+
+#define SET_AUX_VALUE(dcontext, reg, value) \
+   dc_set_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg, \
+      value)
+
+
+
+void dc_check_dcontext (dc)
+   dc_dcontext_t dc;
+   /* Check consistency of information supplied to make a dcontext. */
+{
+   int i;
+
+   if ((REG_STATE(dc, 0) != DC_READABLE) || (dc->reg_info[0] != 0))
+      dc_error (dc->handle, "Register 0 is misspecified");
+   for (i = 1; i < DC_NUM_REG; i++)
+      if (REG_STATE(dc, i) == DC_RESERVED)
+         dc_error (dc->handle,
+            "State for general register %d is incorrect", i);
+   for (i = 0; i < DC_NUM_AUX; i++)
+      if (AUX_STATE(dc, i) == DC_RESERVED)
+         dc_error (dc->handle,
+            "State for auxiliary register %d is incorrect", i);
+   if (AUX_STATE(dc, DC_AUX_LOC) == DC_INVALID)
+      dc_error (dc->handle, "Location is specified as invalid");
+   if (GET_AUX_VALUE(dc, DC_AUX_LOC) == 0)
+      dc_error (dc->handle, "Location is zero.");
+   if (dc->loc_exact >= 3)
+      dc_error (dc->handle, "Location exactness is incorrectly specified: %d",
+         dc->loc_exact);
+   if (dc->psr_ind >= 2)
+      dc_error (dc->handle,
+         "PSR indirection flag is incorrectly specified: %d",
+         dc->psr_ind);
+   for (i = 0; i < 32; i++)
+      if (PSR_STATE(dc, i) == DC_RESERVED)
+         dc_error (dc->handle, "State for PSR bit %d is incorrect", i);
+}
+
+
+
+tdesc_elem_t * dc_tdesc_lookup (loc, tt, tt_size, map_info_in_ptr)
+   dc_word_t loc;
+   tdesc_table_t tt;
+   int tt_size;
+   dc_map_info_in_t *map_info_in_ptr;
+   /* Return address of tdesc_elem_t for given location, or NULL if
+      there is no tdesc chunk for the location.
+   */
+{
+   int l = 0;
+   int h = tt_size;
+   int m;
+
+   if (tt_size == 0) {
+      map_info_in_ptr->flags = 0;
+      return (tdesc_elem_t *)NULL;
+   }
+   for (;;) {
+      m = (l + h) / 2;
+      if (m == l) break;
+      if (loc >= tt[m].start_address)
+         l = m;
+      else
+         h = m;
+   }
+   if (loc >= tt[m].end_address) {
+      map_info_in_ptr->preceding_tdesc_end = tt[m].end_address;
+      if (m+1 < tt_size) {
+        map_info_in_ptr->following_tdesc_start = tt[m+1].start_address;
+        map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END |
+                                 DC_MII_FOLLOWING_TDESC_START;
+      } else {
+        map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END;
+      }
+      return (tdesc_elem_t *)NULL;
+   } else if (loc < tt[m].start_address) {
+      map_info_in_ptr->following_tdesc_start = tt[m].start_address;
+      map_info_in_ptr->flags = DC_MII_FOLLOWING_TDESC_START;
+      return (tdesc_elem_t *)NULL;
+   } else {
+      return (&tt[m]);
+   }
+}
+
+
+
+dc_dcontext_t dc_make_dcontext (handle,
+                                reg_info, reg_flags,
+                                aux_info, aux_flags, loc_exact,
+                                psr_info, psr_ind, psr_flags)
+   dc_handle_t handle;
+   dc_word_t reg_info[DC_NUM_REG];
+   dc_word_t reg_flags[2];
+   dc_word_t aux_info[DC_NUM_AUX];
+   dc_word_t aux_flags[2];
+   dc_exactness_t loc_exact;
+   dc_word_t psr_info;
+   dc_boolean_t psr_ind;
+   dc_word_t psr_flags[2];
+{
+   dc_dcontext_t dc = (dc_dcontext_t) dc_malloc (handle, sizeof(dcontext_info_t));
+   int i;
+   dc_map_info_in_t map_info_in;
+
+   /* Fill in supplied content. */
+   dc->handle = ((dc_handle_t)handle);
+   for (i = 0; i < DC_NUM_REG; i++) dc->reg_info[i]  = reg_info[i];
+   for (i = 0; i < 2; i++)       dc->reg_flags[i] = reg_flags[i];
+   for (i = 0; i < DC_NUM_AUX; i++) dc->aux_info[i]  = aux_info[i];
+   for (i = 0; i < 2; i++)       dc->aux_flags[i] = aux_flags[i];
+   dc->loc_exact = loc_exact;
+   dc->psr_info = psr_info;
+   dc->psr_ind = psr_ind;
+   for (i = 0; i < 2; i++)       dc->psr_flags[i] = psr_flags[i];
+
+   dc_check_dcontext(dc);
+
+   /* Find tdesc information for the text chunk. */
+   {
+/***************************************************************/
+/* BUG 8/16/89 Found by hls.  Not zeroing EV bits of location. */
+/*                            SHOULD USE dc_location()!        */
+/*      dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC);         */
+/***************************************************************/
+      dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC) & ~3;
+      tdesc_elem_t *tep =
+         dc_tdesc_lookup(loc, ((dc_handle_t)handle)->tdesc_table,
+             ((dc_handle_t)handle)->tdesc_table_size,&map_info_in);
+      if (tep) {
+                dc->code_reading = 0;
+         dc->info_ptr.tdesc_elem_ptr = tep;
+      } else {
+         dc->code_reading = 1;
+         if (!dc->handle->map_fcn) {
+             dc_error (dc->handle, "No tdesc information for %#.8X and no map function supplied.",loc);
+         }
+/****************************************************************/
+/* BUG 9/18/89 Found by hls.  Not using dc_malloc()             */
+/* dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)malloc(sizeof(dc_cr_data_t )); */
+/****************************************************************/
+         dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)dc_calloc(dc->handle,1,sizeof(dc_cr_data_t ));
+         dc_read_code(loc,dc,map_info_in,dc->info_ptr.cr_data_ptr);
+      }
+   }
+
+   return (dc_dcontext_t) dc;
+}
+
+
+
+void dc_free_dcontext (dcontext)
+   dc_dcontext_t dcontext;
+{
+/****************************************************************/
+/* BUG 9/19/89 Found by hls.  Freeing non-pointer value.        */
+/*       free((char *)dcontext->code_reading);                 */
+/****************************************************************/
+   if (dcontext->code_reading)
+         free((char *)dcontext->info_ptr.cr_data_ptr);
+   free((char *)dcontext);
+}
+
+
+
+dc_register_state_t dc_location_state (dcontext)
+   dc_dcontext_t dcontext;
+{
+   return AUX_STATE(((dc_dcontext_t)dcontext), DC_AUX_LOC);
+}
+
+
+dc_exactness_t dc_location_exactness (dcontext)
+   dc_dcontext_t dcontext;
+{
+   return ((dc_dcontext_t)dcontext)->loc_exact;
+}
+
+
+dc_word_t dc_location (dcontext)
+   dc_dcontext_t dcontext;
+   /* Return high 30 bits only. */
+{
+   /* Don't need: CHECK_AUX_READ (((dc_dcontext_t)dcontext), DC_AUX_LOC); */
+   return GET_AUX_VALUE (((dc_dcontext_t)dcontext), DC_AUX_LOC) & ~3;
+}
+
+
+dc_boolean_t dc_location_in_text_chunk( dcontext, value )
+   dc_dcontext_t dcontext;
+   dc_word_t value;
+{
+   /* Check that new location is still within same text chunk. */
+   tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+/********************************************************************/
+/* Bug in predicate -- LS adjusted according to OCS documentation.. */
+/*  if ((value < tep->start_address) || (value >= tep->end_address))*/
+/********************************************************************/
+   if ((value >= tep->start_address) && (value < tep->end_address))
+        return DC_TRUE;
+    else
+        return DC_FALSE;
+
+}
+
+
+void dc_set_location (dcontext, value)
+   dc_dcontext_t dcontext;
+   dc_word_t value;
+   /* Set high 30 bits only. */
+{
+   if (dc_location_in_text_chunk( dcontext, value ) != DC_TRUE)
+      dc_warn (((dc_dcontext_t)dcontext)->handle,
+         "New location is not in same text chunk.");
+
+   CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), DC_AUX_LOC);
+   dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+      ((dc_dcontext_t)dcontext)->aux_info[DC_AUX_LOC], ~3, value);
+}
+
+
+
+dc_register_state_t dc_general_register_state (dcontext, reg)
+   dc_dcontext_t dcontext;
+   int reg;
+{
+   CHECK_REG (((dc_dcontext_t)dcontext), reg);
+   return REG_STATE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+dc_word_t dc_general_register (dcontext, reg)
+   dc_dcontext_t dcontext;
+   int reg;
+{
+   CHECK_REG (((dc_dcontext_t)dcontext), reg);
+   CHECK_REG_READ (((dc_dcontext_t)dcontext), reg);
+   return GET_REG_VALUE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+void dc_set_general_register (dcontext, reg, value)
+   dc_dcontext_t dcontext;
+   int reg;
+   dc_word_t value;
+{
+   CHECK_REG (((dc_dcontext_t)dcontext), reg);
+   CHECK_REG_WRITE (((dc_dcontext_t)dcontext), reg);
+   SET_REG_VALUE (((dc_dcontext_t)dcontext), reg, value);
+}
+
+
+
+dc_register_state_t dc_auxiliary_register_state (dcontext, reg)
+   dc_dcontext_t dcontext;
+   int reg;
+{
+   CHECK_AUX (((dc_dcontext_t)dcontext), reg);
+   return AUX_STATE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+dc_word_t dc_auxiliary_register (dcontext, reg)
+   dc_dcontext_t dcontext;
+   int reg;
+{
+   CHECK_AUX (((dc_dcontext_t)dcontext), reg);
+   CHECK_AUX_READ (((dc_dcontext_t)dcontext), reg);
+   return GET_AUX_VALUE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+void dc_set_auxiliary_register (dcontext, reg, value)
+   dc_dcontext_t dcontext;
+   int reg;
+   dc_word_t value;
+{
+   CHECK_AUX (((dc_dcontext_t)dcontext), reg);
+   CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), reg);
+   SET_AUX_VALUE (((dc_dcontext_t)dcontext), reg, value);
+}
+
+
+
+dc_register_state_t dc_psr_register_bit_state (dcontext, bit)
+   dc_dcontext_t dcontext;
+   int bit;
+{
+   CHECK_BIT (((dc_dcontext_t)dcontext), bit);
+   return PSR_STATE(((dc_dcontext_t)dcontext), bit);
+}
+
+
+dc_word_t dc_psr_register (dcontext)
+   dc_dcontext_t dcontext;
+{
+   if (((dc_dcontext_t)dcontext)->psr_ind) {
+      return dc_read_word(((dc_dcontext_t)dcontext)->handle,
+                       ((dc_dcontext_t)dcontext)->psr_info);
+   } else {
+      return ((dc_dcontext_t)dcontext)->psr_info;
+   }
+}
+
+
+void dc_set_psr_register (dcontext, mask, value)
+   dc_dcontext_t dcontext;
+   dc_word_t mask;
+   dc_word_t value;
+   /* Set bits of PSR corresponding to 1 bits in mask. */
+{
+   if (((dc_dcontext_t)dcontext)->psr_ind) {
+      if (((((dc_dcontext_t)dcontext)->psr_flags[0] & mask) != mask) ||
+          ((((dc_dcontext_t)dcontext)->psr_flags[1] & mask) != 0))
+         dc_error (((dc_dcontext_t)dcontext)->handle,
+            "Some PSR bits specified are not writable.");
+      dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+                         ((dc_dcontext_t)dcontext)->psr_info, mask, value);
+   } else {
+      dc_error (((dc_dcontext_t)dcontext)->handle, "PSR is not writable.");
+   }
+}
+
+
+
+dc_word_t dc_frame_address (dcontext)
+   dc_dcontext_t dcontext;
+{
+  if (!dcontext->code_reading) {
+        tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+        return dc_general_register(dcontext,
+               tep->info.frame_address_register) + tep->info.frame_address_offset;
+  } else {
+        if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].reg == DC_REG_SP) {
+               return (dc_general_register(dcontext,DC_REG_FP)
+                       - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].off);
+        }
+        if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].reg == DC_REG_SP) {
+               return (dc_general_register(dcontext,DC_REG_SP)
+                       - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].off);
+        }
+     dc_error (((dc_dcontext_t)dcontext)->handle, "Cannot locate frame pointer.");
+  }
+}
+
+
+
+dc_kind_t dc_context_kind (dcontext)
+   dc_dcontext_t dcontext;
+{
+   return DC_CALL_KIND;
+}
+
+
+
+
+/* operations valid for call contexts only */
+
+
+dc_register_state_t dc_return_address_state (dcontext)
+   dc_dcontext_t dcontext;
+{
+   tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+   int reg;
+
+   if (!dcontext->code_reading) {
+         if (tep->info.return_address_info_discriminant) {
+                return DC_WRITABLE;
+         } else {
+                return REG_STATE(((dc_dcontext_t)dcontext), tep->info.return_address_info);
+         }
+   } else {
+         reg= DC_REG_RA;
+         if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
+               if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
+                  return DC_WRITABLE;
+               } else {
+                  reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
+               }
+         }
+               return REG_STATE(((dc_dcontext_t)dcontext),reg);
+
+         
+   }
+}
+
+
+dc_exactness_t dc_return_address_exactness (dcontext)
+   dc_dcontext_t dcontext;
+{
+   return DC_MAYBE;
+}
+
+
+dc_word_t dc_return_address (dcontext)
+   dc_dcontext_t dcontext;
+   /* Return high 30 bits only. */
+{
+   tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+   dc_word_t rai = tep->info.return_address_info;
+   dc_word_t val;
+   int reg;
+
+   if (!dcontext->code_reading) {
+        if (tep->info.return_address_info_discriminant) {
+               val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
+                                                dc_frame_address(dcontext) + rai);
+        } else {
+               val = dc_general_register (dcontext, rai);
+        }
+   } else {
+         reg=DC_REG_RA;
+         if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,reg)) {
+                 if (bit_test(dcontext->info_ptr.cr_data_ptr->how,reg)) {
+                        val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
+                                                  dc_frame_address(dcontext) + 
+                                                   (dcontext->info_ptr.cr_data_ptr->where[reg]));
+                 } else {
+                        reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
+                        val = dc_general_register (dcontext, reg);
+                 }
+         } else {
+                val = dc_general_register (dcontext, reg);
+         }
+   }
+        return val & ~3;
+}
+
+
+void dc_set_return_address (dcontext, value)
+   dc_dcontext_t dcontext;
+   dc_word_t value;
+   /* Set high 30 bits only. */
+{
+  if (!dcontext->code_reading) {
+        tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+        dc_word_t rai = tep->info.return_address_info;
+
+        if (tep->info.return_address_info_discriminant) {
+               dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+                  dc_frame_address(dcontext) + rai, ~3, value);
+        } else {
+      dc_set_general_register (dcontext, rai,
+         (value & ~3) | (dc_general_register(dcontext, rai) & 3));
+   }
+ } else {
+       if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
+               if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
+                  dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+                     dc_frame_address(dcontext)
+                          + dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA], ~3, value);
+                 } else {
+                        dc_set_general_register( dcontext,
+                                                                 dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
+                 }
+         } else {
+                 dc_set_general_register( dcontext,
+                                                         dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
+         }
+   }
+}
+
+
+
+/* operations valid for save contexts only */
+
+/* (none) */
+
+
+
+/* operations valid for exception contexts only */
+
+
+void dc_get_exception_info (dcontext, handler, datum)
+   dc_dcontext_t dcontext;
+   dc_word_t *handler;
+   dc_word_t *datum;
+{
+   dc_error (((dc_dcontext_t)dcontext)->handle,
+      "dc_get_exception_info is not yet implemented.");
+}
+
+
+
+/* operations valid for protection contexts only */
+
+
+void dc_get_protection_info (dcontext, handler, datum)
+   dc_dcontext_t dcontext;
+   dc_word_t *handler;
+   dc_word_t *datum;
+{
+   dc_error (((dc_dcontext_t)dcontext)->handle,
+      "dc_get_protection_info is not yet implemented.");
+}
+
+
+
+/* operations valid for special contexts only */
+
+
+void dc_get_special_info (dcontext, kind, datum)
+   dc_dcontext_t dcontext;
+   dc_word_t *kind;
+   dc_word_t *datum;
+{
+   dc_error (((dc_dcontext_t)dcontext)->handle,
+      "dc_get_special_info is not yet implemented.");
+}
+
+
+
+/* operations valid for all contexts (again) */
+
+
+dc_dcontext_t dc_previous_dcontext (dcontext)
+   dc_dcontext_t dcontext;
+   /* Return NULL if there is no previous context. */
+{
+   dc_dcontext_t old = (dc_dcontext_t) dcontext;
+   dcontext_info_t new;    /* to serve as temporary storage only */
+   tdesc_elem_t *tep;
+       dc_cr_data_t *cdp;
+   dc_word_t cfa;
+   int rsm;
+   dc_word_t offset;
+   dc_word_t rai;
+   int r;
+
+   if (dc_return_address_state((dc_dcontext_t)old) == DC_INVALID)
+      dc_error (old->handle, "Return address is invalid.");
+
+   if (dc_return_address((dc_dcontext_t)old) == 0)
+      return (dc_dcontext_t)NULL;  /* end of the chain */
+
+   /* Copy over old contents. */
+   new = *old;
+
+   cfa = dc_frame_address(old);
+       /* Restore stack pointer. */
+       new.reg_info[DC_REG_SP] = cfa;
+       SET_READABLE (new.reg_flags, DC_REG_SP);
+
+   /* Invalidate temporary registers. */
+   for (r = 1; r <= 13; r++) SET_INVALID (new.reg_flags, r);
+
+       if (!old->code_reading) {
+               tep = old->info_ptr.tdesc_elem_ptr;
+               /* Restore preserved registers. */
+               rsm = tep->info.register_save_mask;
+               offset = cfa + tep->info.register_save_offset;
+               for (r = 14; r <= 30; r++) {
+                       if (bit_test(rsm, 30-r)) {
+                               new.reg_info[r] = offset;
+                               SET_WRITABLE (new.reg_flags, r);
+                               offset += sizeof(dc_word_t);
+                       }
+               }
+
+               /* Set location from old return address. */
+               rai = tep->info.return_address_info;
+               if (tep->info.return_address_info_discriminant) {
+                       new.aux_info[DC_AUX_LOC] = cfa + rai;
+                       SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
+               } else {
+                       new.aux_info[DC_AUX_LOC] = old->reg_info[rai];
+                       ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC, old->reg_flags, rai);
+               }
+       } else {
+               cdp = old->info_ptr.cr_data_ptr;
+               
+               /* Restore preserved registers. */
+               for (r = 14; r <= 30; r++) { 
+                       if (bit_test(cdp->saved,r)) {
+                               if (bit_test(cdp->how,r)){ /* saved in the frame */
+                                       new.reg_info[r] = cfa+cdp->where[r];
+                                       SET_WRITABLE (new.reg_flags, r);
+                               } else { /* saved in the in a register */
+                                       new.reg_info[r] = dc_general_register(old,cdp->where[r]);
+                                       ASSIGN_RSTATE (new.aux_flags, r, old->reg_flags, cdp->where[r]);
+                               }
+                       }  /* not saved, therefore, already valid , no else*/
+               }
+
+               /* Set location from old return address. */
+               if (bit_test(cdp->saved,DC_REG_RA)) {
+                       if (bit_test(cdp->how,DC_REG_RA)){ /* saved in the frame */
+                               new.aux_info[DC_AUX_LOC] = 
+                                       new.reg_info[DC_REG_RA] = cfa+cdp->where[DC_REG_RA];
+                               SET_WRITABLE (new.reg_flags, DC_REG_RA);
+                               SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
+                       } else { /* saved in the in a register */
+                               new.reg_info[DC_REG_RA] =
+                                       new.aux_info[DC_AUX_LOC] =
+                                                       dc_general_register(old,cdp->where[DC_REG_RA]);
+                               ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC, 
+                                                                       old->reg_flags, cdp->where[DC_REG_RA]);
+                       }
+               } else { /* not saved, therefore, already valid , set DC_AUX_LOC only*/
+                               new.aux_info[DC_AUX_LOC] =
+                                               dc_general_register(old,DC_REG_RA);
+                               ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC, 
+                                                                       old->reg_flags, DC_REG_RA);
+               }
+       }
+
+   /* Invalidate instruction pointers. */
+   SET_INVALID (new.aux_flags, DC_AUX_SXIP);
+   SET_INVALID (new.aux_flags, DC_AUX_SNIP);
+   SET_INVALID (new.aux_flags, DC_AUX_SFIP);
+
+   /* No change to FCR registers. */
+
+   /* No change to PSR register. */
+
+   return dc_make_dcontext ((dc_handle_t)new.handle,
+                            new.reg_info, new.reg_flags,
+                            new.aux_info, new.aux_flags, new.loc_exact,
+                            new.psr_info, new.psr_ind, new.psr_flags);
+}
+
+
+
+/* extensions for nonlocal goto */
+
+#if 0
+
+typedef
+   struct label {
+      ???
+   } label_t;
+
+
+label_t dc_make_label (dcontext, location)
+   dc_dcontext_t dcontext;
+   dc_word_t location;
+{
+}
+
+#endif
+
+/* procedure for reading code */
+
+dc_read_code(loc,dc,map_info_in,cdp)
+dc_word_t loc;
+dc_dcontext_t dc;
+dc_cr_data_t *cdp;
+dc_map_info_in_t map_info_in;
+{
+dc_map_info_out_t map_info_out;
+dc_word_t pc;
+dc_boolean_t found_branch=DC_FALSE;
+dc_word_t instr;
+
+       (*dc->handle->map_fcn)(dc->handle->map_env,loc,map_info_in,&map_info_out);
+       if (map_info_out.flags & DC_MIO_ENTRY_POINT 
+               && (!(map_info_in.flags & DC_MII_PRECEDING_TDESC_END)
+                   || map_info_out.entry_point >= map_info_in.preceding_tdesc_end
+                       || map_info_out.flags & DC_MIO_LITERAL_ENTRY_POINT)) {
+          dc_init_cr_data(cdp,(tdesc_elem_t *)NULL);
+          pc= map_info_out.entry_point;
+       } else if (map_info_in.flags & DC_MII_PRECEDING_TDESC_END) { 
+               /**/
+               /* tdesc_lookup gets the tep for the preceeding tdesc information
+               /* so we call it with one less than the preceding tdesc end since
+               /* tdesc information is exclusive of the ending address
+               /**/
+          dc_init_cr_data(cdp, 
+                                          dc_tdesc_lookup(map_info_in.preceding_tdesc_end-1, 
+                                                                       ((dc_handle_t)dc->handle)->tdesc_table,
+                                                       ((dc_handle_t)dc->handle)->tdesc_table_size,
+                                                                       &map_info_in));
+          pc= map_info_in.preceding_tdesc_end;
+       } else {
+      dc_error (dc->handle, "Insufficient information for code reading.");
+       }
+       for (;;pc+=4) {
+               if (pc==loc) {
+                  return (DC_TRUE);
+               }
+               instr= dc_read_word(dc->handle,pc);
+               found_branch= dc_decode_finds_branch(dc,instr);
+               if ((map_info_out.flags & DC_MIO_PROLOGUE_END) 
+                         && (pc==map_info_out.prologue_end)) {
+                       break;
+               }
+               if (found_branch) {
+                       if (DC_MIO_IMPLICIT_PROLOGUE_END & map_info_out.flags) {
+                               break;
+                       } else {
+                       dc_error (dc->handle, "Found branch before end of prologue.");
+                       }
+               }
+       }
+       if (!(map_info_out.flags & DC_MIO_LITERAL_EPILOGUE_START)
+                && (map_info_out.epilogue_start >= loc 
+                               || !(map_info_out.flags & DC_MIO_EPILOGUE_START))) {
+               return (DC_TRUE);
+       }
+       dc_correct_cr_data(cdp,dc->handle);
+       for (pc=map_info_out.epilogue_start;pc<loc;pc+=4) {
+               instr= dc_read_word(dc->handle,pc);
+               if (dc_decode_finds_branch(dc,instr)) {
+                       return (DC_FALSE);
+               }
+       }
+       return (DC_TRUE);
+
+}
+
+
+
+dc_init_cr_data(cdp,tep)
+dc_cr_data_t *cdp;
+tdesc_elem_t *tep;
+{
+int reg;
+dc_word_t rai;
+dc_word_t raid;
+dc_word_t rsm;
+dc_word_t frpos;
+
+       if (tep){
+
+          /* Start off with all registers undefined and none saved. */
+          for (reg = 0; reg < DC_NUM_REG; reg++) {
+                 cdp->reg_val[reg].reg = DC_UNDEF;
+          }
+          cdp->saved = 0;
+
+          /* Overwrite with what tdesc element says. */
+
+          cdp->reg_val[tep->info.frame_address_register].reg = DC_REG_SP;
+          cdp->reg_val[tep->info.frame_address_register].off =
+                                 - tep->info.frame_address_offset;
+
+          rai = tep->info.return_address_info;
+          raid = tep->info.return_address_info_discriminant;
+          if (raid || rai != DC_REG_RA) {
+                 bit_set(cdp->saved,DC_REG_RA);
+                 bit_assign(cdp->how,DC_REG_RA,raid);
+                 cdp->where[DC_REG_RA] = rai;
+          }
+
+          rsm = tep->info.register_save_mask;
+          frpos = tep->info.register_save_offset;
+          for (reg = 14; reg <= 30; reg++) {
+                       if (bit_test(rsm, 30-reg)) {
+                               bit_set(cdp->saved,reg);
+                               bit_set(cdp->how,reg);
+                               cdp->where[reg] = frpos;
+                               frpos += sizeof(dc_word_t);
+                       } else {
+                                       cdp->reg_val[reg].reg = reg;
+                                       cdp->reg_val[reg].off = 0;
+                       }
+          }
+
+          cdp->reg_val[0].reg = 0;   /* guarantee what hardware does */
+          cdp->reg_val[0].off = 0;
+
+       } else {
+          /* Each register has its own initial value. */
+          for (reg = 0; reg < DC_NUM_REG; reg++) {
+                 cdp->reg_val[reg].reg = reg;
+                 cdp->reg_val[reg].off = 0;
+          }
+   /* No register is yet saved. */
+   cdp->saved = 0;
+   cdp->how = 0;
+       }
+}
+void dc_correct_cr_data(cdp,handle)
+dc_cr_data_t *cdp;
+dc_handle_t handle;
+{
+long sr,r;
+dc_word_t save_regs = 0;  /* registers used to save others */
+   for (r = 1; r < DC_REG_SP; r++) {
+      if (bit_test(cdp->saved,r) && !bit_test(cdp->how,r)) {
+         sr = cdp->where[r];
+         if (bit_test(save_regs,sr)) {
+            dc_error(handle, "Same register used to save two others.");
+        }
+         bit_set(save_regs,sr);
+      }
+   }
+   for (r = 1; r < DC_REG_FP; r++) {
+      if ((r < 14 || bit_test(cdp->saved,r)) && !bit_test(save_regs,r)) {
+         cdp->reg_val[r].reg = DC_UNDEF;
+      }
+   }
+   if (bit_test(cdp->saved,DC_REG_FP) &&
+       cdp->reg_val[DC_REG_FP].reg == DC_REG_SP) {  /* is r30 the far? */
+      cdp->reg_val[DC_REG_SP].reg = DC_UNDEF;  /* trash sp */
+   } else if (cdp->reg_val[DC_REG_SP].reg == DC_REG_SP) { /* is r31 the far? */
+      if (bit_test(cdp->saved,DC_REG_FP) && !bit_test(save_regs,DC_REG_FP)) {
+         cdp->reg_val[DC_REG_FP].reg = DC_UNDEF;  /* trash r30 */
+      }
+   }
+}
diff --git a/gdb/tdesc.h b/gdb/tdesc.h
new file mode 100755 (executable)
index 0000000..3936330
--- /dev/null
@@ -0,0 +1,329 @@
+/* This file has been modified by Data General Corporation, November 1989. */
+
+#ifndef _tdesc_h
+#define _tdesc_h
+#ifdef __STDC__ 
+#define _ARGS(x)       x
+#else
+#define _ARGS(x)       ()
+#endif
+
+/*
+      This file provides an abstract interface to "tdesc" information.
+      It is designed to be used in a uniform manner by several kinds
+      of debuggers:
+         (1) code in live debugged process (e.g., a traceback routine)
+         (2) a separate-process debugger debugging a live process
+         (3) a separate-process debugger debugging a memory dump
+
+      Dcontext model notes
+         * captures machine context
+            * partial: excludes memory
+         * frames
+            * kinds
+         * make one for starters, chain in reverse order to previous ones
+         * representation: pointer to opaque
+            * alloc/free protocol
+
+      Overall model
+         * access functions
+         * handle
+         * error handling
+*/
+
+
+
+typedef int dc_boolean_t;   /* range 0 .. 1 */
+#define DC_FALSE 0
+#define DC_TRUE 1
+
+
+typedef int dc_tristate_t;  /* range 0 .. 2 */
+#define DC_NO 0
+#define DC_YES 1
+#define DC_MAYBE 2
+
+
+#define DC_MII_PRECEDING_TDESC_END   (1<<0)
+#define DC_MII_FOLLOWING_TDESC_START (1<<1)
+
+#define DC_MIO_ENTRY_POINT            (1<< 0)
+#define DC_MIO_PROLOGUE_END           (1<< 1)
+#define DC_MIO_EPILOGUE_START         (1<< 2)
+#define DC_MIO_IMPLICIT_PROLOGUE_END  (1<<16)
+#define DC_MIO_LITERAL_ENTRY_POINT    (1<<17)
+#define DC_MIO_LITERAL_EPILOGUE_START (1<<18)
+
+
+/*
+   A word is 32 bits of information.  In memory, a word is word-aligned.
+
+   A common and important use of word_t is to represent values in the
+   target process, including (byte) addresses in the target process.
+   In this case, C arithmetic can be used to simulate machine address
+   arithmetic on the target.  (Unsigned arithmetic is actually modulus
+   arithmetic.)
+*/
+typedef unsigned int dc_word_t;
+
+
+/*----------------*/
+
+
+/* The exactness of locations may not be certainly known. */
+typedef dc_tristate_t dc_exactness_t;
+
+
+/*
+   The model includes five kinds of contexts.  Because each context
+   has an associated region and frame, these describe region kinds
+   and frame kinds as well.
+   [more description needed]
+   Currently, only call contexts exist.
+*/
+
+typedef int dc_kind_t;   /* range 0 .. 4 */
+#define DC_CALL_KIND          0
+#define DC_SAVE_KIND          1
+#define DC_EXCEPTION_KIND     2
+#define DC_PROTECTION_KIND    3
+#define DC_SPECIAL_KIND       4
+#define DC_NUM_KINDS          5
+
+
+typedef struct dc_debug_info {
+   unsigned int            protocol;            /* 1 for this structure */
+   dc_word_t               tdesc_ptr;
+   unsigned int            text_words_count;
+   dc_word_t               text_words_ptr;
+   unsigned int            data_words_count;
+   dc_word_t               data_words_ptr;
+} dc_debug_info_t;
+
+
+typedef struct dc_mstate {
+   dc_word_t reg[32];                      /* general registers */
+   dc_word_t xip;
+   dc_word_t nip;
+   dc_word_t fip;
+   dc_word_t fpsr;
+   dc_word_t fpcr;
+   dc_word_t psr;
+} dc_mstate_t;
+
+
+
+#if 0
+
+   void error_fcn (env, continuable, message)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      boolean_t continuable;            /* whether error function may return */
+      char *message;                    /* string (no trailing newline) */
+
+   /* In the future, we probably want the error_fcn to be: */
+   void error_fcn (env, continuable, code, ...)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      boolean_t continuable;            /* whether error function may return */
+      int code;                         /* error code */
+      ...                               /* parameters to message associated
+                                           with the code */
+
+   void read_fcn (env, memory, length, buffer)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_word_t memory;                    /* start address in image */
+      int length;                       /* in bytes */
+      char *buffer;                     /* start address of buffer */
+      /* There are no alignment assumptions for the read function. */
+
+   void write_fcn (env, memory, length, buffer)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_word_t memory;                    /* start address in image */
+      int length;                       /* in bytes */
+      char *buffer;                     /* start address of buffer */
+      /* There are no alignment assumptions for the write function. */
+      /* The write function is optional.  It must be provided if changes
+         to writable registers are to be made. */
+
+   void exec_fcn (env, mstate)
+      dc_word_t env;                       /* environment (arbitrary datum) */
+      dc_mstate_t *mstate;              /* machine state (read-write) */
+      /* The execute function is optional.  It would be used (in the future)
+         by the implementation of a procedurally specified tdesc mechanism. */
+
+#endif
+
+/*----------------*/
+
+
+typedef struct dc_map_info_in {
+   dc_word_t flags;
+   dc_word_t preceding_tdesc_end;
+   dc_word_t following_tdesc_start;
+} dc_map_info_in_t;
+
+
+typedef struct dc_map_info_out {
+   dc_word_t flags;
+   dc_word_t entry_point;
+   dc_word_t prologue_end;
+   dc_word_t epilogue_start;
+} dc_map_info_out_t;
+
+
+typedef void *dc_handle_t;
+
+typedef void (*tdesc_error_fcn_type) _ARGS((
+      dc_word_t env,                   /* environment (arbitrary datum) */
+      dc_boolean_t continuable,        /* whether error function may return */
+      const char *message              /* string (no trailing newline) */
+));
+typedef void (*tdesc_io_fcn_type) _ARGS((
+      dc_word_t env,                       /* environment (arbitrary datum) */
+      dc_word_t memory,                    /* start address in image */
+      int length,                       /* in bytes */
+      void *buffer                     /* start address of buffer */
+));
+typedef void (*tdesc_exec_fcn_type) _ARGS((
+      dc_word_t env,                       /* environment (arbitrary datum) */
+      dc_mstate_t *mstate              /* machine state (read-write) */
+));
+typedef void (*tdesc_map_fcn_type) _ARGS((
+      dc_word_t map_env,
+      dc_word_t loc,
+      dc_map_info_in_t map_info_in,
+      dc_map_info_out_t *map_info_out
+));
+
+
+extern dc_handle_t dc_initiate _ARGS((
+   dc_word_t debug_info_ptr,
+   tdesc_error_fcn_type error_fcn,
+   dc_word_t error_env,
+   tdesc_io_fcn_type read_fcn,
+   dc_word_t read_env,
+   tdesc_io_fcn_type write_fcn, /* NULL => absent */
+   dc_word_t write_env,
+   tdesc_exec_fcn_type exec_fcn, /* NULL => absent */
+   dc_word_t exec_env,
+   tdesc_map_fcn_type map_fcn, /* NULL => absent */
+   dc_word_t map_env
+));
+extern void dc_terminate _ARGS((
+   dc_handle_t handle
+));
+
+typedef int dc_register_state_t;    /* range 0 to 2 */
+
+#define DC_INVALID  0
+#define DC_READABLE 1
+#define DC_WRITABLE 2
+
+#define DC_NUM_REG 32
+
+#define DC_AUX_LOC  0
+#define DC_AUX_SXIP 1
+#define DC_AUX_SNIP 2
+#define DC_AUX_SFIP 3
+#define DC_AUX_FPSR 4
+#define DC_AUX_FPCR 5
+#define DC_NUM_AUX  6
+
+
+typedef void *dc_dcontext_t;
+
+extern dc_dcontext_t dc_make_dcontext _ARGS((
+   dc_handle_t handle,
+   dc_word_t reg_info[DC_NUM_REG],
+   dc_word_t reg_flags[2],
+   dc_word_t aux_info[DC_NUM_AUX],
+   dc_word_t aux_flags[2],
+   dc_exactness_t loc_exact,
+   dc_word_t psr_info,
+   dc_boolean_t psr_ind,
+   dc_word_t psr_flags[2]
+));
+extern void dc_free_dcontext _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_register_state_t dc_location_state _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_exactness_t dc_location_exactness _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_word_t dc_location _ARGS((
+   dc_dcontext_t dcontext
+));
+extern void dc_set_location _ARGS((
+   dc_dcontext_t dcontext,
+   dc_word_t value
+));
+extern dc_register_state_t dc_general_register_state _ARGS((
+   dc_dcontext_t dcontext,
+   int reg
+));
+extern dc_word_t dc_general_register _ARGS((
+   dc_dcontext_t dcontext,
+   int reg
+));
+extern void dc_set_general_register _ARGS((
+   dc_dcontext_t dcontext,
+   int reg,
+   dc_word_t value
+));
+extern dc_register_state_t dc_auxiliary_register_state _ARGS((
+   dc_dcontext_t dcontext,
+   int reg
+));
+extern dc_word_t dc_auxiliary_register _ARGS((
+   dc_dcontext_t dcontext,
+   int reg
+));
+extern void dc_set_auxiliary_register _ARGS((
+   dc_dcontext_t dcontext,
+   int reg,
+   dc_word_t value
+));
+extern dc_register_state_t dc_psr_register_bit_state _ARGS((
+   dc_dcontext_t dcontext,
+   int bit
+));
+extern dc_word_t dc_psr_register _ARGS((
+   dc_dcontext_t dcontext
+));
+extern void dc_set_psr_register _ARGS((
+   dc_dcontext_t dcontext,
+   dc_word_t mask,
+   dc_word_t value
+));
+extern dc_word_t dc_frame_address _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_kind_t dc_context_kind _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_register_state_t dc_return_address_state _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_exactness_t dc_return_address_exactness _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_word_t dc_return_address _ARGS((
+   dc_dcontext_t dcontext
+));
+extern void dc_set_return_address _ARGS((
+   dc_dcontext_t dcontext,
+   dc_word_t value
+));
+extern void dc_get_exception_info();
+extern void dc_get_protection_info();
+extern void dc_get_special_info();
+extern dc_dcontext_t dc_previous_dcontext _ARGS((
+   dc_dcontext_t dcontext
+));
+extern dc_boolean_t dc_location_in_text_chunk _ARGS((
+   dc_dcontext_t dcontext,
+   dc_word_t value
+));
+
+#endif
diff --git a/gdb/terminal.h b/gdb/terminal.h
new file mode 100644 (file)
index 0000000..4658c7a
--- /dev/null
@@ -0,0 +1,50 @@
+/* Terminal interface definitions for GDB, the GNU Debugger.
+   Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Define a common set of macros -- BSD based -- and redefine whatever
+   the system offers to make it look like that.  */
+
+#ifdef HAVE_TERMIO
+
+#include <termio.h>
+
+#undef TIOCGETP
+#define TIOCGETP TCGETA
+#undef TIOCSETN
+#define TIOCSETN TCSETA
+#undef TIOCSETP
+#define TIOCSETP TCSETAF
+#define TERMINAL struct termio
+
+#ifdef NO_JOB_CONTROL
+# undef TIOCGPGRP
+# undef TIOCGPGRP
+#endif
+
+#else /* no termio */
+
+#include <fcntl.h>
+#include <sgtty.h>
+#include <sys/ioctl.h>
+#define TERMINAL struct sgttyb
+
+#endif /* no termio */
+
+extern void new_tty ();
diff --git a/gdb/tm-29k.h b/gdb/tm-29k.h
new file mode 100644 (file)
index 0000000..4594622
--- /dev/null
@@ -0,0 +1,653 @@
+/* Parameters for target machine of AMD 29000, for GDB, the GNU debugger.
+   Copyright 1990, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.  Written by Jim Kingdon.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Parameters for an EB29K (a board which plugs into a PC and is
+   accessed through EBMON software running on the PC, which we
+   use as we'd use a remote stub (see remote-eb.c).
+
+   If gdb is ported to other 29k machines/systems, the
+   machine/system-specific parts should be removed from this file (a
+   la tm-68k.h).  */
+
+/* Byte order is configurable, but this machine runs big-endian.  */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Floating point uses IEEE representations.  */
+#define IEEE_FLOAT
+
+/* We can either use a.out, encapsulated, or can use COFF */
+#ifndef COFF_ENCAPSULATE
+#define COFF_FORMAT
+/* This just has to do with what coff header files are in use.  */
+#define COFF_CHECK_X_ZEROES
+#endif
+
+/* Recognize our magic number.  */
+#define BADMAG(x) ((x)->f_magic != 0572)
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc) \
+  { pc = skip_prologue (pc); }
+CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_register (LR0_REGNUM))
+
+/* I'm not sure about the exact value of this, but based on looking
+   at the stack pointer when we get to main this seems to be right.
+
+   This is the register stack; We call it "CONTROL" in GDB for consistency
+   with Pyramid.  */
+#define CONTROL_END_ADDR 0x80200000
+
+/* Memory stack.  This is for the default register stack size, which is
+   only 0x800 bytes.  Perhaps we should let the user specify stack sizes
+   (and tell EBMON with the "ZS" command).  */
+#define STACK_END_ADDR 0x801ff800
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Stack must be aligned on 32-bit word boundaries.  */
+#define STACK_ALIGN(ADDR) (((ADDR) + 3) & ~3)
+
+/* Sequence of bytes for breakpoint instruction.  */
+/* ASNEQ 0x50, gr1, gr1
+   The trap number 0x50 is chosen arbitrarily.  */
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BREAKPOINT {0x72, 0x50, 0x01, 0x01}
+#else /* Target is little-endian.  */
+#define BREAKPOINT {0x01, 0x01, 0x50, 0x72}
+#endif /* Target is little-endian.  */
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 4
+
+/* Nonzero if instruction at PC is a return instruction.
+   On the 29k, this is a "jmpi l0" instruction.  */
+
+#define ABOUT_TO_RETURN(pc) \
+  ((read_memory_integer (pc, 4) & 0xff0000ff) == 0xc0000080)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 205
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.
+
+   FIXME, add floating point registers and support here.
+
+   Also note that this list does not attempt to deal with kernel
+   debugging (in which the first 32 registers are gr64-gr95).  */
+
+#define REGISTER_NAMES \
+{"gr96", "gr97", "gr98", "gr99", "gr100", "gr101", "gr102", "gr103", "gr104", \
+ "gr105", "gr106", "gr107", "gr108", "gr109", "gr110", "gr111", "gr112", \
+ "gr113", "gr114", "gr115", "gr116", "gr117", "gr118", "gr119", "gr120", \
+ "gr121", "gr122", "gr123", "gr124", "gr125", "gr126", "gr127",                 \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9",   \
+ "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", "lr16", "lr17", "lr18", \
+ "lr19", "lr20", "lr21", "lr22", "lr23", "lr24", "lr25", "lr26", "lr27", \
+ "lr28", "lr29", "lr30", "lr31", "lr32", "lr33", "lr34", "lr35", "lr36", \
+ "lr37", "lr38", "lr39", "lr40", "lr41", "lr42", "lr43", "lr44", "lr45", \
+ "lr46", "lr47", "lr48", "lr49", "lr50", "lr51", "lr52", "lr53", "lr54", \
+ "lr55", "lr56", "lr57", "lr58", "lr59", "lr60", "lr61", "lr62", "lr63", \
+ "lr64", "lr65", "lr66", "lr67", "lr68", "lr69", "lr70", "lr71", "lr72", \
+ "lr73", "lr74", "lr75", "lr76", "lr77", "lr78", "lr79", "lr80", "lr81", \
+ "lr82", "lr83", "lr84", "lr85", "lr86", "lr87", "lr88", "lr89", "lr90", \
+ "lr91", "lr92", "lr93", "lr94", "lr95", "lr96", "lr97", "lr98", "lr99", \
+ "lr100", "lr101", "lr102", "lr103", "lr104", "lr105", "lr106", "lr107", \
+ "lr108", "lr109", "lr110", "lr111", "lr112", "lr113", "lr114", "lr115", \
+ "lr116", "lr117", "lr118", "lr119", "lr120", "lr121", "lr122", "lr123", \
+ "lr124", "lr125", "lr126", "lr127",                                    \
+  "AI0", "AI1", "AI2", "AI3", "AI4", "AI5", "AI6", "AI7", "AI8", "AI9",  \
+  "AI10", "AI11", "AI12", "AI13", "AI14", "AI15", "FP",                         \
+  "bp", "fc", "cr", "q",                                                \
+  "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr",         \
+  "pc0", "pc1", "pc2", "mmu", "lru", "fpe", "int", "fps", "exo", "gr1",  \
+  "alu", "ipc", "ipa", "ipb" }
+
+/* Special register #x.  */
+#define SR_REGNUM(x) \
+  ((x) < 15  ? VAB_REGNUM + (x)                                         \
+   : (x) >= 128 && (x) < 131 ? IPC_REGNUM + (x)                         \
+   : (x) == 131 ? Q_REGNUM                                      \
+   : (x) == 132 ? ALU_REGNUM                                    \
+   : (x) >= 133 && (x) < 136 ? BP_REGNUM + (x)                  \
+   : (x) >= 160 && (x) < 163 ? FPE_REGNUM + (x)                         \
+   : (x) == 164 ? EXO_REGNUM                                     \
+   : (error ("Internal error in SR_REGNUM"), 0))
+#define GR96_REGNUM 0
+#define GR1_REGNUM 200
+/* This needs to be the memory stack pointer, not the register stack pointer,
+   to make call_function work right.  */
+#define SP_REGNUM MSP_REGNUM
+#define FP_REGNUM 33 /* lr1 */
+/* Large Return Pointer (gr123).  */
+#define LRP_REGNUM (123 - 96 + GR96_REGNUM)
+/* Static link pointer (gr124).  */
+#define SLP_REGNUM (124 - 96 + GR96_REGNUM)
+/* Memory Stack Pointer (gr125).  */
+#define MSP_REGNUM (125 - 96 + GR96_REGNUM)
+/* Register allocate bound (gr126).  */
+#define RAB_REGNUM (126 - 96 + GR96_REGNUM)
+/* Register Free Bound (gr127).  */
+#define RFB_REGNUM (127 - 96 + GR96_REGNUM)
+/* Register Stack Pointer.  */
+#define RSP_REGNUM GR1_REGNUM
+#define LR0_REGNUM 32
+#define PC_REGNUM 192 /* pc1 */
+#define NPC_REGNUM 191 /* pc0 */
+#define PC2_REGNUM 193
+#define BP_REGNUM 177
+#define FC_REGNUM 178
+#define CR_REGNUM 179
+#define Q_REGNUM 180
+#define VAB_REGNUM 181
+#define LRU_REGNUM 195
+#define FPE_REGNUM 196
+#define INT_REGNUM 197
+#define FPS_REGNUM 198
+#define EXO_REGNUM 199
+#define PS_REGNUM 201
+#define ALU_REGNUM 201
+#define IPC_REGNUM 202
+#define IPB_REGNUM 204
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+#define REGISTER_BYTE(N)  ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+/* All regs are 4 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  */
+
+/* All regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE (4)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE (4)
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+  (((N) == PC_REGNUM || (N) == LRP_REGNUM || (N) == SLP_REGNUM         \
+    || (N) == MSP_REGNUM || (N) == RAB_REGNUM || (N) == RFB_REGNUM     \
+    || (N) == GR1_REGNUM || (N) == FP_REGNUM || (N) == LR0_REGNUM       \
+    || (N) == NPC_REGNUM || (N) == PC2_REGNUM)                           \
+   ? lookup_pointer_type (builtin_type_void) : builtin_type_int)
+\f
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+/* On the 29k the LRP points to the part of the structure beyond the first
+   16 words.  */
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  write_register (LRP_REGNUM, (ADDR) + 16 * 4);
+
+/* Should call_function allocate stack space for a struct return?  */
+/* On the 29k objects over 16 words require the caller to allocate space.  */
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 16 * 4)
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF)             \
+  {                                                                               \
+    int reg_length = TYPE_LENGTH (TYPE);                                  \
+    if (reg_length > 16 * 4)                                              \
+      {                                                                           \
+       reg_length = 16 * 4;                                               \
+       read_memory (*((int *)(REGBUF) + LRP_REGNUM), (VALBUF) + 16 * 4,   \
+                    TYPE_LENGTH (TYPE) - 16 * 4);                         \
+      }                                                                           \
+    bcopy (((int *)(REGBUF))+GR96_REGNUM, (VALBUF), reg_length);          \
+  }
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  {                                                                      \
+    int reg_length = TYPE_LENGTH (TYPE);                                 \
+    if (reg_length > 16 * 4)                                             \
+      {                                                                          \
+        reg_length = 16 * 4;                                             \
+        write_memory (read_register (LRP_REGNUM),                        \
+                     (char *)(VALBUF) + 16 * 4,                          \
+                     TYPE_LENGTH (TYPE) - 16 * 4);                       \
+      }                                                                          \
+    write_register_bytes (REGISTER_BYTE (GR96_REGNUM), (char *)(VALBUF),  \
+                         TYPE_LENGTH (TYPE));                            \
+  }
+\f
+/* The am29k user's guide documents well what the stacks look like.
+   But what isn't so clear there is how this interracts with the
+   symbols, or with GDB.
+   In the following saved_msp, saved memory stack pointer (which functions
+   as a memory frame pointer), means either
+   a register containing the memory frame pointer or, in the case of
+   functions with fixed size memory frames (i.e. those who don't use
+   alloca()), the result of the calculation msp + msize.
+
+   LOC_ARG, LOC_LOCAL - For GCC, these are relative to saved_msp.
+     For high C, these are relative to msp (making alloca impossible).
+   LOC_REGISTER, LOC_REGPARM - The register number is the number at the
+     time the function is running (after the prologue), or in the case
+     of LOC_REGPARM, may be a register number in the range 160-175.
+
+   The compilers do things like store an argument into memory, and then put out
+   a LOC_ARG for it, or put it into global registers and put out a
+   LOC_REGPARM.  Thus is it important to execute the first line of
+   code (i.e. the line of the open brace, i.e. the prologue) of a function
+   before trying to print arguments or anything.
+
+   The following diagram attempts to depict what is going on in memory
+   (see also the _am29k user's guide_) and also how that interacts with
+   GDB frames.  We arbitrarily pick fci->frame to point the same place
+   as the register stack pointer; since we set it ourself in
+   INIT_EXTRA_FRAME_INFO, and access it only through the FRAME_*
+   macros, it doesn't really matter exactly how we
+   do it.  However, note that FRAME_FP is used in two ways in GDB:
+   (1) as a "magic cookie" which uniquely identifies frames (even over
+   calls to the inferior), (2) (in PC_IN_CALL_DUMMY [!CANNOT_EXECUTE_STACK])
+   as the value of SP_REGNUM before the dummy frame was pushed.  These
+   two meanings would be incompatible for the 29k if we didn't define
+   CANNOT_EXECUTE_STACK (but we do, so don't worry about it).
+   Also note that "lr1" below, while called a frame pointer
+   in the user's guide, has only one function:  To determine whether
+   registers need to be filled in the function epilogue.
+
+   Consider the code:
+              < call bar>
+               loc1: . . .
+        bar:  sub gr1,gr1,rsize_b
+             . . .
+             add mfp,msp,0
+             sub msp,msp,msize_b
+             . . .
+             < call foo >
+       loc2: . . .
+        foo:  sub gr1,gr1,rsize_f
+             . . .
+             add mfp,msp,0
+             sub msp,msp,msize_f
+             . . .
+        loc3: < suppose the inferior stops here >
+
+                   memory stack      register stack
+                  |           |     |____________|
+                  |           |     |____loc1____|
+         +------->|___________|     |            |   ^
+         |        | ^         |     |  locals_b  |   |
+         |        | |         |     |____________|   |
+         |        | |         |     |            |   | rsize_b
+         |        | | msize_b |     | args_to_f  |   |
+         |        | |         |     |____________|   |
+         |        | |         |     |____lr1_____|   V
+         |        | V         |     |____loc2____|<----------------+
+         |   +--->|___________|<---------mfp     |   ^             |
+         |   |    | ^         |     |  locals_f  |   |             |
+         |   |    | | msize_f |     |____________|   |             |
+         |   |    | |         |     |            |   | rsize_f     |
+         |   |    | V         |     |   args     |   |             |
+         |   |    |___________|<msp |____________|   |             |
+         |   |                      |_____lr1____|   V             |
+         |   |                      |___garbage__| <- gr1 <----+   |
+         |   |                                                 |   |
+          |   |                                                |   |
+         |   |                      pc=loc3                    |   |
+         |   |                                                 |   |
+         |   |                                                 |   |
+         |   |            frame cache                          |   |
+          |   |       |_________________|                      |   |
+          |   |       |rsize=rsize_b    |                      |   |
+          |   |       |msize=msize_b    |                      |   |
+          +---|--------saved_msp        |                      |   |
+              |       |frame------------------------------------|---+
+              |       |pc=loc2          |                       |
+              |       |_________________|                       |
+              |       |rsize=rsize_f    |                       |
+              |       |msize=msize_f    |                       |
+              +--------saved_msp        |                       |
+                      |frame------------------------------------+
+                      |pc=loc3          |
+                      |_________________|
+
+   So, is that sufficiently confusing?  Welcome to the 29000.
+   Notes:
+   * The frame for foo uses a memory frame pointer but the frame for
+     bar does not.  In the latter case the saved_msp is
+     computed by adding msize to the saved_msp of the
+     next frame.
+   * msize is in the frame cache only for high C's sake.  */
+
+void read_register_stack ();
+long read_register_stack_integer ();
+\f
+#define EXTRA_FRAME_INFO  \
+  CORE_ADDR saved_msp;    \
+  unsigned int rsize;     \
+  unsigned int msize;
+
+/* Because INIT_FRAME_PC gets passed fromleaf, that's where we init
+   not only ->pc and ->frame, but all the extra stuff, when called from
+   get_prev_frame_info, that is.  */
+#define INIT_EXTRA_FRAME_INFO(fci) \
+  init_extra_frame_info(fci);
+void init_extra_frame_info ();
+#define INIT_FRAME_PC(fromleaf, fci) \
+  init_frame_pc(fromleaf, fci);
+void init_frame_pc ();
+\f
+/* FRAME_CHAIN takes a FRAME
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* On the 29k, the nominal address of a frame is the address on the
+   register stack of the return address (the one next to the incoming
+   arguments, not down at the bottom so nominal address == stack pointer).
+
+   GDB expects "nominal address" to equal contents of FP_REGNUM,
+   at least when it comes time to create the innermost frame.
+   However, that doesn't work for us, so when creating the innermost
+   frame we set ->frame ourselves in INIT_EXTRA_FRAME_INFO.  */
+
+/* These are mostly dummies for the 29k because INIT_FRAME_PC
+   sets prev->frame instead.  */
+#define FRAME_CHAIN(thisframe) (0)
+
+/* Not sure how to figure out where the bottom frame is.  There is
+   no frame for start.  In my tests so far the
+   pc has been outside the text segment, though, so check for that.
+   However, allow a pc in a call dummy.  */
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (outside_startup_file (FRAME_SAVED_PC (thisframe))   \
+   && FRAME_SAVED_PC (thisframe) >= text_start         \
+   && FRAME_SAVED_PC (thisframe) < text_end + CALL_DUMMY_LENGTH)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (0)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* Saved pc (i.e. return address).  */
+#define FRAME_SAVED_PC(fraim) \
+  (read_register_stack_integer ((fraim)->frame + (fraim)->rsize, 4))
+
+/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
+   offsets being relative to the memory stack pointer (high C) or
+   saved_msp (gcc).  */
+
+#define FRAME_LOCALS_ADDRESS(fi) frame_locals_address (fi)
+extern CORE_ADDR frame_locals_address ();
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+/* While we could go the effort of finding the tags word and getting
+   the argcount field from it,
+   (1) It only counts arguments in registers, i.e. the first 16 words
+       of arguments
+   (2) It gives the number of arguments the function was declared with
+       not how many it was called with (or some variation, like all 16
+       words for varadic functions).  This makes argcount pretty much
+       redundant with -g info, even for varadic functions.
+   So don't bother.  */
+#define FRAME_NUM_ARGS(numargs, fi) ((numargs) = -1)
+
+#define FRAME_ARGS_ADDRESS(fi) FRAME_LOCALS_ADDRESS (fi)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Provide our own get_saved_register.  HAVE_REGISTER_WINDOWS is insufficient
+   because registers get renumbered on the 29k without getting saved.  */
+
+#define GET_SAVED_REGISTER
+\f
+/* Call function stuff.  */
+
+/* The dummy frame looks like this (see also the general frame picture
+   above):
+
+                                       register stack
+
+                                     |                |  frame for function
+                                             |   locals_sproc |  executing at time
+                                      |________________|  of call_function.
+                                     |                |  We must not disturb
+                                     | args_out_sproc |  it.
+        memory stack                 |________________|
+                                     |____lr1_sproc___|
+       |            |                |__retaddr_sproc_| <- gr1 (at start)
+       |____________|<-msp 0 <-----------mfp_dummy_____|
+       |            |  (at start)     |                |
+       | arg_slop   |                |  saved regs    |
+       | (16 words) |                | gr96-gr124     |
+       |____________|<-msp 1--after   | sr128-sr135    |
+       |            | PUSH_DUMMY_FRAME|                |
+       | struct ret |                 |________________|
+       | 17+        |                 |                |
+       |____________|<- lrp           | args_out_dummy |
+       | struct ret |                |  (16 words)    |
+       | 16         |                |________________|
+       | (16 words) |                 |____lr1_dummy___|
+       |____________|<- msp 2--after  |_retaddr_dummy__|<- gr1 after
+       |            | struct ret      |                |   PUSH_DUMMY_FRAME
+       | margs17+   | area allocated  |  locals_inf    |
+       |            |                 |________________|    called
+       |____________|<- msp 4--when   |                |    function's
+       |            |   inf called    | args_out_inf   |    frame (set up
+       | margs16    |                 |________________|    by called
+       | (16 words) |                 |_____lr1_inf____|    function).
+       |____________|<- msp 3--after  |       .        |
+       |            |   args pushed   |       .        |
+       |            |                |       .        |
+                                      |                |
+
+   arg_slop: This area is so that when the call dummy adds 16 words to
+      the msp, it won't end up larger than mfp_dummy (it is needed in the
+      case where margs and struct_ret do not add up to at least 16 words).
+   struct ret:  This area is allocated by GDB if the return value is more
+      than 16 words.  struct ret_16 is not used on the 29k.
+   margs:  Pushed by GDB.  The call dummy copies the first 16 words to
+      args_out_dummy.
+   retaddr_sproc:  Contains the PC at the time we call the function.
+      set by PUSH_DUMMY_FRAME and read by POP_FRAME.
+   retaddr_dummy:  This points to a breakpoint instruction in the dummy.  */
+\f
+/* Rsize for dummy frame, in bytes.  */
+
+/* Bytes for outgoing args, lr1, and retaddr.  */
+#define DUMMY_ARG (2 * 4 + 16 * 4)
+
+/* Number of special registers (sr128-) to save.  */
+#define DUMMY_SAVE_SR128 8
+/* Number of general (gr96-) registers to save.  */
+#define DUMMY_SAVE_GR96 29
+
+#define DUMMY_FRAME_RSIZE \
+(4 /* mfp_dummy */                                        \
+ + DUMMY_SAVE_GR96 * 4                             \
+ + DUMMY_SAVE_SR128 * 4                                   \
+ + DUMMY_ARG                                      \
+ )
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME push_dummy_frame();
+extern void push_dummy_frame ();
+
+/* Discard from the stack the innermost frame,
+   restoring all saved registers.  */
+
+#define POP_FRAME pop_frame ();
+extern void pop_frame ();
+
+/* This sequence of words is the instructions
+   mtsrim cr, 15
+   loadm 0, 0, lr2, msp     ; load first 16 words of arguments into registers
+   add msp, msp, 16 * 4     ; point to the remaining arguments
+  CONST_INSN:
+   const gr96,inf
+   consth gr96,inf
+   calli lr0, gr96
+   aseq 0x40,gr1,gr1   ; nop
+   asneq 0x50,gr1,gr1  ; breakpoint
+   */
+
+/* Position of the "const" instruction within CALL_DUMMY in bytes.  */
+#define CONST_INSN (3 * 4)
+#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
+#define CALL_DUMMY {0x0400870f, 0x3600827d, 0x157d7d40, 0x03ff60ff,    \
+                   0x02ff60ff, 0xc8008060, 0x70400101, 0x72500101}
+#else /* Byte order differs.  */
+  you lose
+#endif /* Byte order differs.  */
+#define CALL_DUMMY_LENGTH (8 * 4)
+
+#define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
+
+/* Helper macro for FIX_CALL_DUMMY.  WORDP is a long * which points to a
+   word in target byte order; bits 0-7 and 16-23 of *WORDP are replaced with
+   bits 0-7 and 8-15 of DATA (which is in host byte order).  */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define STUFF_I16(WORDP, DATA) \
+  { \
+    *((char *)(WORDP) + 3) = ((DATA) & 0xff);\
+    *((char *)(WORDP) + 1) = (((DATA) >> 8) & 0xff);\
+  }
+#else /* Target is little endian.  */
+#define STUFF_I16(WORDP, DATA) \
+  {
+    *(char *)(WORDP) = ((DATA) & 0xff);
+    *((char *)(WORDP) + 2) = (((DATA) >> 8) & 0xff);
+  }
+#endif /* Target is little endian.  */
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+/* Currently this stuffs in the address of the function that we are calling.
+   If different 29k systems use different breakpoint instructions, it
+   could also stuff BREAKPOINT in the right place (to avoid having to
+   duplicate CALL_DUMMY in each tm-*.h file).  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)   \
+  {\
+    STUFF_I16((char *)dummyname + CONST_INSN, fun);\
+    STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16);\
+  }
+
+/* At least our 29k board has separate data & instruction memories and can't
+   execute the data memory.  Also, there should be space after text_end;
+   we won't get a SIGSEGV or scribble on data space.  */
+
+#define CALL_DUMMY_LOCATION AFTER_TEXT_END
+
+/* How to translate register numbers in the .stab's into gdb's internal register
+   numbers.  We don't translate them, but we warn if an invalid register
+   number is seen.  Note that FIXME, we use the value "sym" as an implicit
+   argument in printing the error message.  It happens to be available where
+   this macro is used.  (This macro definition appeared in a late revision
+   of gdb-3.91.6 and is not well tested.  Also, it should be a "complaint".) */
+
+#define        STAB_REG_TO_REGNUM(num) \
+       (((num) > LR0_REGNUM + 127) \
+          ? fprintf(stderr,    \
+               "Invalid register number %d in symbol table entry for %s\n", \
+                (num), SYMBOL_NAME (sym)), (num)       \
+          : (num))
diff --git a/gdb/tm-3b1.h b/gdb/tm-3b1.h
new file mode 100644 (file)
index 0000000..65143a9
--- /dev/null
@@ -0,0 +1,108 @@
+/* Parameters for targeting to a 3b1.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define BREAKPOINT { 0x4e, 0x41 }
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in COFF format.  */
+
+#define COFF_FORMAT
+#define COFF_NO_LONG_FILE_NAMES
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0x300000
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+  register int regnum;                             \
+  sp = push_word (sp, read_register (PC_REGNUM));   \
+  sp = push_word (sp, read_register (FP_REGNUM));   \
+  write_register (FP_REGNUM, sp);                  \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)  \
+    sp = push_word (sp, read_register (regnum));    \
+  sp = push_word (sp, read_register (PS_REGNUM));   \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                  \
+  register CORE_ADDR fp;                                        \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info *fi;                                                \
+  fi = get_frame_info (frame);                                  \
+  fp = fi->frame;                                               \
+  get_frame_saved_regs (fi, &fsr);                              \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)           \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                      \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+     moveml 0xfffc,-(sp)
+     clrw -(sp)
+     movew ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of 
+       the following jsr instruction.  *../
+     jsr @#32323232
+     addl #69696969,sp
+     bpt
+     nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 24
+
+#define CALL_DUMMY_START_OFFSET 8
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type)     \
+{ *(int *)((char *) dummyname + 16) = nargs * 4;  \
+  *(int *)((char *) dummyname + 10) = fun; }
+\f
+#include "tm-68k.h"
diff --git a/gdb/tm-68k.h b/gdb/tm-68k.h
new file mode 100644 (file)
index 0000000..120ea08
--- /dev/null
@@ -0,0 +1,473 @@
+/* Parameters for execution on a 68000 series machine.
+   Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Generic 68000 stuff, to be included by other m-*.h files.
+   Define HAVE_68881 if that is the case.  */
+
+#if defined (HAVE_68881)
+#define IEEE_FLOAT 1
+#endif
+
+/* Define the bit, byte, and word ordering of the machine.  */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc)   \
+{ register int op = read_memory_integer (pc, 2);       \
+  if (op == 0047126)                                   \
+    pc += 4;   /* Skip link #word */                   \
+  else if (op == 0044016)                              \
+    pc += 6;   /* Skip link #long */                   \
+  /* Not sure why branches are here.  */                \
+  /* From m-isi.h, m-altos.h */                         \
+  else if (op == 0060000)                              \
+    pc += 4;   /* Skip bra #word */                    \
+  else if (op == 00600377)                             \
+    pc += 6;   /* skip bra #long */                    \
+  else if ((op & 0177400) == 0060000)                  \
+    pc += 2;   /* skip bra #char */                    \
+}
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.
+   This is a TRAP instruction.  The last 4 bits (0xf below) is the
+   vector.  Systems which don't use 0xf should define BREAKPOINT
+   themselves before including this file.  */
+
+#if !defined (BREAKPOINT)
+#define BREAKPOINT {0x4e, 0x4f}
+#endif
+
+/* If your kernel resets the pc after the trap happens you may need to
+   define this in m-68k.h.  */
+
+#if !defined (DECR_PC_AFTER_BREAK)
+#define DECR_PC_AFTER_BREAK 2
+#endif
+
+/* Nonzero if instruction at PC is a return instruction.  */
+/* Allow any of the return instructions, including a trapv and a return
+   from interupt.  */
+
+#define ABOUT_TO_RETURN(pc) ((read_memory_integer (pc, 2) & ~0x3) == 0x4e74)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long registers are.  */
+
+#define REGISTER_TYPE long
+
+#if defined (HAVE_68881)
+#  if defined (sun)
+    /* Sun3 status includes fpflags, which shows whether the FPU has been used
+       by the process, and whether the FPU was done with an instruction or 
+       was interrupted in the middle of a long instruction.  See
+       <machine/reg.h>.  */
+    /*                      a&d, pc,sr, fp, fpstat, fpflags   */
+#    define NUM_REGS 31
+#    define REGISTER_BYTES (16*4 + 8 + 8*12 + 3*4 + 4)
+#  else /* Not sun3.  */
+#    define NUM_REGS 29
+#    define REGISTER_BYTES (16*4 + 8 + 8*12 + 3*4)
+#  endif /* Not sun3.  */
+#else /* No 68881.  */
+#  define NUM_REGS 18
+#  define REGISTER_BYTES (16*4 + 8)
+#endif /* No 68881.  */
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#if defined (HAVE_68881)
+#define REGISTER_BYTE(N)  \
+ ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168   \
+  : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
+  : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the 68000, all regs are 4 bytes
+   except the floating point regs which are 12 bytes.  */
+/* Note that the unsigned cast here forces the result of the
+   subtraction to very high positive values if N < FP0_REGNUM */
+
+#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the 68000, all regs are 4 bytes
+   except the floating point regs which are 8-byte doubles.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 12
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+{ \
+  extern struct ext_format ext_format_68881 [];        \
+  \
+  if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+    ieee_extended_to_double (ext_format_68881, (FROM), (TO));  \
+  else                                 \
+    bcopy ((FROM), (TO), 4);   \
+}
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+{ \
+  extern struct ext_format ext_format_68881 [];        \
+  \
+  if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+    double_to_ieee_extended (ext_format_68881, (FROM), (TO));  \
+  else                                 \
+    bcopy ((FROM), (TO), 4);   \
+}
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+/* Note, for registers which contain addresses return
+   pointer to void, not pointer to char, because we don't
+   want to attempt to print the string after printing the address.  */
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double :           \
+  (N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM ?         \
+  lookup_pointer_type (builtin_type_void) : builtin_type_int)
+
+#else /* no 68881.  */
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N)  ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the 68000, all regs are 4 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the 68000, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)  bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)  bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N)  builtin_type_int
+
+#endif /* No 68881.  */
+
+/* Initializer for an array of names of registers.
+   Entries beyond the first NUM_REGS are ignored.  */
+
+#define REGISTER_NAMES  \
+ {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+  "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
+  "ps", "pc",  \
+  "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
+  "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define A1_REGNUM 9
+#define FP_REGNUM 14           /* Contains address of executing stack frame */
+#define SP_REGNUM 15           /* Contains address of top of stack */
+#define PS_REGNUM 16           /* Contains processor status */
+#define PC_REGNUM 17           /* Contains program counter */
+#if defined (HAVE_68881)
+#define FP0_REGNUM 18          /* Floating point register 0 */
+#define FPC_REGNUM 26          /* 68881 control register */
+#define FPS_REGNUM 27          /* 68881 status register */
+#endif /* 68881.  */
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { write_register (A1_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  This is assuming that floating point values are returned
+   as doubles in d0/d1.  */
+
+#if !defined (EXTRACT_RETURN_VALUE)
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+#endif
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  Assumes floats are passed
+   in d0/d1.  */
+
+#if !defined (STORE_RETURN_VALUE)
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+#endif
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the 68000, the frame's nominal address
+   is the address of a 4-byte word containing the calling frame's address.  */
+
+#define FRAME_CHAIN(thisframe)  \
+  (outside_startup_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && outside_startup_file (FRAME_SAVED_PC (thisframe)))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+   Can set VAL to -1, meaning no way to tell.  */
+
+/* We can't tell how many args there are
+   now that the C compiler delays popping them.  */
+#if !defined (FRAME_NUM_ARGS)
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+#endif
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#if !defined (FRAME_FIND_SAVED_REGS)
+#if defined (HAVE_68881)
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{ register int regnum;                                                 \
+  register int regmask;                                                        \
+  register CORE_ADDR next_addr;                                                \
+  register CORE_ADDR pc;                                               \
+  int nextinsn;                                                                \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
+      && (frame_info)->pc <= (frame_info)->frame)                              \
+    { next_addr = (frame_info)->frame;                                 \
+      pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
+  else                                                                 \
+    { pc = get_pc_function_start ((frame_info)->pc);                   \
+      /* Verify we have a link a6 instruction next;                    \
+        if not we lose.  If we win, find the address above the saved   \
+        regs using the amount of storage from the link instruction.  */\
+      if (044016 == read_memory_integer (pc, 2))                       \
+       next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \
+      else if (047126 == read_memory_integer (pc, 2))                  \
+       next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \
+      else goto lose;                                                  \
+      /* If have an addal #-n, sp next, adjust next_addr.  */          \
+      if ((0177777 & read_memory_integer (pc, 2)) == 0157774)          \
+       next_addr += read_memory_integer (pc += 2, 4), pc += 4;         \
+    }                                                                  \
+  /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */     \
+  regmask = read_memory_integer (pc + 2, 2);                           \
+  /* But before that can come an fmovem.  Check for it.  */            \
+  nextinsn = 0xffff & read_memory_integer (pc, 2);                     \
+  if (0xf227 == nextinsn                                               \
+      && (regmask & 0xff00) == 0xe000)                                 \
+    { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
+      for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)             \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr -= 12);         \
+      regmask = read_memory_integer (pc + 2, 2); }                     \
+  if (0044327 == read_memory_integer (pc, 2))                          \
+    { pc += 4; /* Regmask's low bit is for register 0, the first written */ \
+      for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)           \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; }    \
+  else if (0044347 == read_memory_integer (pc, 2))                     \
+    { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
+      for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)          \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr -= 4); }                \
+  else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))           \
+    { regnum = 0xf & read_memory_integer (pc, 2); pc += 2;             \
+      (frame_saved_regs).regs[regnum] = (next_addr -= 4); }            \
+  /* fmovemx to index of sp may follow.  */                            \
+  regmask = read_memory_integer (pc + 2, 2);                           \
+  nextinsn = 0xffff & read_memory_integer (pc, 2);                     \
+  if (0xf236 == nextinsn                                               \
+      && (regmask & 0xff00) == 0xf000)                                 \
+    { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
+      for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)             \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12;    \
+      regmask = read_memory_integer (pc + 2, 2); }                     \
+  /* clrw -(sp); movw ccr,-(sp) may follow.  */                                \
+  if (0x426742e7 == read_memory_integer (pc, 4))                       \
+    (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4);             \
+  lose: ;                                                              \
+  (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8;                \
+  (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame;            \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;                \
+}
+#else /* no 68881.  */
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{ register int regnum;                                                 \
+  register int regmask;                                                        \
+  register CORE_ADDR next_addr;                                                \
+  register CORE_ADDR pc;                                               \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 \
+      && (frame_info)->pc <= (frame_info)->frame)                              \
+    { next_addr = (frame_info)->frame;                                 \
+      pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4; }\
+  else                                                                 \
+    { pc = get_pc_function_start ((frame_info)->pc);                   \
+      /* Verify we have a link a6 instruction next;                    \
+        if not we lose.  If we win, find the address above the saved   \
+        regs using the amount of storage from the link instruction.  */\
+      if (044016 == read_memory_integer (pc, 2))                       \
+       next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \
+      else if (047126 == read_memory_integer (pc, 2))                  \
+       next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \
+      else goto lose;                                                  \
+      /* If have an addal #-n, sp next, adjust next_addr.  */          \
+      if ((0177777 & read_memory_integer (pc, 2)) == 0157774)          \
+       next_addr += read_memory_integer (pc += 2, 4), pc += 4;         \
+    }                                                                  \
+  /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */     \
+  regmask = read_memory_integer (pc + 2, 2);                           \
+  if (0044327 == read_memory_integer (pc, 2))                          \
+    { pc += 4; /* Regmask's low bit is for register 0, the first written */ \
+      for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)           \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; }    \
+  else if (0044347 == read_memory_integer (pc, 2))                     \
+    { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
+      for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)          \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr -= 4); }                \
+  else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2))             \
+    { regnum = 0xf & read_memory_integer (pc, 2); pc += 2;             \
+      (frame_saved_regs).regs[regnum] = (next_addr -= 4); }            \
+  /* clrw -(sp); movw ccr,-(sp) may follow.  */                                \
+  if (0x426742e7 == read_memory_integer (pc, 4))                       \
+    (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4);             \
+  lose: ;                                                              \
+  (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8;                \
+  (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame;            \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;                \
+}
+#endif /* no 68881.  */
+#endif /* no FIND_FRAME_SAVED_REGS.  */
+
+/* Note that stuff for calling inferior functions is not in this file
+   because the call dummy is different for different breakpoint
+   instructions, which are different on different systems.  Perhaps
+   they could be merged, but I haven't bothered.  */
diff --git a/gdb/tm-altos.h b/gdb/tm-altos.h
new file mode 100644 (file)
index 0000000..ea92f8b
--- /dev/null
@@ -0,0 +1,130 @@
+/* Definitions to make GDB run on an Altos 3068 (m68k running SVR2)
+   Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x4e, 0x4e}
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#undef NAMES_HAVE_UNDERSCORE
+
+/* Exec files and symbol tables are in COFF format */
+
+#define COFF_FORMAT
+#define COFF_NO_LONG_FILE_NAMES
+
+/* Address of end of stack space.  */
+
+/*#define STACK_END_ADDR (0xffffff)*/
+#define STACK_END_ADDR (0x1000000)
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.
+   On the Altos, the kernel resets the pc to the trap instr */
+
+#define DECR_PC_AFTER_BREAK 0
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  char raw_buffer[12];                                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));                      \
+  sp = push_word (sp, read_register (FP_REGNUM));                      \
+  write_register (FP_REGNUM, sp);                                      \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);    \
+      sp = push_bytes (sp, raw_buffer, 12); }                          \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    sp = push_word (sp, read_register (regnum));                       \
+  sp = push_word (sp, read_register (PS_REGNUM));                      \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                         \
+  register CORE_ADDR fp;                                               \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info *fi;                                               \
+  char raw_buffer[12];                                                 \
+  fi = get_frame_info (frame);                                         \
+  fp = fi->frame;                                                      \
+  get_frame_saved_regs (fi, &fsr);                                     \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    if (fsr.regs[regnum])                                              \
+      { read_memory (fsr.regs[regnum], raw_buffer, 12);                        \
+        write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    if (fsr.regs[regnum])                                              \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                             \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));             \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));         \
+  write_register (SP_REGNUM, fp + 8);                                  \
+  flush_cached_frames ();                                              \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),      \
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+     fmovem 0xff,-(sp)
+     moveml 0xfffc,-(sp)
+     clrw -(sp)
+     movew ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of 
+       the following jsr instruction.  *../
+     jsr @#32323232
+     addl #69696969,sp
+     bpt
+     nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4e4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+#include "tm-68k.h"
diff --git a/gdb/tm-altosgas.h b/gdb/tm-altosgas.h
new file mode 100644 (file)
index 0000000..eb342ea
--- /dev/null
@@ -0,0 +1,28 @@
+/* Definitions to make GDB run on an Altos 3068 using COFF encapsulation.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define COFF_ENCAPSULATE
+
+#include "m-altos.h"
+
+#undef COFF_FORMAT
+#undef COFF_NO_LONG_FILE_NAMES
+#define NAMES_HAVE_UNDERSCORE
+
+#define READ_DBX_FORMAT
diff --git a/gdb/tm-arm.h b/gdb/tm-arm.h
new file mode 100644 (file)
index 0000000..c061399
--- /dev/null
@@ -0,0 +1,415 @@
+/* Definitions to make GDB target for an ARM under RISCiX (4.3bsd).
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* IEEE format floating point */
+
+#define IEEE_FLOAT
+
+/* I provide my own xfer_core_file to cope with shared libraries */
+
+#define XFER_CORE_FILE
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc) pc = skip_prologue(pc)
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_register (LR_REGNUM) & 0x03fffffc)
+
+/* I don't know the real values for these.  */
+#define TARGET_UPAGES UPAGES
+#define TARGET_NBPG NBPG
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0x01000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x00,0x00,0x18,0xef} /* BKPT_SWI from <sys/ptrace.h> */
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) \
+      ((read_memory_integer(pc, 4) & 0x0fffffff == 0x01b0f00e) || \
+       (read_memory_integer(pc, 4) & 0x0ffff800 == 0x09eba800))
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes.  */
+
+#define INVALID_FLOAT(p, len) 0
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { arm_float_info (); }
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+/* Note: I make a fake copy of the pc in register 25 (calling it ps) so
+   that I can clear the status bits from pc (register 15) */
+
+#define NUM_REGS 26
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES \
+      { "a1", "a2", "a3", "a4",                                        \
+       "v1", "v2", "v3", "v4", "v5", "v6",                     \
+        "sl", "fp", "ip", "sp", "lr", "pc",                    \
+        "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "fps", "ps" }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define AP_REGNUM 11
+#define FP_REGNUM 11           /* Contains address of executing stack frame */
+#define SP_REGNUM 13           /* Contains address of top of stack */
+#define LR_REGNUM 14           /* address to return to from a function call */
+#define PC_REGNUM 15           /* Contains program counter */
+#define F0_REGNUM 16           /* first floating point register */
+#define FPS_REGNUM 24          /* floating point status register */
+#define PS_REGNUM 25           /* Contains processor status */
+
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (16*4 + 12*8 + 4 + 4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) (((N) < F0_REGNUM) ? (N)*4 : \
+                         (((N) < PS_REGNUM) ? 16*4 + ((N) - 16)*12 : \
+                          16*4 + 8*12 + ((N) - FPS_REGNUM) * 4))
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the vax, all regs are 4 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 12)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the vax, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 8)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 12
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) ((unsigned)(N) - F0_REGNUM < 8)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  if (REGISTER_CONVERTIBLE(REGNUM))                                    \
+      convert_from_extended((FROM), (TO));                             \
+  else                                                                 \
+      bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  if (REGISTER_CONVERTIBLE(REGNUM))                    \
+    convert_to_extended((FROM), (TO));                 \
+  else                                                 \
+    bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)(N) - F0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
+\f
+/* The system C compiler uses a similar structure return convention to gcc */
+
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 4)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { write_register (0, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  if (TYPE_CODE (TYPE) == TYPE_CODE_FLT)                               \
+    convert_from_extended(REGBUF + REGISTER_BYTE (F0_REGNUM), VALBUF); \
+  else                                                                 \
+    bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) {                             \
+    char _buf[MAX_REGISTER_RAW_SIZE];                                  \
+    convert_to_extended(VALBUF, _buf);                                 \
+    write_register_bytes (REGISTER_BYTE (F0_REGNUM), _buf, MAX_REGISTER_RAW_SIZE); \
+  } else                                                               \
+    write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* Specify that for the native compiler variables for a particular
+   lexical context are listed after the beginning LBRAC instead of
+   before in the executables list of symbols.  */
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (!(gcc_p))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the ARM, the frame's nominal address is the FP value,
+   and 12 bytes before comes the saved previous FP value as a 4-byte word.  */
+
+#define FRAME_CHAIN(thisframe)  \
+  ((thisframe)->pc >= first_object_file_end ? \
+   read_memory_integer ((thisframe)->frame - 12, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{                                                      \
+  CORE_ADDR func_start, after_prologue;                        \
+  func_start = (get_pc_function_start ((FI)->pc) +     \
+               FUNCTION_START_OFFSET);                 \
+  after_prologue = func_start;                         \
+  SKIP_PROLOGUE (after_prologue);                      \
+  (FRAMELESS) = (after_prologue == func_start);                \
+}
+
+/* Saved Pc.  */
+
+#define FRAME_SAVED_PC(FRAME) \
+  (read_memory_integer ((FRAME)->frame - 4, 4) & 0x03fffffc)
+
+#define FRAME_ARGS_ADDRESS(fi) (fi->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{                                                                              \
+    register int regnum;                                                       \
+    register int frame;                                                                \
+    register int next_addr;                                                    \
+    register int return_data_save;                                             \
+    register int saved_register_mask;                                          \
+    bzero (&frame_saved_regs, sizeof frame_saved_regs);                                \
+    frame = (frame_info)->frame;                                               \
+    return_data_save = read_memory_integer(frame, 4) & 0x03fffffc - 12;                \
+    saved_register_mask =                                                      \
+       read_memory_integer(return_data_save, 4);                               \
+    next_addr = frame - 12;                                                    \
+    for (regnum = 4; regnum < 10; regnum++)                                    \
+       if (saved_register_mask & (1<<regnum)) {                                \
+           next_addr -= 4;                                                     \
+           (frame_saved_regs).regs[regnum] = next_addr;                        \
+       }                                                                       \
+    if (read_memory_integer(return_data_save + 4, 4) == 0xed6d7103) {          \
+       next_addr -= 12;                                                        \
+       (frame_saved_regs).regs[F0_REGNUM + 7] = next_addr;                     \
+    }                                                                          \
+    if (read_memory_integer(return_data_save + 8, 4) == 0xed6d6103) {          \
+       next_addr -= 12;                                                        \
+       (frame_saved_regs).regs[F0_REGNUM + 6] = next_addr;                     \
+    }                                                                          \
+    if (read_memory_integer(return_data_save + 12, 4) == 0xed6d5103) {         \
+       next_addr -= 12;                                                        \
+       (frame_saved_regs).regs[F0_REGNUM + 5] = next_addr;                     \
+    }                                                                          \
+    if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103) {         \
+       next_addr -= 12;                                                        \
+       (frame_saved_regs).regs[F0_REGNUM + 4] = next_addr;                     \
+    }                                                                          \
+    (frame_saved_regs).regs[SP_REGNUM] = next_addr;                            \
+    (frame_saved_regs).regs[PC_REGNUM] = frame - 4;                            \
+    (frame_saved_regs).regs[PS_REGNUM] = frame - 4;                            \
+    (frame_saved_regs).regs[FP_REGNUM] = frame - 12;                           \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{                                                              \
+    register CORE_ADDR sp = read_register (SP_REGNUM);         \
+    register int regnum;                                       \
+    /* opcode for ldmdb fp,{v1-v6,fp,ip,lr,pc}^ */             \
+    sp = push_word(sp, 0xe92dbf0); /* dummy return_data_save ins */ \
+    /* push a pointer to the dummy instruction minus 12 */     \
+    sp = push_word(sp, read_register (SP_REGNUM) - 16);                \
+    sp = push_word(sp, read_register (PS_REGNUM));             \
+    sp = push_word(sp, read_register (SP_REGNUM));             \
+    sp = push_word(sp, read_register (FP_REGNUM));             \
+    for (regnum = 9; regnum >= 4; regnum --)                   \
+       sp = push_word(sp, read_register (regnum));             \
+    write_register (FP_REGNUM, read_register (SP_REGNUM) - 8); \
+    write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME \
+{                                                                      \
+    register CORE_ADDR fp = read_register (FP_REGNUM);                 \
+    register unsigned long return_data_save =                          \
+       read_memory_integer ( (read_memory_integer (fp, 4) &            \
+                              0x03fffffc)  - 12, 4);                   \
+    register int regnum;                                               \
+    write_register (PS_REGNUM, read_memory_integer (fp - 4, 4));       \
+    write_register (PC_REGNUM, read_register (PS_REGNUM) & 0x03fffffc);        \
+    write_register (SP_REGNUM, read_memory_integer (fp - 8, 4));       \
+    write_register (FP_REGNUM, read_memory_integer (fp - 12, 4));      \
+    fp -= 12;                                                          \
+    for (regnum = 9; regnum >= 4; regnum--)                            \
+       if (return_data_save & (1<<regnum)) {                           \
+           fp -= 4;                                                    \
+           write_register (regnum, read_memory_integer(fp, 4));        \
+       }                                                               \
+    flush_cached_frames ();                                            \
+    set_current_frame (create_new_frame (read_register (FP_REGNUM),    \
+                                        read_pc ()));                  \
+}
+
+/* This sequence of words is the instructions
+
+     ldmia     sp!,{a1-a4}
+     mov       lk,pc
+     bl                *+8
+     swi       bkpt_swi
+
+   Note this is 16 bytes.  */
+
+#define CALL_DUMMY {0xe8bd000f, 0xe1a0e00f, 0xeb000000, 0xef180000}
+
+#define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{                                                                              \
+    register enum type_code code = TYPE_CODE (type);                           \
+    register nargs_in_registers, struct_return = 0;                            \
+    /* fix the load-arguments mask to move the first 4 or less arguments       \
+       into a1-a4 but make sure the structure return address in a1 is          \
+       not disturbed if the function is returning a structure */               \
+    if ((code == TYPE_CODE_STRUCT ||                                           \
+        code == TYPE_CODE_UNION ||                                             \
+        code == TYPE_CODE_ARRAY) &&                                            \
+       TYPE_LENGTH (type) > 4) {                                               \
+       nargs_in_registers = min(nargs + 1, 4);                                 \
+       struct_return = 1;                                                      \
+    } else                                                                     \
+       nargs_in_registers = min(nargs, 4);                                     \
+    *(char *) dummyname = (1 << nargs_in_registers) - 1 - struct_return;       \
+    *(int *)((char *) dummyname + 8) =                                         \
+       (((fun - (pc + 16)) / 4) & 0x00ffffff) | 0xeb000000; }
diff --git a/gdb/tm-bigmips.h b/gdb/tm-bigmips.h
new file mode 100644 (file)
index 0000000..7d6bae5
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+#include "tm-mips.h"
diff --git a/gdb/tm-convex.h b/gdb/tm-convex.h
new file mode 100644 (file)
index 0000000..5a001f1
--- /dev/null
@@ -0,0 +1,563 @@
+/* Definitions to make GDB run on Convex Unix (4bsd)
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* I don't know if this will work for cross-debugging, even if you do get
+   the right files.  */
+/* Include certain files for dbxread.c  */
+#include <convex/filehdr.h>
+#include <convex/opthdr.h>
+#include <convex/scnhdr.h>
+#include <nlist.h>
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* There is come problem with the debugging symbols generated by the
+   compiler such that the debugging symbol for the first line of a
+   function overlap with the function prologue.  */
+#define PROLOGUE_FIRSTLINE_OVERLAP
+
+/* When convex pcc says CHAR or SHORT, it provides the correct address.  */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Symbol types to ignore.  */
+/* 0xc4 is N_MONPT.  Use the numeric value for the benefit of people
+   with (rather) old OS's.  */
+#define IGNORE_SYMBOL(TYPE) \
+    (((TYPE) & ~N_EXT) == N_TBSS       \
+     || ((TYPE) & ~N_EXT) == N_TDATA   \
+     || ((TYPE) & ~N_EXT) == 0xc4)
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.
+   Convex prolog is:
+       [sub.w #-,sp]           in one of 3 possible sizes
+       [mov psw,-              fc/vc main program prolog
+        and #-,-                 (skip it because the "mov psw" saves the
+       mov -,psw]                 T bit, so continue gets a surprise trap)
+       [and #-,sp]             fc/vc O2 main program prolog
+       [ld.- -(ap),-]          pcc/gcc register arg loads
+*/
+
+#define SKIP_PROLOGUE(pc)  \
+{ int op, ix;                                                          \
+  op = read_memory_integer (pc, 2);                                    \
+  if ((op & 0xffc7) == 0x5ac0) pc += 2;                                        \
+  else if (op == 0x1580) pc += 4;                                      \
+  else if (op == 0x15c0) pc += 6;                                      \
+  if ((read_memory_integer (pc, 2) & 0xfff8) == 0x7c40                 \
+      && (read_memory_integer (pc + 2, 2) & 0xfff8) == 0x1240          \
+      && (read_memory_integer (pc + 8, 2) & 0xfff8) == 0x7c48)         \
+    pc += 10;                                                          \
+  if (read_memory_integer (pc, 2) == 0x1240) pc += 6;                  \
+  for (;;) {                                                           \
+    op = read_memory_integer (pc, 2);                                  \
+    ix = (op >> 3) & 7;                                                        \
+    if (ix != 6) break;                                                        \
+    if ((op & 0xfcc0) == 0x3000) pc += 4;                              \
+    else if ((op & 0xfcc0) == 0x3040) pc += 6;                         \
+    else if ((op & 0xfcc0) == 0x2800) pc += 4;                         \
+    else if ((op & 0xfcc0) == 0x2840) pc += 6;                         \
+    else break;}}
+
+/* Immediately after a function call, return the saved pc.
+   (ignore frame and return *$sp so we can handle both calls and callq) */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+    read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space.
+   This is ((USRSTACK + 0xfff) & -0x1000)) from <convex/vmparam.h> but
+   that expression depends on the kernel version; instead, fetch a
+   page-zero pointer and get it from that.  This will be invalid if
+   they ever change the way bkpt signals are delivered.  */
+
+#define STACK_END_ADDR (0xfffff000 & *(unsigned *) 0x80000050)
+
+/* User-mode traps push an extended rtn block,
+   then fault with one of the following PCs */
+
+#define is_trace_pc(pc)  ((unsigned) ((pc) - (*(int *) 0x80000040)) <= 4)
+#define is_arith_pc(pc)  ((unsigned) ((pc) - (*(int *) 0x80000044)) <= 4)
+#define is_break_pc(pc)  ((unsigned) ((pc) - (*(int *) 0x80000050)) <= 4)
+
+/* We need to manipulate trap bits in the psw */
+
+#define PSW_TRAP_FLAGS 0x69670000
+#define PSW_T_BIT      0x08000000
+#define PSW_S_BIT      0x01000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. (bkpt)  */
+
+#define BREAKPOINT {0x7d,0x50}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT but not always.
+   (The break PC needs to be decremented by 2, but we do it when the
+   break frame is recognized and popped.  That way gdb can tell breaks
+   from trace traps with certainty.) */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. (rtn or rtnq) */
+
+#define ABOUT_TO_RETURN(pc) \
+    ((read_memory_integer (pc, 2) & 0xffe0) == 0x7c80)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p,len)   0
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long long
+
+/* Number of machine registers */
+
+#define NUM_REGS 26
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"pc","psw","fp","ap","a5","a4","a3","a2","a1","sp",\
+                       "s7","s6","s5","s4","s3","s2","s1","s0",\
+                       "S7","S6","S5","S4","S3","S2","S1","S0"}
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define S0_REGNUM 25           /* the real S regs */
+#define S7_REGNUM 18
+#define s0_REGNUM 17           /* low-order halves of S regs */
+#define s7_REGNUM 10
+#define SP_REGNUM 9            /* A regs */
+#define A1_REGNUM 8
+#define A5_REGNUM 4
+#define AP_REGNUM 3
+#define FP_REGNUM 2            /* Contains address of executing stack frame */
+#define PS_REGNUM 1            /* Contains processor status */
+#define PC_REGNUM 0            /* Contains program counter */
+
+/* convert dbx stab register number (from `r' declaration) to a gdb REGNUM */
+
+#define STAB_REG_TO_REGNUM(value) \
+      ((value) < 8 ? S0_REGNUM - (value) : SP_REGNUM - ((value) - 8))
+
+/* Vector register numbers, not handled as ordinary regs.
+   They are treated as convenience variables whose values are read
+   from the inferior when needed.  */
+
+#define V0_REGNUM 0
+#define V7_REGNUM 7
+#define VM_REGNUM 8
+#define VS_REGNUM 9
+#define VL_REGNUM 10
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (4*10 + 8*8)
+
+/* Index within `registers' of the first byte of the space for
+   register N.
+   NB: must match structure of struct syscall_context for correct operation */
+
+#define REGISTER_BYTE(N) ((N) < s7_REGNUM ? 4*(N) : \
+                         (N) < S7_REGNUM ? 44 + 8 * ((N)-s7_REGNUM) : \
+                                           40 + 8 * ((N)-S7_REGNUM))
+
+/* Number of bytes of storage in the actual machine representation
+   for register N. */
+
+#define REGISTER_RAW_SIZE(N) ((N) < S7_REGNUM ? 4 : 8)
+
+/* Number of bytes of storage in the program's representation
+   for register N.   */
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+   bcopy ((FROM), (TO), REGISTER_RAW_SIZE (REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), REGISTER_RAW_SIZE (REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+   ((N) < S7_REGNUM ? builtin_type_int : builtin_type_long_long)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { write_register (A1_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (&((char *) REGBUF) [REGISTER_BYTE (S0_REGNUM) + \
+                            8 - TYPE_LENGTH (TYPE)],\
+        VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+    write_register_bytes (REGISTER_BYTE (S0_REGNUM), VALBUF, 8)
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+    (*(int *) & ((char *) REGBUF) [REGISTER_BYTE (s0_REGNUM)])
+
+/* Define trapped internal variable hooks to read and write
+   vector and communication registers.  */
+
+#define IS_TRAPPED_INTERNALVAR is_trapped_internalvar
+#define VALUE_OF_TRAPPED_INTERNALVAR value_of_trapped_internalvar
+#define SET_TRAPPED_INTERNALVAR set_trapped_internalvar
+
+extern struct value *value_of_trapped_internalvar ();
+
+/* Hooks to read data from soff exec and core files,
+   and to describe the files.  */
+
+#define XFER_CORE_FILE
+#define FILES_INFO_HOOK print_maps
+
+/* Hook to call to print a typeless integer value, normally printed in decimal.
+   For convex, use hex instead if the number looks like an address.  */
+
+#define PRINT_TYPELESS_INTEGER decout
+
+/* For the native compiler, variables for a particular lexical context
+   are listed after the beginning LBRAC instead of before in the
+   executables list of symbols.  Using "gcc_compiled." to distinguish
+   between GCC and native compiler doesn't work on Convex because the
+   linker sorts the symbols to put "gcc_compiled." in the wrong place.
+   desc is nonzero for native, zero for gcc.   */
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (desc != 0)
+
+/* Pcc occaisionally puts an SO where there should be an SOL.   */
+#define PCC_SOL_BROKEN
+
+/* Cannot execute with pc on the stack.  */
+#define CANNOT_EXECUTE_STACK
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame_info with a frame's nominal address in fi->frame,
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* (caller fp is saved at 8(fp)) */
+
+#define FRAME_CHAIN(fi)   (read_memory_integer ((fi)->frame + 8, 4))
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.
+   On convex, check at the return address for `callq' -- if so, frameless,
+   otherwise, not.  */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{                                                                      \
+  extern CORE_ADDR text_start, text_end;                               \
+  CORE_ADDR call_addr = SAVED_PC_AFTER_CALL (FI);                      \
+  (FRAMELESS) = (call_addr >= text_start && call_addr < text_end       \
+                && read_memory_integer (call_addr - 6, 1) == 0x22);    \
+}
+
+#define FRAME_SAVED_PC(fi) (read_memory_integer ((fi)->frame, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) (read_memory_integer ((fi)->frame + 12, 4))
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi)  \
+{ numargs = read_memory_integer (FRAME_ARGS_ADDRESS (fi) - 4, 4); \
+  if (numargs < 0 || numargs >= 256) numargs = -1;}
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+/* Normal (short) frames save only PC, FP, (callee's) AP.  To reasonably
+   handle gcc and pcc register variables, scan the code following the
+   call for the instructions the compiler inserts to reload register
+   variables from stack slots and record the stack slots as the saved
+   locations of those registers.  This will occasionally identify some
+   random load as a saved register; this is harmless.  vc does not
+   declare its register allocation actions in the stabs.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{ register int regnum;                                                 \
+  register int frame_length =  /* 3 short, 2 long, 1 extended, 0 context */\
+      (read_memory_integer ((frame_info)->frame + 4, 4) >> 25) & 3;    \
+  register CORE_ADDR frame_fp =                                                \
+      read_memory_integer ((frame_info)->frame + 8, 4);                        \
+  register CORE_ADDR next_addr;                                                \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 0;                \
+  (frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4;                \
+  (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 8;                \
+  (frame_saved_regs).regs[AP_REGNUM] = frame_fp + 12;                  \
+  next_addr = (frame_info)->frame + 12;                                        \
+  if (frame_length < 3)                                                        \
+    for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum)             \
+      (frame_saved_regs).regs[regnum] = (next_addr += 4);              \
+  if (frame_length < 2)                                                        \
+    (frame_saved_regs).regs[SP_REGNUM] = (next_addr += 4);             \
+  next_addr -= 4;                                                      \
+  if (frame_length < 3)                                                        \
+    for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum)             \
+      (frame_saved_regs).regs[regnum] = (next_addr += 8);              \
+  if (frame_length < 2)                                                        \
+    (frame_saved_regs).regs[S0_REGNUM] = (next_addr += 8);             \
+  else                                                                 \
+    (frame_saved_regs).regs[SP_REGNUM] = next_addr + 8;                        \
+  if (frame_length == 3) {                                             \
+    CORE_ADDR pc = read_memory_integer ((frame_info)->frame, 4);       \
+    int op, ix, disp;                                                  \
+    op = read_memory_integer (pc, 2);                                  \
+    if ((op & 0xffc7) == 0x1480) pc += 4;      /* add.w #-,sp */       \
+    else if ((op & 0xffc7) == 0x58c0) pc += 2; /* add.w #-,sp */       \
+    op = read_memory_integer (pc, 2);                                  \
+    if ((op & 0xffc7) == 0x2a06) pc += 4;      /* ld.w -,ap */         \
+    for (;;) {                                                         \
+      op = read_memory_integer (pc, 2);                                        \
+      ix = (op >> 3) & 7;                                              \
+      if ((op & 0xfcc0) == 0x2800) {           /* ld.- -,ak */         \
+        regnum = SP_REGNUM - (op & 7);                                 \
+       disp = read_memory_integer (pc + 2, 2);                         \
+       pc += 4;}                                                       \
+      else if ((op & 0xfcc0) == 0x2840) {      /* ld.- -,ak */         \
+        regnum = SP_REGNUM - (op & 7);                                 \
+       disp = read_memory_integer (pc + 2, 4);                         \
+       pc += 6;}                                                       \
+      if ((op & 0xfcc0) == 0x3000) {           /* ld.- -,sk */         \
+        regnum = S0_REGNUM - (op & 7);                                 \
+       disp = read_memory_integer (pc + 2, 2);                         \
+       pc += 4;}                                                       \
+      else if ((op & 0xfcc0) == 0x3040) {      /* ld.- -,sk */         \
+        regnum = S0_REGNUM - (op & 7);                                 \
+       disp = read_memory_integer (pc + 2, 4);                         \
+       pc += 6;}                                                       \
+      else if ((op & 0xff00) == 0x7100) {      /* br crossjump */      \
+        pc += 2 * (char) op;                                           \
+        continue;}                                                     \
+      else if (op == 0x0140) {                 /* jmp crossjump */     \
+        pc = read_memory_integer (pc + 2, 4);                          \
+        continue;}                                                     \
+      else break;                                                      \
+      if ((frame_saved_regs).regs[regnum])                             \
+       break;                                                          \
+      if (ix == 7) disp += frame_fp;                                   \
+      else if (ix == 6) disp += read_memory_integer (frame_fp + 12, 4);        \
+      else if (ix != 0) break;                                         \
+      (frame_saved_regs).regs[regnum] =                                        \
+       disp - 8 + (1 << ((op >> 8) & 3));                              \
+      if (regnum >= S7_REGNUM)                                         \
+        (frame_saved_regs).regs[regnum - S0_REGNUM + s0_REGNUM] =      \
+         disp - 4 + (1 << ((op >> 8) & 3));                            \
+    }                                                                  \
+  }                                                                    \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  char buf[8];                                                         \
+  long word;                                                           \
+  for (regnum = S0_REGNUM; regnum >= S7_REGNUM; --regnum) {            \
+    read_register_bytes (REGISTER_BYTE (regnum), buf, 8);              \
+    sp = push_bytes (sp, buf, 8);}                                     \
+  for (regnum = SP_REGNUM; regnum >= FP_REGNUM; --regnum) {            \
+    word = read_register (regnum);                                     \
+    sp = push_bytes (sp, &word, 4);}                                           \
+  word = (read_register (PS_REGNUM) &~ (3<<25)) | (1<<25);             \
+  sp = push_bytes (sp, &word, 4);                                      \
+  word = read_register (PC_REGNUM);                                    \
+  sp = push_bytes (sp, &word, 4);                                      \
+  write_register (SP_REGNUM, sp);                                      \
+  write_register (FP_REGNUM, sp);                                      \
+  write_register (AP_REGNUM, sp);}
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  do {\
+  register CORE_ADDR fp = read_register (FP_REGNUM);       \
+  register int regnum;                                     \
+  register int frame_length =  /* 3 short, 2 long, 1 extended, 0 context */ \
+      (read_memory_integer (fp + 4, 4) >> 25) & 3;          \
+  char buf[8];                                             \
+  write_register (PC_REGNUM, read_memory_integer (fp, 4));  \
+  write_register (PS_REGNUM, read_memory_integer (fp += 4, 4));  \
+  write_register (FP_REGNUM, read_memory_integer (fp += 4, 4));  \
+  write_register (AP_REGNUM, read_memory_integer (fp += 4, 4));  \
+  if (frame_length < 3)                                     \
+    for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum)   \
+      write_register (regnum, read_memory_integer (fp += 4, 4)); \
+  if (frame_length < 2)                                             \
+    write_register (SP_REGNUM, read_memory_integer (fp += 4, 4)); \
+  fp -= 4;                                                     \
+  if (frame_length < 3)                                        \
+    for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) {   \
+      read_memory (fp += 8, buf, 8);                           \
+      write_register_bytes (REGISTER_BYTE (regnum), buf, 8);}   \
+  if (frame_length < 2)        {                                       \
+    read_memory (fp += 8, buf, 8);                             \
+    write_register_bytes (REGISTER_BYTE (regnum), buf, 8);}     \
+  else write_register (SP_REGNUM, fp + 8);                     \
+  flush_cached_frames ();                                      \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM), \
+                                      read_pc ()));            \
+} while (0)
+
+/* This sequence of words is the instructions
+     mov sp,ap
+     pshea 69696969
+     calls 32323232
+     bkpt
+   Note this is 16 bytes.  */
+
+#define CALL_DUMMY {0x50860d4069696969LL,0x2140323232327d50LL}
+
+#define CALL_DUMMY_LENGTH 16
+
+#define CALL_DUMMY_START_OFFSET 0
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)   \
+{ *(int *)((char *) dummyname + 4) = nargs;    \
+  *(int *)((char *) dummyname + 10) = fun; }
+\f
+/* Defs to read soff symbol tables, see dbxread.c */
+
+#define NUMBER_OF_SYMBOLS    ((long) opthdr.o_nsyms)
+#define STRING_TABLE_OFFSET  ((long) filehdr.h_strptr)
+#define SYMBOL_TABLE_OFFSET  ((long) opthdr.o_symptr)
+#define STRING_TABLE_SIZE    ((long) filehdr.h_strsiz)
+#define SIZE_OF_TEXT_SEGMENT ((long) txthdr.s_size)
+#define ENTRY_POINT          ((long) opthdr.o_entry)
+
+#define READ_STRING_TABLE_SIZE(BUFFER) \
+    (BUFFER = STRING_TABLE_SIZE)
+
+#define DECLARE_FILE_HEADERS \
+  FILEHDR filehdr;                                                     \
+  OPTHDR opthdr;                                                       \
+  SCNHDR txthdr
+
+#define READ_FILE_HEADERS(DESC,NAME) \
+{                                                                      \
+  int n;                                                               \
+  val = myread (DESC, &filehdr, sizeof filehdr);                       \
+  if (val < 0)                                                         \
+    perror_with_name (NAME);                                           \
+  if (! IS_SOFF_MAGIC (filehdr.h_magic))                               \
+    error ("%s: not an executable file.", NAME);                       \
+  lseek (DESC, 0L, 0);                                                 \
+  if (myread (DESC, &filehdr, sizeof filehdr) < 0)                     \
+    perror_with_name (NAME);                                           \
+  if (myread (DESC, &opthdr, filehdr.h_opthdr) <= 0)                   \
+    perror_with_name (NAME);                                           \
+  for (n = 0; n < filehdr.h_nscns; n++)                                        \
+    {                                                                  \
+      if (myread (DESC, &txthdr, sizeof txthdr) < 0)                   \
+       perror_with_name (NAME);                                        \
+      if ((txthdr.s_flags & S_TYPMASK) == S_TEXT)                      \
+       break;                                                          \
+    }                                                                  \
+}
diff --git a/gdb/tm-hp300bsd.h b/gdb/tm-hp300bsd.h
new file mode 100644 (file)
index 0000000..d4601bf
--- /dev/null
@@ -0,0 +1,142 @@
+/* Parameters for execution on a Hewlett-Packard 9000/300, running bsd.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Configuration file for HP9000/300 series machine running
+ * University of Utah's 4.3bsd port.  This is NOT for HP-UX.
+ * Problems to hpbsd-bugs@cs.utah.edu
+ */
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+#define TARGET_NBPG 4096
+#define TARGET_UPAGES 3
+
+/* On the HP300, sigtramp is in the u area.  Gak!  User struct is not
+   mapped to the same virtual address in user/kernel address space
+   (hence STACK_END_ADDR as opposed to KERNEL_U_ADDR).  This tests
+   for the whole u area, since we don't necessarily have hp300bsd
+   include files around.  */
+#define IN_SIGTRAMP(pc, name) \
+  ((pc) >= STACK_END_ADDR   \
+   && (pc) < STACK_END_ADDR + TARGET_UPAGES * TARGET_NBPG \
+   )
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0xfff00000
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x4e, 0x42}
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  char raw_buffer[12];                                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));                      \
+  sp = push_word (sp, read_register (FP_REGNUM));                      \
+  write_register (FP_REGNUM, sp);                                      \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    { read_register_gen (regnum, raw_buffer);                          \
+      sp = push_bytes (sp, raw_buffer, 12); }                          \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    sp = push_word (sp, read_register (regnum));                       \
+  sp = push_word (sp, read_register (PS_REGNUM));                      \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                  \
+  register CORE_ADDR fp;                                        \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info *fi;                                        \
+  char raw_buffer[12];                                          \
+  fi = get_frame_info (frame);                                  \
+  fp = fi->frame;                                               \
+  get_frame_saved_regs (fi, &fsr);                              \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)         \
+    if (fsr.regs[regnum])                                       \
+      { read_memory (fsr.regs[regnum], raw_buffer, 12);                 \
+        write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)           \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                      \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+     fmovem 0xff,-(sp)
+     moveml 0xfffc,-(sp)
+     clrw -(sp)
+     movew ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of 
+       the following jsr instruction.  *../
+     jsr @#32323232
+     addl #69696969,sp
+     trap #2
+     nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e424e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+#define HAVE_68881
+
+#include "tm-68k.h"
diff --git a/gdb/tm-hp300hpux.h b/gdb/tm-hp300hpux.h
new file mode 100644 (file)
index 0000000..67c9323
--- /dev/null
@@ -0,0 +1,122 @@
+/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x4e, 0x41}
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0xFFF00000
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  char raw_buffer[12];                                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));                      \
+  sp = push_word (sp, read_register (FP_REGNUM));                      \
+  write_register (FP_REGNUM, sp);                                      \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);    \
+      sp = push_bytes (sp, raw_buffer, 12); }                          \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    sp = push_word (sp, read_register (regnum));                       \
+  sp = push_word (sp, read_register (PS_REGNUM));                      \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                  \
+  register CORE_ADDR fp;                                        \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info *fi;                                        \
+  char raw_buffer[12];                                          \
+  fi = get_frame_info (frame);                                  \
+  fp = fi->frame;                                               \
+  get_frame_saved_regs (fi, &fsr);                              \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)         \
+    if (fsr.regs[regnum])                                       \
+      { read_memory (fsr.regs[regnum], raw_buffer, 12);                 \
+        write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)           \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                      \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+                                      read_pc ()));}
+
+/* This sequence of words is the instructions
+     fmovem 0xff,-(sp)
+     moveml 0xfffc,-(sp)
+     clrw -(sp)
+     movew ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of 
+       the following jsr instruction.  *../
+     jsr @#32323232
+     addl #69696969,sp
+     bpt
+     nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e414e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+#include HAVE_68881
+
+#include "tm-68k.h"
diff --git a/gdb/tm-i386v-g.h b/gdb/tm-i386v-g.h
new file mode 100644 (file)
index 0000000..e1dc3fd
--- /dev/null
@@ -0,0 +1,38 @@
+/* Macro definitions for i386 using the GNU object file format.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ * 
+ * i386gnu: COFF_ENCAPSULATE
+ */
+
+
+#define COFF_ENCAPSULATE
+
+#include "tm-i386v.h"
+
+/* The version in m-i386.h is for COFF.  */
+#undef N_SET_MAGIC
+
+#define NAMES_HAVE_UNDERSCORE
+
+#undef COFF_FORMAT
+#define READ_DBX_FORMAT
diff --git a/gdb/tm-i386v.h b/gdb/tm-i386v.h
new file mode 100644 (file)
index 0000000..59f8967
--- /dev/null
@@ -0,0 +1,307 @@
+/* Macro defintions for i386.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* define this if you don't have the extension to coff that allows
+ * file names to appear in the string table
+ * (aux.x_file.x_foff)
+ */
+#define COFF_NO_LONG_FILE_NAMES
+
+/* turn this on when rest of gdb is ready */
+/* #define IEEE_FLOAT */
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+/* #define NAMES_HAVE_UNDERSCORE */
+
+/* Specify debugger information format.  */
+
+/* #define READ_DBX_FORMAT */
+#define COFF_FORMAT
+
+/* number of traps that happen between exec'ing the shell 
+ * to run an inferior, and when we finally get to 
+ * the inferior code.  This is 2 on most implementations.
+ */
+#define START_INFERIOR_TRAPS_EXPECTED 4
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(frompc)   {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+  (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* This is only supposed to work in execcore.c, where x == 0 and
+   this is called before any other fields are filled in.  */
+#define N_SET_MAGIC(aouthdr, x) \
+  bzero ((char *) &aouthdr, sizeof aouthdr)
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0x80000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 1
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes -- not relevant on the 386.  */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 16
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+/* the order of the first 8 registers must match the compiler's 
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+                        "esp", "ebp", "esi", "edi", \
+                        "eip", "ps", "cs", "ss", \
+                        "ds", "es", "fs", "gs", \
+                        }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define FP_REGNUM 5            /* Contains address of executing stack frame */
+#define SP_REGNUM 4            /* Contains address of top of stack */
+
+#define PC_REGNUM 8
+#define PS_REGNUM 9
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+       (addr) = i386_register_u_addr ((blockend),(regno));
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+   for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { (SP) -= sizeof (ADDR);             \
+    write_memory ((SP), &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+#define FRAME_CHAIN(thisframe) \
+  (outside_startup_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  { i386_pop_frame (); }
+
+/* this is 
+ *   call 11223344 (32 bit relative)
+ *   int3
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)   \
+{ \
+       int from, to, delta, loc; \
+       loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+       from = loc + 5; \
+       to = (int)(fun); \
+       delta = to - from; \
+       *(int *)((char *)(dummyname) + 1) = delta; \
+}
diff --git a/gdb/tm-i960.h b/gdb/tm-i960.h
new file mode 100644 (file)
index 0000000..5ddf8c2
--- /dev/null
@@ -0,0 +1,399 @@
+/* Parameters for target machine Intel 960, for GDB, the GNU debugger.
+   Copyright (C) 1990-1991 Free Software Foundation, Inc.
+   Contributed by Intel Corporation.
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Definitions to target GDB to any i960.  */
+
+#ifndef I80960
+#define I80960
+#endif
+
+/* Hook for the SYMBOL_CLASS of a parameter when decoding DBX symbol
+   information.  In the i960, parameters can be stored as locals or as
+   args, depending on the type of the debug record.
+
+   From empirical observation, gcc960 uses N_LSYM to indicate
+   arguments passed in registers and then copied immediately
+   to the frame, and N_PSYM to indicate arguments passed in a
+   g14-relative argument block.  */
+
+#define        DBX_PARM_SYMBOL_CLASS(type) ((type == N_LSYM)? LOC_LOCAL_ARG: LOC_ARG)
+
+/* Byte order is configurable, but this machine runs little-endian.  */
+#define        TARGET_BYTE_ORDER       LITTLE_ENDIAN
+
+/* We have IEEE floating point, if we have any float at all.  */
+
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance ip across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(ip)      { ip = skip_prologue (ip); }
+extern CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved ip.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function
+   executes some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) (saved_pc_after_call (frame))
+extern CORE_ADDR saved_pc_after_call ();
+
+/* Stack grows upward */
+
+#define INNER_THAN >
+
+/* Nonzero if instruction at ip is a return instruction.  */
+
+#define ABOUT_TO_RETURN(ip) (read_memory_integer(ip,4) == 0x0a000000)
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes.  */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* How long (ordinary) registers are */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+#define NUM_REGS 40
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES { \
+       /*  0 */ "pfp", "sp",  "rip", "r3",  "r4",  "r5",  "r6",  "r7", \
+       /*  8 */ "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",\
+       /* 16 */ "g0",  "g1",  "g2",  "g3",  "g4",  "g5",  "g6",  "g7", \
+       /* 24 */ "g8",  "g9",  "g10", "g11", "g12", "g13", "g14", "fp", \
+       /* 32 */ "pc",  "ac",  "ip",  "tc",  "fp0", "fp1", "fp2", "fp3",       \
+}
+
+/* Register numbers of various important registers (used to index
+   into arrays of register names and register values).  */
+
+#define R0_REGNUM   0  /* First local register         */
+#define SP_REGNUM   1  /* Contains address of top of stack */
+#define RIP_REGNUM  2  /* Return instruction pointer (local r2) */
+#define R15_REGNUM 15  /* Last local register          */
+#define G0_REGNUM  16  /* First global register        */
+#define G13_REGNUM 29  /* g13 - holds struct return address */
+#define G14_REGNUM 30  /* g14 - ptr to arg block / leafproc return address */
+#define FP_REGNUM  31  /* Contains address of executing stack frame */
+#define        PCW_REGNUM 32   /* process control word */
+#define        ACW_REGNUM 33   /* arithmetic control word */
+#define        IP_REGNUM  34   /* instruction pointer */
+#define        TCW_REGNUM 35   /* trace control word */
+#define FP0_REGNUM 36  /* First floating point register */
+
+/* Some registers have more than one name */
+
+#define PC_REGNUM  IP_REGNUM   /* GDB refers to ip as the Program Counter */
+#define PFP_REGNUM R0_REGNUM   /* Previous frame pointer       */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES ((36*4) + (4*10))
+
+/* Index within `registers' of the first byte of the space for register N.  */
+
+#define REGISTER_BYTE(N) ( (N) < FP0_REGNUM ? \
+                               (4*(N)) : ((10*(N)) - (6*FP0_REGNUM)) )
+
+/* The i960 has register windows, sort of.  */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system?  A yes answer
+   implies that 1) The name of this register will not be the same in
+   other frames, and 2) This register is automatically "saved" upon
+   subroutine calls and thus there is no need to search more than one
+   stack frame for it.
+   
+   On the i960, in fact, the name of this register in another frame is
+   "mud" -- there is no overlap between the windows.  Each window is
+   simply saved into the stack (true for our purposes, after having been
+   flushed; normally they reside on-chip and are restored from on-chip
+   without ever going to memory).  */
+
+#define REGISTER_IN_WINDOW_P(regnum)   ((regnum) <= R15_REGNUM)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the i960, all regs are 4 bytes except for floating
+   point, which are 10.  NINDY only sends us 8 byte values for these,
+   which is a pain, but VxWorks handles this correctly, so we must.  */
+
+#define REGISTER_RAW_SIZE(N)           ( (N) < FP0_REGNUM ? 4 : 10 )
+
+/* Number of bytes of storage in the program's representation for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N)       ( (N) < FP0_REGNUM ? 4 : 8 )
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion from raw format to virtual
+   format.  */
+
+#define REGISTER_CONVERTIBLE(N) ((N) >= FP0_REGNUM)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)     \
+{ \
+  extern struct ext_format ext_format_i960[];          \
+  \
+  if ((REGNUM) >= FP0_REGNUM)   \
+    ieee_extended_to_double (ext_format_i960, (FROM), (TO));     \
+  else                                  \
+    bcopy ((FROM), (TO), 4);   \
+}
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+{ \
+  extern struct ext_format ext_format_i960[];          \
+  \
+  if ((REGNUM) >= FP0_REGNUM)   \
+    double_to_ieee_extended (ext_format_i960, (FROM), (TO));     \
+  else                                  \
+    bcopy ((FROM), (TO), 4);   \
+}
+
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) ((N) < FP0_REGNUM ? \
+                                       builtin_type_int : builtin_type_double)
+\f
+/* Macros for understanding function return values... */
+
+/* Does the specified function use the "struct returning" convention
+   or the "value returning" convention?  The "value returning" convention
+   almost invariably returns the entire value in registers.  The
+   "struct returning" convention often returns the entire value in
+   memory, and passes a pointer (out of or into the function) saying
+   where the value (is or should go).
+
+   Since this sometimes depends on whether it was compiled with GCC,
+   this is also an argument.  This is used in call_function to build a
+   stack, and in value_being_returned to print return values.
+
+   On i960, a structure is returned in registers g0-g3, if it will fit.
+   If it's more than 16 bytes long, g13 pointed to it on entry.  */
+
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 16)
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  This is only called if USE_STRUCT_CONVENTION for this
+   type is 0.
+
+   On the i960 we just take as many bytes as we need from G0 through G3.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+       bcopy(REGBUF+REGISTER_BYTE(G0_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
+
+/* If USE_STRUCT_CONVENTION produces a 1, 
+   extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).
+
+   Address of where to put structure was passed in in global
+   register g13 on entry.  God knows what's in g13 now.  The
+   (..., 0) below is to make it appear to return a value, though
+   actually all it does is call error().  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+   (error("Don't know where large structure is returned on i960"), 0)
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format, for "value returning" functions.
+  
+   For 'return' command:  not (yet) implemented for i960.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+    error ("Returning values from functions is not implemented in i960 gdb")
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+    error ("Returning values from functions is not implemented in i960 gdb")
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* We cache information about saved registers in the frame structure,
+   to save us from having to re-scan function prologues every time
+   a register in a non-current frame is accessed.  */
+
+#define EXTRA_FRAME_INFO       \
+       struct frame_saved_regs *fsr;   \
+       CORE_ADDR arg_pointer;
+
+/* Zero the frame_saved_regs pointer when the frame is initialized,
+   so that FRAME_FIND_SAVED_REGS () will know to allocate and
+   initialize a frame_saved_regs struct the first time it is called.
+   Set the arg_pointer to -1, which is not valid; 0 and other values
+   indicate real, cached values.  */
+
+#define INIT_EXTRA_FRAME_INFO(fi) ((fi)->fsr = 0, (fi)->arg_pointer = -1)
+
+/* On the i960, we get the chain pointer by reading the PFP saved
+   on the stack and clearing the status bits.  */
+
+#define FRAME_CHAIN(thisframe) \
+  (read_memory_integer (FRAME_FP(thisframe), 4) & ~0xf)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+   and has no caller.  In that case, FRAME_CHAIN_COMBINE is not used.
+
+   On the i960, each various target system type must define FRAME_CHAIN_VALID,
+   since it differs between NINDY and VxWorks, the two currently supported
+   targets types.  We leave it undefined here.  */
+
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  { (FRAMELESS) = (leafproc_return ((FI)->pc) != 0); }
+
+/* Note that in the i960 architecture the return pointer is saved in the
+   *caller's* stack frame.
+  
+   Make sure to zero low-order bits because of bug in 960CA A-step part
+   (instruction addresses should always be word-aligned anyway).  */
+
+#define FRAME_SAVED_PC(frame) \
+                       ((read_memory_integer(FRAME_CHAIN(frame)+8,4)) & ~3)
+
+/* On the i960, FRAME_ARGS_ADDRESS should return the value of
+   g14 as passed into the frame, if known.  We need a function for this.
+   We cache this value in the frame info if we've already looked it up.  */
+
+#define FRAME_ARGS_ADDRESS(fi)         \
+  (((fi)->arg_pointer != -1)? (fi)->arg_pointer: frame_args_address (fi, 0))
+extern CORE_ADDR frame_args_address ();                /* i960-tdep.c */
+
+/* This is the same except it should return 0 when
+   it does not really know where the args are, rather than guessing.
+   This value is not cached since it is only used infrequently.  */
+
+#define        FRAME_ARGS_ADDRESS_CORRECT(fi)  (frame_args_address (fi, 1))
+
+#define FRAME_LOCALS_ADDRESS(fi)       (fi)->frame
+
+/* Set NUMARGS to the number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi)    (numargs = -1)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Produce the positions of the saved registers in a stack frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info_addr, sr) \
+       frame_find_saved_regs (frame_info_addr, &sr)
+extern void frame_find_saved_regs();           /* See i960-tdep.c */
+
+
+/* Print status when we get a random unexpected signal.  We have more
+   kinds of signals than Unix does... */
+
+#define        PRINT_RANDOM_SIGNAL(stop_signal) print_fault (stop_signal)
+\f
+/* Things needed for making calls to functions in the inferior process */
+
+/* Push an empty stack frame, to record the current ip, etc.
+  
+   Not (yet?) implemented for i960.  */
+
+#define PUSH_DUMMY_FRAME       \
+error("Function calls into the inferior process are not supported on the i960")
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME \
+       pop_frame ()
+
+
+/* This sequence of words is the instructions
+  
+       callx 0x00000000
+       fmark
+ */
+
+/* #define CALL_DUMMY { 0x86003000, 0x00000000, 0x66003e00 } */
+
+/* #define CALL_DUMMY_START_OFFSET 0 *//* Start execution at beginning of dummy */
+
+/* Indicate that we don't support calling inferior child functions.  */
+
+#undef CALL_DUMMY
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at 'dummyname'.
+  
+   Ignore arg count on i960.  */
+
+/* #define FIX_CALL_DUMMY(dummyname, fun, nargs) *(((int *)dummyname)+1) = fun */
+
+#undef FIX_CALL_DUMMY
+
+
+/* Interface definitions for kernel debugger KDB */
+/* (Not relevant to i960.) */
diff --git a/gdb/tm-isi.h b/gdb/tm-isi.h
new file mode 100644 (file)
index 0000000..7697a9f
--- /dev/null
@@ -0,0 +1,227 @@
+/* Definitions to target GDB on an ISI Optimum V (3.05) under 4.3bsd.
+   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This has not been tested on ISI's running BSD 4.2, but it will probably
+   work.  */
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/*#define STACK_END_ADDR 0x10000000*/
+#define STACK_END_ADDR 0xfffe000
+
+/* Data segment starts at etext rounded up to DATAROUND in {N,Z}MAGIC files */
+
+#define DATAROUND      0x20000
+#define N_DATADDR(hdr) (hdr.a_magic != OMAGIC ? \
+       (hdr.a_text + DATAROUND) & ~(DATAROUND-1) : hdr.a_text)
+
+/* Text segment starts at sizeof (struct exec) in {N,Z}MAGIC files */
+
+#define N_TXTADDR(hdr) (hdr.a_magic != OMAGIC ? sizeof (struct exec) : 0)
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.
+   On the ISI, the kernel resets the pc to the trap instr */
+
+#define DECR_PC_AFTER_BREAK 0
+
+\f
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(val, fi)  \
+{ register CORE_ADDR pc = FRAME_SAVED_PC (fi);                 \
+  register int insn = 0177777 & read_memory_integer (pc, 2);   \
+  val = 0;                                                     \
+  if (insn == 0047757 || insn == 0157374)  /* lea W(sp),sp or addaw #W,sp */ \
+    val = read_memory_integer (pc + 2, 2);                     \
+  else if ((insn & 0170777) == 0050217 /* addql #N, sp */      \
+          || (insn & 0170777) == 0050117)  /* addqw */         \
+    { val = (insn >> 9) & 7; if (val == 0) val = 8; }          \
+  else if (insn == 0157774) /* addal #WW, sp */                        \
+    val = read_memory_integer (pc + 2, 4);                     \
+  val >>= 2; }
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{ register int regnum;                                                 \
+  register int regmask;                                                        \
+  register CORE_ADDR next_addr;                                                \
+  register CORE_ADDR pc;                                               \
+  register int insn;                                                   \
+  register int offset;                                                 \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
+      && (frame_info)->pc <= (frame_info)->frame)                              \
+    { next_addr = (frame_info)->frame;                                 \
+      pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
+  else                                                                 \
+    { pc = get_pc_function_start ((frame_info)->pc);                   \
+      /* Verify we have a link a6 instruction next,                    \
+        or a branch followed by a link a6 instruction;                 \
+        if not we lose.  If we win, find the address above the saved   \
+        regs using the amount of storage from the link instruction.  */\
+retry:                                                                 \
+      insn = read_memory_integer (pc, 2);                              \
+      if (insn == 044016)                                              \
+       next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 4), pc+=4; \
+      else if (insn == 047126)                                         \
+       next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 2), pc+=2; \
+      else if ((insn & 0177400) == 060000)     /* bra insn */          \
+       { offset = insn & 0377;                                         \
+          pc += 2;                             /* advance past bra */  \
+         if (offset == 0)                      /* bra #word */         \
+           offset = read_memory_integer (pc, 2), pc += 2;              \
+         else if (offset == 0377)              /* bra #long */         \
+           offset = read_memory_integer (pc, 4), pc += 4;              \
+         pc += offset;                                                 \
+         goto retry;                                                   \
+      } else goto lose;                                                        \
+      /* If have an addal #-n, sp next, adjust next_addr.  */          \
+      if ((0177777 & read_memory_integer (pc, 2)) == 0157774)          \
+       next_addr += read_memory_integer (pc += 2, 4), pc += 4;         \
+    }                                                                  \
+  /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */     \
+  insn = read_memory_integer (pc, 2), pc += 2;                         \
+  regmask = read_memory_integer (pc, 2);                               \
+  if ((insn & 0177760) == 022700)      /* movl rn, (sp) */             \
+    (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr;  \
+  else if ((insn & 0177760) == 024700) /* movl rn, -(sp) */            \
+    (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr-=4; \
+  else if (insn == 0044327)            /* moveml mask, (sp) */         \
+    { pc += 2;                                                         \
+      /* Regmask's low bit is for register 0, the first written */     \
+      next_addr -= 4;                                                  \
+      for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)           \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr += 4);          \
+  } else if (insn == 0044347)          /* moveml mask, -(sp) */        \
+    { pc += 2;                                                         \
+      /* Regmask's low bit is for register 15, the first pushed */     \
+      for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)          \
+       if (regmask & 1)                                                \
+          (frame_saved_regs).regs[regnum] = (next_addr -= 4); }                \
+  /* clrw -(sp); movw ccr,-(sp) may follow.  */                                \
+  if (read_memory_integer (pc, 2) == 041147                            \
+      && read_memory_integer (pc+2, 2) == 042347)                      \
+    (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4);             \
+  lose: ;                                                              \
+  (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8;                \
+  (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame;            \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;                \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  char raw_buffer[12];                                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));                      \
+  sp = push_word (sp, read_register (FP_REGNUM));                      \
+  write_register (FP_REGNUM, sp);                                      \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);    \
+      sp = push_bytes (sp, raw_buffer, 12); }                          \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    sp = push_word (sp, read_register (regnum));                       \
+  sp = push_word (sp, read_register (PS_REGNUM));                      \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                         \
+  register CORE_ADDR fp;                                               \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info *fi;                                               \
+  char raw_buffer[12];                                                 \
+  fi = get_frame_info (frame);                                         \
+  fp = fi->frame;                                                      \
+  get_frame_saved_regs (fi, &fsr);                                     \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    if (fsr.regs[regnum])                                              \
+      { read_memory (fsr.regs[regnum], raw_buffer, 12);                        \
+        write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    if (fsr.regs[regnum])                                              \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                             \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));             \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));         \
+  write_register (SP_REGNUM, fp + 8);                                  \
+  flush_cached_frames ();                                              \
+  set_current_frame ( create_new_frame (read_register (FP_REGNUM),     \
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+     fmovem #<f0-f7>,-(sp)
+     moveml 0xfffc,-(sp)
+     clrw -(sp)
+     movew ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of
+       the following jsr instruction.  *../
+     jsr @#32323232
+     addl #69696969,sp
+     bpt
+     nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+#define HAVE_68881 1
+
+#include "tm-68k.h"
diff --git a/gdb/tm-m88k.h b/gdb/tm-m88k.h
new file mode 100644 (file)
index 0000000..1890d6c
--- /dev/null
@@ -0,0 +1,460 @@
+/* Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is currently for a 88000 running DGUX.  If other 88k ports are
+   done, OS-specific stuff should be moved (see tm-68k.h, for example).  */
+/* g++ support is not yet included.  */
+
+#include "tdesc.h"
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* This is not a CREATE_INFERIOR_HOOK because it also applies to
+   remote debugging.  */
+#define START_INFERIOR_HOOK () \
+  { \
+    extern int safe_to_init_tdesc_context; \
+    extern int tdesc_handle; \
+ \
+    safe_to_init_tdesc_context = 0; \
+    if (tdesc_handle) \
+      { \
+       dc_terminate (tdesc_handle); \
+       tdesc_handle = 0; \
+      } \
+  }
+
+#define EXTRA_FRAME_INFO dc_dcontext_t frame_context;
+#define INIT_EXTRA_FRAME_INFO(fci) \
+  {                                                                     \
+    if (fci->next_frame != NULL)                                        \
+      {                                                                 \
+        /* The call to get_prev_context */                              \
+        /* will update current_context for us. */                       \
+        int stack_error = 1;                                            \
+        jmp_buf stack_jmp;                                              \
+        if (!setjmp (stack_jmp))                                        \
+          {                                                             \
+            prev->frame_context                                         \
+              = get_prev_context (next_frame->frame_context);           \
+            stack_error = 0;                                            \
+          }                                                             \
+        else                                                            \
+          {                                                             \
+            stack_error = 0;                                            \
+            next_frame->prev = 0;                                       \
+            return 0;                                                   \
+          }                                                             \
+        if (!prev->frame_context)                                       \
+          {                                                             \
+            next_frame->prev = 0;                                       \
+            return 0;                                                   \
+          }                                                             \
+      }                                                                 \
+    else                                                                \
+      {                                                                 \
+        /* We are creating an arbitrary frame */                        \
+        /* (i.e. we are in create_new_frame).  */                       \
+        extern dc_dcontext_t current_context;                           \
+                                                                        \
+        fci->frame_context = current_context;                           \
+      }                                                                 \
+  }
+
+#define INIT_FRAME_PC(fromleaf, prev) \
+  {                                                                     \
+    prev->pc = dc_location (prev->frame_context);                       \
+    prev->frame = get_frame_base (prev->pc);                            \
+  }
+
+#define IEEE_FLOAT
+
+/* Text Description (TDESC) is used by m88k to maintain stack & reg info */
+
+#define TDESC
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Hook for read_relative_register_raw_bytes */
+
+#define READ_RELATIVE_REGISTER_RAW_BYTES
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(frompc)   0
+
+/* The m88k kernel aligns all instructions on 4-byte boundaries.  The
+   kernel also uses the least significant two bits for its own hocus
+   pocus.  When gdb receives an address from the kernel, it needs to
+   preserve those right-most two bits, but gdb also needs to be careful
+   to realize that those two bits are not really a part of the address
+   of an instruction.  Shrug.  */
+
+#define ADDR_BITS_REMOVE(addr) ((addr) & ~3)
+#define ADDR_BITS_SET(addr) (((addr) | 0x00000002) - 4)
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+  (read_register (SRP_REGNUM) & (~3))
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0xF0000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+/* instruction 0xF000D1FF is 'tb0 0,r0,511'
+   If Bit bit 0 of r0 is clear (always true),
+   initiate exception processing (trap).
+ */
+#define BREAKPOINT {0xF0, 0x00, 0xD1, 0xFF}
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0xF0000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+/* instruction 0xF000D1FF is 'tb0 0,r0,511'
+   If Bit bit 0 of r0 is clear (always true),
+   initiate exception processing (trap).
+ */
+#define BREAKPOINT {0xF0, 0x00, 0xD1, 0xFF}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.  */
+/* 'jmp r1' or 'jmp.n r1' is used to return from a subroutine. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0xF800)
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes -- not relevant on the 386.  */
+
+#define INVALID_FLOAT(p, len) IEEE_isNAN(p,len)
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 38
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {\
+       "r0",\
+       "r1",\
+       "r2",\
+       "r3",\
+       "r4",\
+       "r5",\
+       "r6",\
+       "r7",\
+       "r8",\
+       "r9",\
+       "r10",\
+       "r11",\
+       "r12",\
+       "r13",\
+       "r14",\
+       "r15",\
+       "r16",\
+       "r17",\
+       "r18",\
+       "r19",\
+       "r20",\
+       "r21",\
+       "r22",\
+       "r23",\
+       "r24",\
+       "r25",\
+       "r26",\
+       "r27",\
+       "r28",\
+       "r29",\
+       "r30",\
+       "r31",\
+       "psr",\
+       "fpsr",\
+       "fpcr",\
+       "sxip",\
+       "snip",\
+       "sfip",\
+       "vbr",\
+       "dmt0",\
+       "dmd0",\
+       "dma0",\
+       "dmt1",\
+       "dmd1",\
+       "dma1",\
+       "dmt2",\
+       "dmd2",\
+       "dma2",\
+       "sr0",\
+       "sr1",\
+       "sr2",\
+       "sr3",\
+       "fpecr",\
+       "fphs1",\
+       "fpls1",\
+       "fphs2",\
+       "fpls2",\
+       "fppt",\
+       "fprh",\
+       "fprl",\
+       "fpit",\
+       "fpsr",\
+       "fpcr",\
+       };
+
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define SRP_REGNUM 1           /* Contains subroutine return pointer */
+#define RV_REGNUM 2            /* Contains simple return values */
+#define SRA_REGNUM 12          /* Contains address of struct return values */
+#define FP_REGNUM 30           /* Contains address of executing stack frame */
+#define SP_REGNUM 31           /* Contains address of top of stack */
+#define SXIP_REGNUM 35         /* Contains Shadow Execute Instruction Pointer */
+#define SNIP_REGNUM 36         /* Contains Shadow Next Instruction Pointer */
+#define PC_REGNUM SXIP_REGNUM  /* Program Counter */
+#define NPC_REGNUM SNIP_REGNUM /* Next Program Counter */
+#define PSR_REGNUM 32           /* Processor Status Register */
+#define FPSR_REGNUM 33         /* Floating Point Status Register */
+#define FPCR_REGNUM 34         /* Floating Point Control Register */
+#define SFIP_REGNUM 37         /* Contains Shadow Fetched Intruction pointer */
+#define NNPC_REGNUM SFIP_REGNUM /* Next Next Program Counter */
+
+/* PSR status bit definitions.  */
+
+#define PSR_MODE               0x80000000
+#define PSR_BYTE_ORDER         0x40000000
+#define PSR_SERIAL_MODE                0x20000000
+#define PSR_CARRY              0x10000000
+#define PSR_SFU_DISABLE                0x000003f0
+#define PSR_SFU1_DISABLE       0x00000008
+#define PSR_MXM                        0x00000004
+#define PSR_IND                        0x00000002
+#define PSR_SFRZ               0x00000001
+
+/* BCS requires that the SXIP_REGNUM (or PC_REGNUM) contain the address
+   of the next instr to be executed when a breakpoint occurs.  Because
+   the kernel gets the next instr (SNIP_REGNUM), the instr in SNIP needs
+   to be put back into SFIP, and the instr in SXIP should be shifted
+   to SNIP */
+
+/* Are you sitting down?  It turns out that the 88K BCS (binary compatibility
+  standard) folks originally felt that the debugger should be responsible
+  for backing up the IPs, not the kernel (as is usually done).  Well, they
+  have reversed their decision, and in future releases our kernel will be
+  handling the backing up of the IPs.  So, eventually, we won't need to
+  do the SHIFT_INST_REGS stuff.  But, for now, since there are 88K systems out
+  there that do need the debugger to do the IP shifting, and since there
+  will be systems where the kernel does the shifting, the code is a little
+  more complex than perhaps it needs to be (we still go inside SHIFT_INST_REGS,
+  and if the shifting hasn't occurred then gdb goes ahead and shifts).  */
+
+#define SHIFT_INST_REGS
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+
+#define REGISTER_BYTES (NUM_REGS * sizeof(REGISTER_TYPE))
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N)*sizeof(REGISTER_TYPE))
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+#define REGISTER_RAW_SIZE(N) (sizeof(REGISTER_TYPE))
+
+/* Number of bytes of storage in the program's representation
+   for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (sizeof(REGISTER_TYPE))
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE (sizeof(REGISTER_TYPE))
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.
+/* Are FPS1, FPS2, FPR "virtual" regisers? */
+
+#define MAX_REGISTER_VIRTUAL_SIZE (sizeof(REGISTER_TYPE))
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), (sizeof(REGISTER_TYPE)));}
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), (sizeof(REGISTER_TYPE)));}
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+/* The 88k call/return conventions call for "small" values to be returned
+   into consecutive registers starting from r2.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (&(((void *)REGBUF)[REGISTER_BYTE(RV_REGNUM)]), (VALBUF), TYPE_LENGTH (TYPE))
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (2*sizeof(void*), (VALBUF), TYPE_LENGTH (TYPE))
+
+/* In COFF, if PCC says a parameter is a short or a char, do not
+   change it to int (it seems the convention is to change it). */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* These are just dummies for the 88k because INIT_FRAME_PC sets prev->frame
+   instead.  */
+
+#define FRAME_CHAIN(thisframe) (0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (1)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (0)
+
+/* Define other aspects of the stack frame.  */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame+4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi)  ((numargs) = -1)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+/* On the 88k, parameter registers get stored into the so called "homing"
+   area.  This *always* happens when you compiled with GCC and use -g.
+   Also, (with GCC and -g) the saving of the parameter register values
+   always happens right within the function prologue code, so these register
+   values can generally be relied upon to be already copied into their
+   respective homing slots by the time you will normally try to look at
+   them (we hope).
+
+   Note that homing area stack slots are always at *positive* offsets from
+   the frame pointer.  Thus, the homing area stack slots for the parameter
+   registers (passed values) for a given function are actually part of the
+   frame area of the caller.  This is unusual, but it should not present
+   any special problems for GDB.
+
+   Note also that on the 88k, we are only interested in finding the
+   registers that might have been saved in memory.  This is a subset of
+   the whole set of registers because the standard calling sequence allows
+   the called routine to clobber many registers.
+
+   We could manage to locate values for all of the so called "preserved"
+   registers (some of which may get saved within any particular frame) but
+   that would require decoding all of the tdesc information.  Tht would be
+   nice information for GDB to have, but it is not strictly manditory if we
+   can live without the ability to look at values within (or backup to)
+   previous frames.
+*/
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+        frame_find_saved_regs (frame_info, &frame_saved_regs)
+
+\f
+/* When popping a frame on the 88k (say when doing a return command), the
+   calling function only expects to have the "preserved" registers restored.
+   Thus, those are the only ones that we even try to restore here.   */
+
+extern void pop_frame ();
+
+#define POP_FRAME pop_frame ()
+
+/* BCS is a standard for binary compatibility.  This machine uses it.  */
+#define BCS
diff --git a/gdb/tm-merlin.h b/gdb/tm-merlin.h
new file mode 100644 (file)
index 0000000..91475c8
--- /dev/null
@@ -0,0 +1,364 @@
+/* Definitions to target GDB to a merlin under utek 2.1
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* I don't know if this will work for cross-debugging, even if you do get
+   a copy of the right include file.  */
+#include <machine/reg.h>
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc)                              \
+{ register int op = read_memory_integer (pc, 1);       \
+  if (op == 0x82)                                      \
+    { op = read_memory_integer (pc+2,1);               \
+      if ((op & 0x80) == 0) pc += 3;                   \
+      else if ((op & 0xc0) == 0x80) pc += 4;           \
+      else pc += 6;                                    \
+    }}
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+       read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0x800000)
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xf2}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0
+
+/* Define this to say that the "svc" insn is followed by
+   codes in memory saying which kind of system call it is.  */
+
+#define NS32K_SVC_IMMED_OPERANDS
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS               25
+
+#define NUM_GENERAL_REGS       8
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",        \
+                       "pc", "sp", "fp", "ps",                         \
+                       "fsr",                                          \
+                       "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+                       "l0", "l1", "l2", "l3", "l4",                   \
+                       }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define AP_REGNUM FP_REGNUM
+#define FP_REGNUM 10           /* Contains address of executing stack frame */
+#define SP_REGNUM 9            /* Contains address of top of stack */
+#define PC_REGNUM 8            /* Contains program counter */
+#define PS_REGNUM 11           /* Contains processor status */
+#define FPS_REGNUM 12          /* Floating point status register */
+#define FP0_REGNUM 13          /* Floating point register 0 */
+#define LP0_REGNUM 21          /* Double register 0 (same as FP0) */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+       LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+  ((N) >= FP0_REGNUM ?         \
+    ((N) >= LP0_REGNUM ?       \
+     builtin_type_double       \
+     : builtin_type_float)     \
+   : builtin_type_int) 
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function.
+
+   On this machine this is a no-op, as gcc doesn't run on it yet.
+   This calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the Merlin, the frame's nominal address is the FP value,
+   and at that address is saved previous FP value as a 4-byte word.  */
+
+#define FRAME_CHAIN(thisframe)  \
+  (outside_startup_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* compute base of arguments */
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi)                    \
+{ CORE_ADDR pc;                                                \
+  int insn;                                            \
+  int addr_mode;                                       \
+  int width;                                           \
+                                                       \
+  pc = FRAME_SAVED_PC (fi);                            \
+  insn = read_memory_integer (pc,2);                   \
+  addr_mode = (insn >> 11) & 0x1f;                     \
+  insn = insn & 0x7ff;                                 \
+  if ((insn & 0x7fc) == 0x57c                          \
+      && addr_mode == 0x14) /* immediate */            \
+    { if (insn == 0x57c) /* adjspb */                  \
+       width = 1;                                      \
+      else if (insn == 0x57d) /* adjspw */             \
+       width = 2;                                      \
+      else if (insn == 0x57f) /* adjspd */             \
+       width = 4;                                      \
+      numargs = read_memory_integer (pc+2,width);      \
+      if (width > 1)                                   \
+       flip_bytes (&numargs, width);                   \
+      numargs = - sign_extend (numargs, width*8) / 4; }        \
+  else numargs = -1;                                   \
+}
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ int regmask,regnum;                                          \
+  int localcount;                                              \
+  CORE_ADDR enter_addr;                                                \
+  CORE_ADDR next_addr;                                         \
+                                                               \
+  enter_addr = get_pc_function_start ((frame_info)->pc);       \
+  regmask = read_memory_integer (enter_addr+1, 1);             \
+  localcount = ns32k_localcount (enter_addr);                  \
+  next_addr = (frame_info)->frame + localcount;                        \
+  for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)                \
+    (frame_saved_regs).regs[regnum]                            \
+      = (regmask & 1) ? (next_addr -= 4) : 0;                  \
+  (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4;        \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;        \
+  (frame_saved_regs).regs[FP_REGNUM]                           \
+     = read_memory_integer ((frame_info)->frame, 4); }
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);   \
+  register int regnum;                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));      \
+  sp = push_word (sp, read_register (FP_REGNUM));      \
+  write_register (FP_REGNUM, sp);                      \
+  for (regnum = 0; regnum < 8; regnum++)               \
+    sp = push_word (sp, read_register (regnum));       \
+  write_register (SP_REGNUM, sp);                      \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                  \
+  register CORE_ADDR fp;                                        \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info *fi;                                                \
+  fi = get_frame_info (frame);                                  \
+  fp = fi->frame;                                               \
+  get_frame_saved_regs (fi, &fsr);                              \
+  for (regnum = 0; regnum < 8; regnum++)                        \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+                                      read_pc ()));             \
+}
+
+/* This sequence of words is the instructions
+     enter     0xff,0          82 ff 00
+     jsr       @0x00010203     7f ae c0 01 02 03
+     adjspd    0x69696969      7f a5 01 02 03 04
+     bpt                       f2
+   Note this is 16 bytes.  */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET        3
+#define CALL_DUMMY_LENGTH      16
+#define CALL_DUMMY_ADDR                5
+#define CALL_DUMMY_NARGS       11
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)                   \
+{ int flipped = fun | 0xc0000000;                              \
+  flip_bytes (&flipped, 4);                                    \
+  *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
+  flipped = - nargs * 4;                                       \
+  flip_bytes (&flipped, 4);                                    \
+  *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped;        \
+}
diff --git a/gdb/tm-mips.h b/gdb/tm-mips.h
new file mode 100644 (file)
index 0000000..6fd681d
--- /dev/null
@@ -0,0 +1,363 @@
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+   Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+   and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (TARGET_BYTE_ORDER)
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* Floating point is IEEE compliant */
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+/*#define NAMES_HAVE_UNDERSCORE*/
+
+/* Debugger information will be in mips' format */
+
+#define READ_MIPS_FORMAT
+
+/* File format is coff, but with additions */
+
+#define COFF_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc)      pc = mips_skip_prologue(pc)
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame)     read_register(RA_REGNUM)
+
+/* Are we currently handling a signal */
+
+#define IN_SIGTRAMP(pc, name)  in_sigtramp(pc, name)
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0x7ffff000)
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+#define BIG_ENDIAN 4321
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BREAKPOINT {0, 0x5, 0, 0xd}
+#else
+#define BREAKPOINT {0xd, 0, 0x5, 0}
+#endif
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. "j ra" on mips. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0x3e00008)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p,l)     isa_NAN(p,l)
+
+/* Say how long (all) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 73
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES         \
+    {  "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3", \
+       "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7", \
+       "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7", \
+       "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra", \
+       "sr",   "lo",   "hi",   "bad",  "cause","pc",    \
+       "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
+       "f8",   "f9",   "f10",   "f11",   "f12",   "f13",   "f14",   "f15", \
+       "f16",   "f17",   "f18",   "f19",   "f20",   "f21",   "f22",   "f23",\
+       "f24",   "f25",   "f26",   "f27",   "f28",   "f29",   "f30",   "f31",\
+       "fsr",   "fir", "fp" \
+    }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define SP_REGNUM 29           /* Contains address of top of stack */
+#define PC_REGNUM 37           /* Contains program counter */
+#define RA_REGNUM 31           /* Contains return address value */
+#define PS_REGNUM 32           /* Contains processor status */
+#define HI_REGNUM 34            /* Multiple/divide temp */
+#define LO_REGNUM 33            /* ... */
+#define FP0_REGNUM 38           /* Floating point register 0 (single float) */
+#define FCRCS_REGNUM 70         /* FP control/status */
+#define FCRIR_REGNUM 71         /* FP implementation/revision */
+#define FP_REGNUM 72           /* Pseudo register that contains true address of executing stack frame */
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+   of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum) mips_do_registers_info(_regnum)
+
+#define REGISTER_U_ADDR(addr, blockend, regno)                 \
+   if (blockend == 0) {                                        \
+       if (regno < 38) addr = (NBPG*UPAGES) + (regno - 38)*sizeof(int);\
+       else addr = 0; /* ..somewhere in the pcb */     \
+   } else if (regno < 32) addr = regno;                        \
+   else if (regno == PC_REGNUM) addr = 96;             \
+   else if (regno == 36) addr = 97;                    \
+   else if (regno == HI_REGNUM) addr = 98;             \
+   else if (regno == LO_REGNUM) addr = 99;             \
+   else if (regno == FCRCS_REGNUM) addr = 100;         \
+   else if (regno == FCRIR_REGNUM) addr = 101;         \
+   else if (regno >= FP0_REGNUM) addr = regno - (FP0_REGNUM-32);\
+   else addr = 0;
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (NUM_REGS*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On mips, all regs are 4 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On mips, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(addr, sp) \
+  { sp = push_word(sp, addr);}
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  XXX floats */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF+16))
+
+/* Structures are returned by ref in extra arg0 */
+#define USE_STRUCT_CONVENTION(gcc_p, type)     1
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+#define FRAME_CHAIN(thisframe) (FRAME_ADDR)mips_frame_chain(thisframe)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+/* We handle this differently for mips, and maybe we should not */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS)  {(FRAMELESS) = 0;}
+
+/* Saved Pc.  */
+
+#define FRAME_SAVED_PC(FRAME)  (mips_frame_saved_pc(FRAME))
+
+#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(num, fi)        (num = mips_frame_num_args(fi))
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) ( \
+  (frame_saved_regs) = *(frame_info)->saved_regs, \
+  (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame)
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Stack has strict alignment. However, use PUSH_ARGUMENTS
+   to take care of it. */
+/*#define STACK_ALIGN(addr)    (((addr)+3)&~3)*/
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+    sp = mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME       mips_push_dummy_frame()
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME              mips_pop_frame()
+
+#define MK_OP(op,rs,rt,offset) (((op)<<26)|((rs)<<21)|((rt)<<16)|(offset))
+#define CALL_DUMMY_SIZE (16*4)
+#define Dest_Reg 2
+#define CALL_DUMMY {\
+ MK_OP(0,RA_REGNUM,0,8),       /* jr $ra # Fake ABOUT_TO_RETURN ...*/\
+ 0,                            /* nop    #  ... to stop raw backtrace*/\
+ 0x27bd0000,                   /* addu sp,?0 # Pseudo prologue */\
+/* Start here: */\
+ MK_OP(061,SP_REGNUM,12,0),    /* lwc1 $f12,0(sp) # Reload first 4 args*/\
+ MK_OP(061,SP_REGNUM,13,4),    /* lwc1 $f13,4(sp) */\
+ MK_OP(061,SP_REGNUM,14,8),    /* lwc1 $f14,8(sp) */\
+ MK_OP(061,SP_REGNUM,15,12),   /* lwc1 $f15,12(sp) */\
+ MK_OP(043,SP_REGNUM,4,0),     /* lw $r4,0(sp) # Re-load FP regs*/\
+ MK_OP(043,SP_REGNUM,5,4),     /* lw $r5,4(sp) */\
+ MK_OP(043,SP_REGNUM,6,8),     /* lw $r6,8(sp) */\
+ MK_OP(043,SP_REGNUM,7,12),    /* lw $r7,12(sp) */\
+ (017<<26)| (Dest_Reg << 16),  /* lui $r31,<target upper 16 bits>*/\
+ MK_OP(13,Dest_Reg,Dest_Reg,0),        /* ori $r31,$r31,<lower 16 bits>*/ \
+ (Dest_Reg<<21) | (31<<11) | 9,        /* jalr $r31 */\
+ MK_OP(043,SP_REGNUM,7,12),    /* lw $r7,12(sp) */\
+ 0x5000d,                      /* bpt */\
+}
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, start_sp, fun, nargs,        args, rettype, gcc_p)\
+  (((int*)dummyname)[11] |= (((unsigned long)(fun)) >> 16), \
+   ((int*)dummyname)[12] |= (unsigned short)(fun))
+
+/* Specific information about a procedure.
+   This overlays the MIPS's PDR records, 
+   mipsread.c (ab)uses this to save memory */
+
+typedef struct mips_extra_func_info {
+       unsigned long   adr;    /* memory address of start of procedure */
+       long    isym;           /* pointer to procedure symbol */
+       long    pad2;           /* iline: start of line number entries*/
+       long    regmask;        /* save register mask */
+       long    regoffset;      /* save register offset */
+       long    numargs;        /* number of args to procedure (was iopt) */
+       long    fregmask;       /* save floating point register mask */
+       long    fregoffset;     /* save floating point register offset */
+       long    framesize;      /* frameoffset: frame size */
+       short   framereg;       /* frame pointer register */
+       short   pcreg;          /* offset or reg of return pc */
+       long    lnLow;          /* lowest line in the procedure */
+       long    lnHigh;         /* highest line in the procedure */
+       long    pad3;           /* cbLineOffset: byte offset for this procedure from the fd base */
+} *mips_extra_func_info_t;
+
+#define EXTRA_FRAME_INFO \
+  char *proc_desc; /* actually, a mips_extra_func_info_t */\
+  int num_args;\
+  struct frame_saved_regs *saved_regs;
+
+#define INIT_EXTRA_FRAME_INFO(fci) init_extra_frame_info(fci)
diff --git a/gdb/tm-news.h b/gdb/tm-news.h
new file mode 100644 (file)
index 0000000..ff50dbf
--- /dev/null
@@ -0,0 +1,172 @@
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* See following cpu type determination macro to get the machine type.
+  
+Here is an m-news.h file for gdb.  It supports the 68881 registers.
+                                           by hikichi@srava.sra.junet
+  
+* Support Sun assembly format instead of Motorola one.
+* Ptrace for handling floating register has a bug(before NEWS OS version 2.2),
+* After NEWS OS version 3.2, some of ptrace's bug is fixed.
+  But we cannot change the floating register(see adb(1) in OS 3.2) yet.  */
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Symbols on this machine are in DBX format. */
+#define READ_DBX_FORMAT
+
+/* Use to compute STACK_END_ADDR.  */
+#define TARGET_UPAGES 2
+#define TARGET_NBPG 4096
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0x80000000 - TARGET_UPAGES * TARGET_NBPG)
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+/* when it return the floating value, use the FP0 in NEWS.  */
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+      { \
+       REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM, \
+                              &REGBUF[REGISTER_BYTE (FP0_REGNUM)], VALBUF); \
+      } \
+    else \
+      bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE)); }
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+/* when it return the floating value, use the FP0 in NEWS.  */
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+      { \
+       char raw_buf[REGISTER_RAW_SIZE (FP0_REGNUM)]; \
+       REGISTER_CONVERT_TO_RAW (FP0_REGNUM, VALBUF, raw_buf); \
+       write_register_bytes (FP0_REGNUM, \
+                             raw_buf, REGISTER_RAW_SIZE (FP0_REGNUM)); \
+      } \
+    else \
+      write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)); }
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(val, fi)  \
+{ register CORE_ADDR pc = FRAME_SAVED_PC (fi);                 \
+  register int insn = 0177777 & read_memory_integer (pc, 2);   \
+  val = 0;                                                     \
+  if (insn == 0047757 || insn == 0157374)  /* lea W(sp),sp or addaw #W,sp */ \
+    val = read_memory_integer (pc + 2, 2);                     \
+  else if ((insn & 0170777) == 0050217 /* addql #N, sp */      \
+          || (insn & 0170777) == 0050117)  /* addqw */         \
+    { val = (insn >> 9) & 7; if (val == 0) val = 8; }          \
+  else if (insn == 0157774) /* addal #WW, sp */                        \
+    val = read_memory_integer (pc + 2, 4);                     \
+  val >>= 2; }
+
+/* Things needed for making the inferior call functions.  */
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  char raw_buffer[12];                                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));                      \
+  sp = push_word (sp, read_register (FP_REGNUM));                      \
+  write_register (FP_REGNUM, sp);                                      \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);    \
+      sp = push_bytes (sp, raw_buffer, 12); }                          \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    sp = push_word (sp, read_register (regnum));                       \
+  sp = push_word (sp, read_register (PS_REGNUM));                      \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                         \
+  register CORE_ADDR fp;                                               \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info *fi;                                               \
+  char raw_buffer[12];                                                 \
+  fi = get_frame_info (frame);                                         \
+  fp = fi->frame;                                                      \
+  get_frame_saved_regs (fi, &fsr);                                     \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    if (fsr.regs[regnum])                                              \
+      { read_memory (fsr.regs[regnum], raw_buffer, 12);                        \
+        write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    if (fsr.regs[regnum])                                              \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                             \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));             \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));         \
+  write_register (SP_REGNUM, fp + 8);                                  \
+  flush_cached_frames ();                                              \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),      \
+                                      read_pc ())); }
+
+/* This sequence of words is the instructions
+     fmove.m #<f0-f7>,-(sp)
+     movem.l 0xfffc,-(sp)     ;; no save a6(fp) and a7(sp)
+     clr.w -(sp)
+     move.w ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of 
+       the following jsr instruction.  *../
+     jbsr (#32323232)
+     add.l #69696969,sp
+     bpt
+     nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
+\f
+#define HAVE_68881
+
+#include "tm-68k.h"
diff --git a/gdb/tm-nindy960.h b/gdb/tm-nindy960.h
new file mode 100644 (file)
index 0000000..e7ed59b
--- /dev/null
@@ -0,0 +1,105 @@
+/* Parameters for Intel 960 running NINDY monitor, for GDB, the GNU debugger.
+   Copyright (C) 1990-1991 Free Software Foundation, Inc.
+   Contributed by Intel Corporation and Cygnus Support.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*****************************************************************************
+ * Definitions to target GDB to an i960 debugged over a serial line.
+ ******************************************************************************/
+
+#include "tm-i960.h"
+
+/* Override the standard gdb prompt when compiled for this target.  */
+
+#define        DEFAULT_PROMPT  "(gdb960) "
+
+/* Additional command line options accepted by nindy gdb's, for handling
+   the remote-nindy.c interface.  These should really be target-specific
+   rather than architecture-specific.  */
+
+extern int nindy_old_protocol; /* nonzero if old NINDY serial protocol */
+extern int nindy_initial_brk;  /* Send a BREAK to reset board first */
+extern char *nindy_ttyname;    /* Name of serial port to talk to nindy */
+
+#define        ADDITIONAL_OPTIONS \
+       {"O", 0, &nindy_old_protocol, 1},       \
+       {"brk", 0, &nindy_initial_brk, 1},      \
+       {"r", 1, 0, 1004},  /* 1004 is magic cookie for ADDL_CASES */
+
+#define        ADDITIONAL_OPTION_CASES \
+       case 1004:      /* -r option:  remote nindy auto-start */       \
+         nindy_ttyname = optarg;       \
+         break;
+
+#define        ADDITIONAL_OPTION_HELP \
+       "\
+  -O                Use old protocol to talk to a Nindy target\n\
+  -brk              Send a break to a Nindy target to reset it.\n\
+  -r SERIAL         Open remote Nindy session to SERIAL port.\n\
+"
+
+/* If specified on the command line, open tty for talking to nindy,
+   and download the executable file if one was specified.  */
+
+#define        ADDITIONAL_OPTION_HANDLER       \
+       if (!setjmp (to_top_level) && nindy_ttyname) {          \
+         nindy_open (nindy_ttyname, !batch);                   \
+         if ( !setjmp(to_top_level) && execarg ) {             \
+               target_load (execarg, !batch);                  \
+         }                                                     \
+       }
+
+/* If configured for i960 target, we take control before main loop
+   and demand that we configure for a nindy target.  */
+
+#define        BEFORE_MAIN_LOOP_HOOK   \
+  nindy_before_main_loop();
+
+/* Address of end of stack space.
+ *     This probably doesn't matter for nindy, because it's only used
+ *     in manipulation of core files, which we don't support.
+ */
+
+#define STACK_END_ADDR (0xfe000000)
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+   and has no caller.  In that case, FRAME_CHAIN_COMBINE is not used.
+
+   On the i960, each various target system type defines FRAME_CHAIN_VALID,
+   since it differs between NINDY and VxWorks, the two currently supported
+   targets types.  */
+
+#define        FRAME_CHAIN_VALID(chain, thisframe) \
+       nindy_frame_chain_valid (chain, thisframe)
+
+extern int nindy_frame_chain_valid();          /* See nindy-tdep.c */
+
+/* Sequence of bytes for breakpoint instruction */
+
+#define BREAKPOINT {0x00, 0x3e, 0x00, 0x66}
+
+/* Amount ip must be decremented by after a breakpoint.
+ * This is often the number of bytes in BREAKPOINT but not always.
+ */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Not needed, because we don't support core files:
+ *     #define KERNEL_U_ADDR
+ *     #define REGISTER_U_ADDR(addr, blockend, regno)
+ */
diff --git a/gdb/tm-np1.h b/gdb/tm-np1.h
new file mode 100644 (file)
index 0000000..0bb1dcc
--- /dev/null
@@ -0,0 +1,515 @@
+/* Parameters for targeting on a Gould NP1, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define GOULD_NPL
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* N_ENTRY appears in libraries on Gould machines.
+   Don't know what 0xa4 is; it's mentioned in stab.h
+   but only in the sdb symbol list.  */
+#define IGNORE_SYMBOL(type) (type == N_ENTRY || type == 0xa4)
+
+/* We don't want the extra gnu symbols on the machine;
+   they will interfere with the shared segment symbols.  */
+#define NO_GNU_STABS
+
+/* Macro for text-offset and data info (in NPL a.out format).  */
+#define        TEXTINFO                                                \
+        text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr);   \
+        exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr)\
+                + exec_aouthdr.a_text
+
+/* Macro for number of symbol table entries */
+#define NUMBER_OF_SYMBOLS                                      \
+       (coffhdr.f_nsyms)
+
+/* Macro for file-offset of symbol table (in NPL a.out format).  */
+#define SYMBOL_TABLE_OFFSET                                    \
+       N_SYMOFF (coffhdr)
+
+/* Macro for file-offset of string table (in NPL a.out format).  */
+#define STRING_TABLE_OFFSET                                    \
+       (N_STROFF (coffhdr))
+
+/* Macro to store the length of the string table data in INTO.  */
+#define READ_STRING_TABLE_SIZE(INTO)                           \
+       { INTO = hdr.a_stsize; }
+
+/* Macro to declare variables to hold the file's header data.  */
+#define DECLARE_FILE_HEADERS  struct exec hdr;                 \
+                             FILHDR coffhdr
+
+/* Macro to read the header data from descriptor DESC and validate it.
+   NAME is the file name, for error messages.  */
+#define READ_FILE_HEADERS(DESC, NAME)                          \
+{ val = myread (DESC, &coffhdr, sizeof coffhdr);               \
+  if (val < 0)                                                 \
+    perror_with_name (NAME);                                   \
+  val = myread (DESC, &hdr, sizeof hdr);                       \
+  if (val < 0)                                                 \
+    perror_with_name (NAME);                                   \
+  if (coffhdr.f_magic != GNP1MAGIC)                            \
+    error ("File \"%s\" not in coff executable format.", NAME);        \
+  if (N_BADMAG (hdr))                                          \
+    error ("File \"%s\" not in executable format.", NAME); }
+
+/* Define COFF and other symbolic names needed on NP1 */
+#define        NS32GMAGIC      GNP1MAGIC
+#define        NS32SMAGIC      GPNMAGIC
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+#define READ_DBX_FORMAT
+
+/* Address of blocks in N_LBRAC and N_RBRAC symbols are absolute addresses,
+   not relative to start of source address.  */
+#define BLOCK_ADDRESS_ABSOLUTE
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+#define FUNCTION_START_OFFSET  8
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  One NPL we can have one two startup
+   sequences depending on the size of the local stack:
+
+   Either:
+      "suabr b2, #"
+   of
+      "lil r4, #", "suabr b2, #(r4)"
+
+   "lwbr b6, #", "stw r1, 8(b2)"
+   Optional "stwbr b3, c(b2)"
+   Optional "trr r2,r7"      (Gould first argument register passing)
+     or
+   Optional "stw r2,8(b3)"   (Gould first argument register passing)
+ */
+#define SKIP_PROLOGUE(pc) {                                            \
+       register int op = read_memory_integer ((pc), 4);                \
+       if ((op & 0xffff0000) == 0xFA0B0000) {                          \
+           pc += 4;                                                    \
+           op = read_memory_integer ((pc), 4);                         \
+           if ((op & 0xffff0000) == 0x59400000) {                      \
+               pc += 4;                                                \
+               op = read_memory_integer ((pc), 4);                     \
+               if ((op & 0xffff0000) == 0x5F000000) {                  \
+                   pc += 4;                                            \
+                   op = read_memory_integer ((pc), 4);                 \
+                   if (op == 0xD4820008) {                             \
+                       pc += 4;                                        \
+                       op = read_memory_integer ((pc), 4);             \
+                       if (op == 0x5582000C) {                         \
+                           pc += 4;                                    \
+                           op = read_memory_integer ((pc), 2);         \
+                           if (op == 0x2fa0) {                         \
+                               pc += 2;                                \
+                           } else {                                    \
+                               op = read_memory_integer ((pc), 4);     \
+                               if (op == 0xd5030008) {                 \
+                                   pc += 4;                            \
+                               }                                       \
+                           }                                           \
+                       } else {                                        \
+                           op = read_memory_integer ((pc), 2);         \
+                           if (op == 0x2fa0) {                         \
+                               pc += 2;                                \
+                           }                                           \
+                       }                                               \
+                   }                                                   \
+               }                                                       \
+           }                                                           \
+       }                                                               \
+       if ((op & 0xffff0000) == 0x59000000) {                          \
+           pc += 4;                                                    \
+           op = read_memory_integer ((pc), 4);                         \
+           if ((op & 0xffff0000) == 0x5F000000) {                      \
+               pc += 4;                                                \
+               op = read_memory_integer ((pc), 4);                     \
+               if (op == 0xD4820008) {                                 \
+                   pc += 4;                                            \
+                   op = read_memory_integer ((pc), 4);                 \
+                   if (op == 0x5582000C) {                             \
+                       pc += 4;                                        \
+                       op = read_memory_integer ((pc), 2);             \
+                       if (op == 0x2fa0) {                             \
+                           pc += 2;                                    \
+                       } else {                                        \
+                           op = read_memory_integer ((pc), 4);         \
+                           if (op == 0xd5030008) {                     \
+                               pc += 4;                                \
+                           }                                           \
+                       }                                               \
+                   } else {                                            \
+                       op = read_memory_integer ((pc), 2);             \
+                       if (op == 0x2fa0) {                             \
+                           pc += 2;                                    \
+                       }                                               \
+                   }                                                   \
+               }                                                       \
+           }                                                           \
+       }                                                               \
+}
+
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  True on NPL! Return address is in R1.
+   The true return address is REALLY 4 past that location! */
+#define SAVED_PC_AFTER_CALL(frame) \
+       (read_register(R1_REGNUM) + 4)
+
+/* Address of end of stack space.  */
+#define STACK_END_ADDR                 0x7fffc000
+
+/* Stack grows downward.  */
+#define INNER_THAN             <
+
+/* Sequence of bytes for breakpoint instruction.
+   This is padded out to the size of a machine word.  When it was just
+   {0x28, 0x09} it gave problems if hit breakpoint on returning from a
+   function call.  */
+#define BREAKPOINT             {0x28, 0x09, 0x0, 0x0}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+#define DECR_PC_AFTER_BREAK    2
+
+/* Nonzero if instruction at PC is a return instruction. "bu 4(r1)" */
+#define ABOUT_TO_RETURN(pc)    (read_memory_integer (pc, 4) == 0x40100004)
+
+/* Return 1 if P points to an invalid floating point value.  */
+#define INVALID_FLOAT(p, len)  ((*(short *)p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are.  */
+#define REGISTER_TYPE          long
+
+/* Size of bytes of vector register (NP1 only), 32 elements * sizeof(int) */
+#define VR_SIZE                        128
+
+/* Number of machine registers */
+#define NUM_REGS               27
+#define NUM_GEN_REGS           16
+#define NUM_CPU_REGS           4
+#define NUM_VECTOR_REGS                7
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+#define REGISTER_NAMES { \
+  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+  "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \
+  "sp", "ps", "pc", "ve", \
+  "v1", "v2", "v3", "v4", "v5", "v6", "v7", \
+}
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+#define R1_REGNUM      1       /* Gr1 => return address of caller */
+#define R2_REGNUM      2       /* Gr2 => return value from function */
+#define R4_REGNUM      4       /* Gr4 => register save area */
+#define R5_REGNUM      5       /* Gr5 => register save area */
+#define R6_REGNUM      6       /* Gr6 => register save area */
+#define R7_REGNUM      7       /* Gr7 => register save area */
+#define B1_REGNUM      9       /* Br1 => start of this code routine */
+#define SP_REGNUM      10      /* Br2 == (sp) */
+#define AP_REGNUM      11      /* Br3 == (ap) */
+#define FP_REGNUM      16      /* A copy of Br2 saved in trap */
+#define PS_REGNUM      17      /* Contains processor status */
+#define PC_REGNUM      18      /* Contains program counter */
+#define VE_REGNUM      19      /* Vector end (user setup) register */
+#define V1_REGNUM      20      /* First vector register */
+#define V7_REGNUM      26      /* First vector register */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES \
+       (NUM_GEN_REGS*4 + NUM_VECTOR_REGS*VR_SIZE + NUM_CPU_REGS*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+#define REGISTER_BYTE(N)  \
+       (((N) < V1_REGNUM) ? ((N) * 4) : (((N) - V1_REGNUM) * VR_SIZE) + 80)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the NP1, all normal regs are 4 bytes, but
+   the vector registers are VR_SIZE*4 bytes long. */
+#define REGISTER_RAW_SIZE(N) \
+       (((N) < V1_REGNUM) ? 4 : VR_SIZE)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the NP1, all regs are 4 bytes. */
+#define REGISTER_VIRTUAL_SIZE(N) \
+       (((N) < V1_REGNUM) ? 4 : VR_SIZE)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+#define MAX_REGISTER_RAW_SIZE          VR_SIZE
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+#define MAX_REGISTER_VIRTUAL_SIZE      VR_SIZE
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+#define REGISTER_CONVERTIBLE(N)                (0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+       bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+       bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+#define REGISTER_VIRTUAL_TYPE(N)       \
+  ((N) > VE_REGNUM ? builtin_type_np1_vector : builtin_type_int)
+extern struct type *builtin_type_np1_vector;
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function.
+
+   On this machine this is a no-op, because gcc isn't used on it
+   yet.  So this calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) push_word(SP + 8, ADDR)
+
+/* Extract from an arrary REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+       bcopy (((int *)(REGBUF)) + 2, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+       write_register_bytes (REGISTER_BYTE (R2_REGNUM), VALBUF,      \
+                             TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*((int *)(REGBUF) + 2))
+
+/* Both gcc and cc return small structs in registers (i.e. in GDB
+   terminology, small structs don't use the struct return convention).  */
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH(type) > 8)
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the NPL, the frame's norminal address is Br2 and the 
+   previous routines frame is up the stack X bytes, where X is the
+   value stored in the code function header xA(Br1). */
+#define FRAME_CHAIN(thisframe)         (findframe(thisframe))
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+        (chain != 0 && chain != (thisframe)->frame)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) \
+       (chain)
+
+/* Define other aspects of the stack frame on NPL.  */
+#define FRAME_SAVED_PC(FRAME) \
+       (read_memory_integer ((FRAME)->frame + 8, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) \
+       ((fi)->next_frame ? \
+        read_memory_integer ((fi)->frame + 12, 4) : \
+        read_register (AP_REGNUM))
+
+#define FRAME_LOCALS_ADDRESS(fi)       ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+   Can set VAL to -1, meaning no way to tell.  */
+
+/* We can check the stab info to see how
+   many arg we have.  No info in stack will tell us */
+#define FRAME_NUM_ARGS(val,fi)         (val = findarg(fi))
+
+/* Return number of bytes at start of arglist that are not really args.  */
+#define FRAME_ARGS_SKIP                        8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{                                                                       \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  (frame_saved_regs).regs[SP_REGNUM] = framechain (frame_info);         \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8;                \
+  (frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30;     \
+  (frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34;     \
+  (frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38;     \
+  (frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C;     \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+
+#define CANNOT_EXECUTE_STACK
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+  register int regnum;                               \
+  for (regnum = 0; regnum < FP_REGNUM; regnum++)     \
+    sp = push_word (sp, read_register (regnum));     \
+  sp = push_word (sp, read_register (PS_REGNUM));    \
+  sp = push_word (sp, read_register (PC_REGNUM));    \
+  write_register (SP_REGNUM, sp);}
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+
+#define POP_FRAME  \
+{ CORE_ADDR sp = read_register(SP_REGNUM);             \
+  REGISTER_TYPE reg;                                   \
+  int regnum;                                          \
+  for(regnum = 0;regnum < FP_REGNUM;regnum++){         \
+    sp-=sizeof(REGISTER_TYPE);                         \
+    read_memory(sp,&reg,sizeof(REGISTER_TYPE));        \
+    write_register(regnum,reg);}                       \
+  sp-=sizeof(REGISTER_TYPE);                           \
+  read_memory(sp,&reg,sizeof(REGISTER_TYPE));          \
+  write_register(PS_REGNUM,reg);                       \
+  sp-=sizeof(REGISTER_TYPE);                           \
+  read_memory(sp,&reg,sizeof(REGISTER_TYPE));          \
+  write_register(PC_REGNUM,reg);}
+
+/* MJD - Size of dummy frame pushed onto stack by PUSH_DUMMY_FRAME */
+
+#define DUMMY_FRAME_SIZE (0x48)
+
+/* MJD - The sequence of words in the instructions is
+   halt
+   halt
+   halt
+   halt
+   subr    b2,stack size,0             grab stack space for dummy call
+   labr    b3,x0(b2),0                 set AP_REGNUM to point at arguments
+   lw      r2,x8(b3),0                 load r2 with first argument    
+   lwbr    b1,arguments size(b2),0     load address of function to be called
+   brlnk   r1,x8(b1),0                 call function
+   halt
+   halt
+   labr    b2,stack size(b2),0         give back stack
+   break                               break
+   */
+
+#define CALL_DUMMY {0x00000000,  \
+                   0x00000000,  \
+                   0x59000000,  \
+                   0x598a0000,  \
+                   0xb5030008,  \
+                   0x5c820000,  \
+                   0x44810008,  \
+                   0x00000000,  \
+                   0x590a0000,  \
+                   0x28090000 }
+
+#define CALL_DUMMY_LENGTH 40
+
+#define CALL_DUMMY_START_OFFSET 8
+
+#define CALL_DUMMY_STACK_ADJUST 8
+
+/* MJD - Fixup CALL_DUMMY for the specific function call.
+   OK heres the problems
+   1) On a trap there are two copies of the stack pointer, one in SP_REGNUM
+      which is read/write and one in FP_REGNUM which is only read. It seems
+      that when restarting the GOULD NP1 uses FP_REGNUM's value.
+   2) Loading function address into b1 looks a bit difficult if bigger than
+      0x0000fffc, infact from what I can tell the compiler sets up table of
+      function address in base3 through which function calls are referenced.
+
+   OK my solutions
+     Calculate the size of the dummy stack frame and do adjustments of
+     SP_REGNUM in the dummy call.
+     Push function address onto the stack and load it in the dummy call
+ */
+
+#define FIX_CALL_DUMMY(dummyname, sp, fun, nargs, args, type, gcc_p) \
+  {   int i;\
+      int arg_len = 0, total_len;\
+      old_sp = push_word(old_sp,fun);\
+      for(i = nargs - 1;i >= 0;i--)\
+       arg_len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));\
+      if(struct_return)\
+       arg_len += TYPE_LENGTH(value_type);\
+      total_len = DUMMY_FRAME_SIZE+CALL_DUMMY_STACK_ADJUST+4+arg_len;\
+      dummyname[0] += total_len;\
+      dummyname[2] += total_len;\
+      dummyname[5] += arg_len+CALL_DUMMY_STACK_ADJUST;\
+      dummyname[8] += total_len;}
+
+/* MJD - So the stack should end up looking like this
+
+                   | Normal stack frame  |
+                   | from normal program |
+                   | flow                |
+                   +---------------------+ <- Final sp - 0x08 - argument size
+                   |                     |    - 0x4 - dummy_frame_size
+                   | Pushed dummy frame  |
+                   |  b0-b7, r0-r7       |
+                   |  pc and ps          |
+                   |                     |
+                   +---------------------+
+                   | Function address    |
+                   +---------------------+ <- Final sp - 0x8 - arguments size
+                   |                     |
+                   |                     |
+                   |                     |
+                   |  Arguments to       |
+                   |       Function      |
+                   |                     |
+                   |                     |
+                   |                     |
+                   +---------------------+ <- Final sp - 0x8
+                   | Dummy_stack_adjust  |
+                   +---------------------+ <- Final sp
+                   |                     |
+                   | where call will     |
+                   |   build frame       |
+*/
diff --git a/gdb/tm-pn.h b/gdb/tm-pn.h
new file mode 100644 (file)
index 0000000..82bf919
--- /dev/null
@@ -0,0 +1,444 @@
+/* Parameters for targe of a Gould Powernode, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define GOULD_PN
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* This code appears in libraries on Gould machines.  Ignore it. */
+#define IGNORE_SYMBOL(type) (type == N_ENTRY)
+
+/* We don't want the extra gnu symbols on the machine;
+   they will interfere with the shared segment symbols.  */
+#define NO_GNU_STABS
+
+/* Macro for text-offset and data info (in PN a.out format).  */
+#define        TEXTINFO                                                \
+       text_offset = N_TXTOFF (exec_coffhdr);                  \
+       exec_data_offset = N_TXTOFF (exec_coffhdr)              \
+               + exec_aouthdr.a_text
+
+/* Macro for number of symbol table entries */
+#define END_OF_TEXT_DEFAULT                                    \
+       (0xffffff)
+
+/* Macro for number of symbol table entries */
+#define NUMBER_OF_SYMBOLS                                      \
+       (coffhdr.f_nsyms)
+
+/* Macro for file-offset of symbol table (in usual a.out format).  */
+#define SYMBOL_TABLE_OFFSET                                    \
+       N_SYMOFF (coffhdr)
+
+/* Macro for file-offset of string table (in usual a.out format).  */
+#define STRING_TABLE_OFFSET                                    \
+       (N_STROFF (coffhdr) + sizeof(int))
+
+/* Macro to store the length of the string table data in INTO.  */
+#define READ_STRING_TABLE_SIZE(INTO)                           \
+       { INTO = hdr.a_stsize; }
+
+/* Macro to declare variables to hold the file's header data.  */
+#define DECLARE_FILE_HEADERS  struct old_exec hdr;             \
+                             FILHDR coffhdr
+
+/* Macro to read the header data from descriptor DESC and validate it.
+   NAME is the file name, for error messages.  */
+#define READ_FILE_HEADERS(DESC, NAME)                          \
+{ val = myread (DESC, &coffhdr, sizeof coffhdr);               \
+  if (val < 0)                                                 \
+    perror_with_name (NAME);                                   \
+  val = myread (DESC, &hdr, sizeof hdr);                       \
+  if (val < 0)                                                 \
+    perror_with_name (NAME);                                   \
+  if (coffhdr.f_magic != GNP1MAGIC)                            \
+    error ("File \"%s\" not in coff executable format.", NAME);        \
+  if (N_BADMAG (hdr))                                          \
+    error ("File \"%s\" not in executable format.", NAME); }
+
+/* Define COFF and other symbolic names needed on NP1 */
+#define        NS32GMAGIC      GDPMAGIC
+#define        NS32SMAGIC      PN_MAGIC
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+#define FUNCTION_START_OFFSET  4
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  One PN we can have one or two startup
+   sequences depending on the size of the local stack:
+
+   Either:
+      "suabr b2, #"
+   of
+      "lil r4, #", "suabr b2, #(r4)"
+
+   "lwbr b6, #", "stw r1, 8(b2)"
+   Optional "stwbr b3, c(b2)"
+   Optional "trr r2,r7"      (Gould first argument register passing)
+     or
+   Optional "stw r2,8(b3)"   (Gould first argument register passing)
+ */
+#define SKIP_PROLOGUE(pc) {                                            \
+       register int op = read_memory_integer ((pc), 4);                \
+       if ((op & 0xffff0000) == 0x580B0000) {                          \
+           pc += 4;                                                    \
+           op = read_memory_integer ((pc), 4);                         \
+           if ((op & 0xffff0000) == 0x59400000) {                      \
+               pc += 4;                                                \
+               op = read_memory_integer ((pc), 4);                     \
+               if ((op & 0xffff0000) == 0x5F000000) {                  \
+                   pc += 4;                                            \
+                   op = read_memory_integer ((pc), 4);                 \
+                   if (op == 0xD4820008) {                             \
+                       pc += 4;                                        \
+                       op = read_memory_integer ((pc), 4);             \
+                       if (op == 0x5582000C) {                         \
+                           pc += 4;                                    \
+                           op = read_memory_integer ((pc), 2);         \
+                           if (op == 0x2fa0) {                         \
+                               pc += 2;                                \
+                           } else {                                    \
+                               op = read_memory_integer ((pc), 4);     \
+                               if (op == 0xd5030008) {                 \
+                                   pc += 4;                            \
+                               }                                       \
+                           }                                           \
+                       } else {                                        \
+                           op = read_memory_integer ((pc), 2);         \
+                           if (op == 0x2fa0) {                         \
+                               pc += 2;                                \
+                           }                                           \
+                       }                                               \
+                   }                                                   \
+               }                                                       \
+           }                                                           \
+       }                                                               \
+       if ((op & 0xffff0000) == 0x59000000) {                          \
+           pc += 4;                                                    \
+           op = read_memory_integer ((pc), 4);                         \
+           if ((op & 0xffff0000) == 0x5F000000) {                      \
+               pc += 4;                                                \
+               op = read_memory_integer ((pc), 4);                     \
+               if (op == 0xD4820008) {                                 \
+                   pc += 4;                                            \
+                   op = read_memory_integer ((pc), 4);                 \
+                   if (op == 0x5582000C) {                             \
+                       pc += 4;                                        \
+                       op = read_memory_integer ((pc), 2);             \
+                       if (op == 0x2fa0) {                             \
+                           pc += 2;                                    \
+                       } else {                                        \
+                           op = read_memory_integer ((pc), 4);         \
+                           if (op == 0xd5030008) {                     \
+                               pc += 4;                                \
+                           }                                           \
+                       }                                               \
+                   } else {                                            \
+                       op = read_memory_integer ((pc), 2);             \
+                       if (op == 0x2fa0) {                             \
+                           pc += 2;                                    \
+                       }                                               \
+                   }                                                   \
+               }                                                       \
+           }                                                           \
+       }                                                               \
+}
+
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  True on PN!  Return address is in R1.
+   Note: true return location is 4 bytes past R1! */
+#define SAVED_PC_AFTER_CALL(frame) \
+       (read_register(R1_REGNUM) + 4)
+
+/* Address of end of stack space.  */
+#define STACK_END_ADDR                 0x480000
+
+/* Stack grows downward.  */
+#define INNER_THAN             <
+
+/* Sequence of bytes for breakpoint instruction.  */
+#define BREAKPOINT             {0x28, 0x09}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+#define DECR_PC_AFTER_BREAK    2
+
+/* Nonzero if instruction at PC is a return instruction. "bu 4(r1)" */
+#define ABOUT_TO_RETURN(pc)    (read_memory_integer (pc, 4) == 0xEC100004)
+
+/* Return 1 if P points to an invalid floating point value.  */
+#define INVALID_FLOAT(p, len)  ((*(short *)p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are.  */
+#define REGISTER_TYPE          long
+
+/* Number of machine registers */
+#define NUM_REGS               19
+#define NUM_GEN_REGS           16
+#define NUM_CPU_REGS           3
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+#define REGISTER_NAMES { \
+  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+  "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \
+  "sp", "ps", "pc", \
+}
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+#define R1_REGNUM      1       /* Gr1 => return address of caller */
+#define R4_REGNUM      4       /* Gr4 => register save area */
+#define R5_REGNUM      5       /* Gr5 => register save area */
+#define R6_REGNUM      6       /* Gr6 => register save area */
+#define R7_REGNUM      7       /* Gr7 => register save area */
+#define B1_REGNUM      9       /* Br1 => start of this code routine */
+#define FP_REGNUM      10      /* Br2 == (sp) */
+#define AP_REGNUM      11      /* Br3 == (ap) */
+#define SP_REGNUM      16      /* A copy of Br2 saved in trap */
+#define PS_REGNUM      17      /* Contains processor status */
+#define PC_REGNUM      18      /* Contains program counter */
+
+/* This is a piece of magic that is given a register number REGNO
+   and as BLOCKEND the address in the system of the end of the user structure
+   and stores in ADDR the address in the kernel or core dump
+   of that register. */
+#define REGISTER_U_ADDR(addr, blockend, regno) {                       \
+       addr = blockend + regno * 4;                                    \
+       if (regno == PC_REGNUM) addr = blockend - 8 * 4;                \
+       if (regno == PS_REGNUM) addr = blockend - 7 * 4;                \
+       if (regno == SP_REGNUM) addr = blockend - 6 * 4;                \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES                 (NUM_GEN_REGS*4 + NUM_CPU_REGS*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+#define REGISTER_BYTE(N)               ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the PN, all normal regs are 4 bytes. */
+#define REGISTER_RAW_SIZE(N)           (4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the PN, all regs are 4 bytes. */
+#define REGISTER_VIRTUAL_SIZE(N)       (4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+#define MAX_REGISTER_RAW_SIZE          (4)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+#define MAX_REGISTER_VIRTUAL_SIZE      (4)
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+#define REGISTER_CONVERTIBLE(N)                (0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+       bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+       bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+#define REGISTER_VIRTUAL_TYPE(N)       (builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function.
+
+   On this machine this is a no-op, because gcc isn't used on it
+   yet.  So this calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an arrary REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+       bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+       write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the NPL, the frame's norminal address is Br2 and the 
+   previous routines frame is up the stack X bytes, where X is the
+   value stored in the code function header xA(Br1). */
+#define FRAME_CHAIN(thisframe)         (findframe(thisframe))
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+        (chain != 0 && chain != (thisframe)->frame)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) \
+       (chain)
+
+/* Define other aspects of the stack frame on NPL.  */
+#define FRAME_SAVED_PC(frame) \
+       (read_memory_integer ((frame)->frame + 8, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) \
+       ((fi)->next_frame ? \
+        read_memory_integer ((fi)->frame + 12, 4) : \
+        read_register (AP_REGNUM))
+
+#define FRAME_LOCALS_ADDRESS(fi)       ((fi)->frame + 80)
+
+/* Set VAL to the number of args passed to frame described by FI.
+   Can set VAL to -1, meaning no way to tell.  */
+
+/* We can check the stab info to see how
+   many arg we have.  No info in stack will tell us */
+#define FRAME_NUM_ARGS(val,fi)         (val = findarg(fi))
+
+/* Return number of bytes at start of arglist that are not really args.  */
+#define FRAME_ARGS_SKIP                        8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{                                                                       \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8;                \
+  (frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30;     \
+  (frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34;     \
+  (frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38;     \
+  (frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C;     \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));                      \
+  sp = push_word (sp, read_register (FP_REGNUM));                      \
+  write_register (FP_REGNUM, sp);                                      \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    sp = push_word (sp, read_register (regnum));                       \
+  sp = push_word (sp, read_register (PS_REGNUM));                      \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                  \
+  register CORE_ADDR fp;                                        \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info *fi;                                        \
+  fi = get_frame_info (frame);                                  \
+  fp = fi->frame;                                               \
+  get_frame_saved_regs (fi, &fsr);                              \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)           \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                      \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions:
+     halt
+     halt
+     halt
+     halt
+     suabr     b2, #<stacksize>
+     lwbr      b6, #con
+     stw       r1, 8(b2)       - save caller address, do we care?
+     lw                r2, 60(b2)      - arg1
+     labr      b3, 50(b2)
+     std       r4, 30(b2)      - save r4-r7
+     std       r6, 38(b2)
+     lwbr      b1, #<func>     - load function call address
+     brlnk     r1, 8(b1)       - call function
+     halt
+     halt
+     ld                r4, 30(b2)      - restore r4-r7
+     ld                r6, 38(b2)
+
+   Setup our stack frame, load argumemts, call and then restore registers.
+*/
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
diff --git a/gdb/tm-pyr.h b/gdb/tm-pyr.h
new file mode 100644 (file)
index 0000000..e37f8f5
--- /dev/null
@@ -0,0 +1,530 @@
+/* Definitions to make GDB run on a Pyramidax under OSx 4.0 (4.2bsd).
+   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Traditional Unix virtual address spaces have thre regions: text,
+   data and stack.  The text, initialised data, and uninitialised data
+   are represented in separate segments of the a.out file.
+   When a process dumps core, the data and stack regions are written
+   to a core file.  This gives a debugger enough information to
+   reconstruct (and debug) the virtual address space at the time of
+   the coredump.
+   Pyramids have an distinct fourth region of the virtual address
+   space, in which the contents of the windowed registers are stacked
+   in fixed-size frames.  Pyramid refer to this region as the control
+   stack.  Each call (or trap) automatically allocates a new register
+   frame; each return deallocates the current frame and restores the
+   windowed registers to their values before the call.
+
+   When dumping core, the control stack is written to a core files as
+   a third segment. The core-handling functions need to know to deal
+   with it. */ 
+/* Tell core.c there is an extra segment.  */
+#define REG_STACK_SEGMENT
+
+/* Floating point is IEEE compatible on most Pyramid hardware
+   (Older processors do not have IEEE NaNs).  */
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+/* FIXME -- do we want to skip insns to allocate the local frame?
+   If so, what do they look like?
+   This is becoming harder, since tege@sics.SE wants to change
+   gcc to not output a prologue when no frame is needed.   */
+#define SKIP_PROLOGUE(pc)  do {} while (0)
+
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
+
+/* Address of end of stack space.  */
+/* This seems to be right for the 90x comp.vuw.ac.nz.
+   The correct value at any site may be a function of the configured
+   maximum control stack depth.  If so, I don't know where the
+   control-stack depth is configured, so I can't #include it here. */ 
+#define STACK_END_ADDR (0xc00cc000)
+
+/* Register window stack (Control stack) stack definitions
+    - Address of beginning of control stack.
+    - size of control stack frame
+   (Note that since crts0 is usually the first function called,
+    main()'s control stack is one frame (0x80 bytes) beyond this value.  */
+
+#define CONTROL_STACK_ADDR (0xc00cd000)
+
+/* Bytes in a register window -- 16 parameter regs, 16 local regs
+   for each call, is 32 regs * 4 bytes */
+
+#define CONTROL_STACK_FRAME_SIZE (32*4)
+
+/* FIXME.  On a pyr, Data Stack grows downward; control stack goes upwards. 
+   Which direction should we use for INNER_THAN, PC_INNER_THAN ?? */
+
+#define INNER_THAN <
+#define PC_INNER_THAN >
+
+/* Stack has strict alignment.  */
+
+#define STACK_ALIGN(ADDR) (((ADDR)+3)&-4)
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xf0, 00, 00, 00}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. 
+   On a pyr, this is either "ret" or "retd".
+   It would be friendly to check that any "retd" always had an
+   argument of 0, since anything else is invalid. */
+
+#define ABOUT_TO_RETURN(pc) \
+(((read_memory_integer (pc, 2) & 0x3ff0) == 0x3090) || \
+ ((read_memory_integer (pc, 2) & 0x0ff0) == 0x00a0))
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes -- not relevant on the Vax.  */
+/* FIXME -- this is ok for a vax, bad for big-endian ieee format.
+   I would use the definition for a Sun; but it is no better! */
+
+#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+/* pyramids have 64, plus one for the PSW; plus perhaps one more for the
+   kernel stack pointer (ksp) and control-stack pointer (CSP) */
+
+#define NUM_REGS 67
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES \
+{"gr0", "gr1", "gr2", "gr3", "gr4", "gr5", "gr6", "gr7", \
+ "gr8", "gr9", "gr10", "gr11", "logpsw", "cfp", "sp", "pc", \
+ "pr0", "pr1", "pr2", "pr3", "pr4", "pr5", "pr6", "pr7", \
+ "pr8", "pr9", "pr10", "pr11", "pr12", "pr13", "pr14", "pr15", \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", \
+ "lr8", "lr9", "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", \
+ "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7", \
+ "tr8", "tr9", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15", \
+  "psw", "ksp", "csp"}
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+/* pseudo-registers: */
+#define PS_REGNUM 64           /* Contains processor status */
+#define PSW_REGNUM 64          /* Contains current psw, whatever it is.*/
+#define CSP_REGNUM 65          /* address of this control stack frame*/
+#define KSP_REGNUM 66          /* Contains process's Kernel Stack Pointer */
+
+#define CFP_REGNUM 13          /* Current data-stack frame ptr */
+#define TR0_REGNUM 48          /* After function call, contains
+                                  function result */
+
+/* Registers interesting to the machine-independent part of gdb*/
+
+#define FP_REGNUM CSP_REGNUM   /* Contains address of executing (control)
+                                  stack frame */
+#define SP_REGNUM 14           /* Contains address of top of stack -??*/
+#define PC_REGNUM 15           /* Contains program counter */
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+   of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum) pyr_do_registers_info(_regnum)
+
+/* need this so we can find the global registers: they never get saved. */
+extern unsigned int global_reg_offset;
+extern unsigned int last_frame_offset;
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (NUM_REGS*4)
+
+/* the Pyramid has register windows.  */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system?  A yes answer
+   implies that 1) The name of this register will not be the same in
+   other frames, and 2) This register is automatically "saved" (out
+   registers shifting into ins counts) upon subroutine calls and thus
+   there is no need to search more than one stack frame for it. */
+
+#define REGISTER_IN_WINDOW_P(regnum)   \
+  ((regnum) >= 16 && (regnum) < 64)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the Pyramid, all regs are 4 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the Pyramid, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* FIXME: It seems impossible for both EXTRACT_RETURN_VALUE and
+   STORE_RETURN_VALUE to be correct. */
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+/****FIXME****/
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { write_register (TR0_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+/* Note that on a register-windowing machine (eg, Pyr, SPARC), this is
+   where the value is found after the function call -- ie, it should
+   correspond to GNU CC's FUNCTION_VALUE rather than FUNCTION_OUTGOING_VALUE.*/
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (((int *)(REGBUF))+TR0_REGNUM, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+/* on pyrs, values are returned in */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (REGISTER_BYTE(TR0_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+/* FIXME */
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+  ( ((int *)(REGBUF)) [TR0_REGNUM])
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+#define EXTRA_FRAME_INFO \
+       FRAME_ADDR bottom;      \
+       CORE_ADDR frame_cfp;    \
+       CORE_ADDR frame_window_addr;
+
+#define INIT_EXTRA_FRAME_INFO(fci)  \
+do {                                                           \
+  (fci)->frame_window_addr = (fci)->frame;                     \
+  (fci)->bottom =                                              \
+         ((fci)->next ?                                        \
+          ((fci)->frame == (fci)->next_frame ?                 \
+           (fci)->next->bottom : (fci)->next->frame) :         \
+          read_register (SP_REGNUM));                          \
+  (fci)->frame_cfp =                                           \
+         read_register (CFP_REGNUM);                           \
+  /***fprintf (stderr,                                         \
+          "[[creating new frame for %0x,pc=%0x,csp=%0x]]\n",   \
+          (fci)->frame, (fci)->pc,(fci)->frame_cfp);*/         \
+} while (0);
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the pyr, the frame's nominal address is the address
+   of parameter register 0.  The previous frame is found 32 words up.   */
+
+#define FRAME_CHAIN(thisframe) \
+  ( (thisframe) -> frame - CONTROL_STACK_FRAME_SIZE)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+ /*((thisframe) >= CONTROL_STACK_ADDR))*/
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.
+
+   I do not understand what this means on a Pyramid, where functions
+   *always* have a control-stack frame, but may or may not have a
+   frame on the data stack.  Since GBD uses the value of the
+   control stack pointer as its "address" of a frame, FRAMELESS
+   is always 1, so does not need to be defined.  */
+
+
+/* Where is the PC for a specific frame */
+
+#define FRAME_SAVED_PC(fi) \
+  ((CORE_ADDR) (read_memory_integer ( (fi) -> frame + 60, 4)))
+
+/* There may be bugs in FRAME_ARGS_ADDRESS and FRAME_LOCALS_ADDRESS;
+   or there may be bugs in accessing the registers that break
+   their definitions.
+   Having the macros expand into functions makes them easier to debug.
+   When the bug is finally located, the inline macro defintions can
+   be un-#if 0ed, and frame_args_addr and frame_locals_address can
+   be deleted from pyr-dep.c */ 
+
+/* If the argument is on the stack, it will be here.  */
+#define FRAME_ARGS_ADDRESS(fi) \
+  frame_args_addr(fi)
+
+#define FRAME_LOCALS_ADDRESS(fi) \
+  frame_locals_address(fi)
+
+/* The following definitions doesn't seem to work.
+   I don't understand why. */
+#if 0
+#define FRAME_ARGS_ADDRESS(fi) \
+   /*(FRAME_FP(fi) + (13*4))*/ (read_register (CFP_REGNUM))
+
+#define FRAME_LOCALS_ADDRESS(fi) \
+  ((fi)->frame +(16*4))
+
+#endif /* 0 */
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(val, fi)  (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.
+
+   Note that on register window machines, we are currently making the
+   assumption that window registers are being saved somewhere in the
+   frame in which they are being used.  If they are stored in an
+   inferior frame, find_saved_register will break.
+
+   On pyrs, frames of window registers are stored contiguously on a
+   separate stack.  All window registers are always stored.
+   The pc and psw (gr15 and gr14)  are also always saved: the call
+   insn saves them in pr15 and pr14 of the new frame (tr15,tr14 of the
+   old frame).  
+   The data-stack frame pointer (CFP) is only saved in functions which
+   allocate a (data)stack frame (with "adsf").  We detect them by
+   looking at the first insn of the procedure. 
+
+   Other non-window registers (gr0-gr11) are never saved.  Pyramid's C
+   compiler and gcc currently ignore them, so it's not an issue.   */ 
+
+#define FRAME_FIND_SAVED_REGS(fi_p, frame_saved_regs) \
+{  register int regnum;                                                        \
+  register CORE_ADDR pc;                                               \
+  register CORE_ADDR fn_start_pc;                                      \
+  register int first_insn;                                             \
+  register CORE_ADDR prev_cf_addr;                                     \
+  register int window_ptr;                                             \
+  FRAME fid = FRAME_INFO_ID (fi_p);                                    \
+  if (!fid) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS");  \
+  bzero (&(frame_saved_regs), sizeof (frame_saved_regs));              \
+                                                                       \
+  window_ptr = prev_cf_addr = FRAME_FP(fi_p);                          \
+                                                                       \
+  for (regnum = 16 ; regnum < 64; regnum++,window_ptr+=4)              \
+  {                                                                    \
+    (frame_saved_regs).regs[regnum] = window_ptr;                      \
+  }                                                                    \
+                                                                       \
+  /* In each window, psw, and pc are "saved" in tr14,tr15. */          \
+  /*** psw is sometimes saved in gr12 (so sez <sys/pcb.h>) */          \
+  (frame_saved_regs).regs[PS_REGNUM] = FRAME_FP(fi_p) + (14*4);        \
+                                                                       \
+/*(frame_saved_regs).regs[PC_REGNUM] = (frame_saved_regs).regs[31];*/  \
+  (frame_saved_regs).regs[PC_REGNUM] = FRAME_FP(fi_p) + ((15+32)*4);   \
+                                                                       \
+  /* Functions that allocate a frame save sp *where*? */               \
+/*first_insn = read_memory_integer (get_pc_function_start ((fi_p)->pc),4); */ \
+                                                                       \
+  fn_start_pc = (get_pc_function_start ((fi_p)->pc));                  \
+  first_insn = read_memory_integer(fn_start_pc, 4);                    \
+                                                                       \
+  if (0x08 == ((first_insn >> 20) &0x0ff)) {                           \
+    /* NB: because WINDOW_REGISTER_P(cfp) is false, a saved cfp                \
+       in this frame is only visible in this frame's callers.          \
+       That means the cfp we mark saved is my caller's cfp, ie pr13.   \
+       I don't understand why we don't have to do that for pc, too.  */        \
+                                                                       \
+    (frame_saved_regs).regs[CFP_REGNUM] = FRAME_FP(fi_p)+(13*4);       \
+                                                                       \
+    (frame_saved_regs).regs[SP_REGNUM] =                               \
+         read_memory_integer (FRAME_FP(fi_p)+((13+32)*4),4);           \
+  }                                                                    \
+                                                                       \
+/*                                                                     \
+ *(frame_saved_regs).regs[CFP_REGNUM] = (frame_saved_regs).regs[61];   \
+ * (frame_saved_regs).regs[SP_REGNUM] =                                        \
+ *       read_memory_integer (FRAME_FP(fi_p)+((13+32)*4),4);           \
+ */                                                                    \
+                                                                       \
+  (frame_saved_regs).regs[CSP_REGNUM] = prev_cf_addr;                  \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+#if 0
+/* These are all lies.  These macro definitions are appropriate for a
+    SPARC. On a pyramid, pushing a dummy frame will
+   surely involve writing the control stack pointer,
+   then saving the pc.  This requires a privileged instruction.
+   Maybe one day Pyramid can be persuaded to add a syscall to do this.
+   Until then, we are out of luck. */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+  register int regnum;                             \
+  sp = push_word (sp, 0); /* arglist */                    \
+  for (regnum = 11; regnum >= 0; regnum--)         \
+    sp = push_word (sp, read_register (regnum));    \
+  sp = push_word (sp, read_register (PC_REGNUM));   \
+  sp = push_word (sp, read_register (FP_REGNUM));   \
+/*  sp = push_word (sp, read_register (AP_REGNUM));*/   \
+  sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef)   \
+                     + 0x2fff0000);                \
+  sp = push_word (sp, 0);                          \
+  write_register (SP_REGNUM, sp);                  \
+  write_register (FP_REGNUM, sp);                  \
+/*  write_register (AP_REGNUM, sp + 17 * sizeof (int));*/ }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  register int regmask = read_memory_integer (fp + 4, 4);       \
+  write_register (PS_REGNUM,                                    \
+                 (regmask & 0xffff)                             \
+                 | (read_register (PS_REGNUM) & 0xffff0000));   \
+  write_register (PC_REGNUM, read_memory_integer (fp + 16, 4));  \
+  write_register (FP_REGNUM, read_memory_integer (fp + 12, 4));  \
+/*  write_register (AP_REGNUM, read_memory_integer (fp + 8, 4));*/   \
+  fp += 16;                                                     \
+  for (regnum = 0; regnum < 12; regnum++)                       \
+    if (regmask & (0x10000 << regnum))                          \
+      write_register (regnum, read_memory_integer (fp += 4, 4)); \
+  fp = fp + 4 + ((regmask >> 30) & 3);                          \
+  if (regmask & 0x20000000)                                     \
+    { regnum = read_memory_integer (fp, 4);                     \
+      fp += (regnum + 1) * 4; }                                         \
+  write_register (SP_REGNUM, fp);                               \
+  set_current_frame (read_register (FP_REGNUM)); }
+
+/* This sequence of words is the instructions
+     calls #69, @#32323232
+     bpt
+   Note this is 8 bytes.  */
+
+#define CALL_DUMMY {0x329f69fb, 0x03323232}
+
+#define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)   \
+{ *((char *) dummyname + 1) = nargs;           \
+  *(int *)((char *) dummyname + 3) = fun; }
+#endif /* 0 */
+
+#define POP_FRAME \
+  { error ("The return command is not supported on this machine."); }
diff --git a/gdb/tm-sparc.h b/gdb/tm-sparc.h
new file mode 100644 (file)
index 0000000..b3316da
--- /dev/null
@@ -0,0 +1,586 @@
+/* Parameters for target machine of Sun 4, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+   Contributed by Michael Tiemann (tiemann@mcc.com)
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Floating point is IEEE compatible.  */
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* When passing a structure to a function, Sun cc passes the address
+   in a register, not the structure itself.  It (under SunOS4) creates
+   two symbols, so we get a LOC_ARG saying the address is on the stack
+   (a lie, and a serious one since we don't know which register to
+   use), and a LOC_REGISTER saying that the struct is in a register
+   (sort of a lie, but fixable with REG_STRUCT_HAS_ADDR).
+
+   This still doesn't work if the argument is not one passed in a
+   register (i.e. it's the 7th or later argument).  */
+#define REG_STRUCT_HAS_ADDR(gcc_p) (!(gcc_p))
+#define STRUCT_ARG_SYM_GARBAGE(gcc_p) (!(gcc_p))
+
+/* If Pcc says that a parameter is a short, it's a short.  This is
+   because the parameter does get passed in in a register as an int,
+   but pcc puts it onto the stack frame as a short (not nailing
+   whatever else might be there.  I'm not sure that I consider this
+   swift.  Sigh.)
+
+   No, don't do this.  The problem here is that pcc says that the
+   argument is in the upper half of the word reserved on the stack,
+   but puts it in the lower half.  */
+/* #define BELIEVE_PCC_PROMOTION 1 */
+/* OK, I've added code to dbxread.c to deal with this case.  */
+#define BELIEVE_PCC_PROMOTION_TYPE
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc) \
+  { pc = skip_prologue (pc); }
+extern CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+/* On the Sun 4 under SunOS, the compile will leave a fake insn which
+   encodes the structure size being returned.  If we detect such
+   a fake insn, step past it.  */
+
+#define PC_ADJUST(pc) ((read_memory_integer (pc + 8, 4) & 0xfffffe00) == 0 ? \
+                      pc+12 : pc+8)
+
+#define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM))
+
+/* Address of the end of stack space.  We get this from the system
+   include files. */
+#include <sys/types.h>
+#include <machine/vmparam.h>
+#define STACK_END_ADDR USRSTACK
+
+#define INNER_THAN <
+
+/* Stack has strict alignment.  */
+
+#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8)
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0x91, 0xd0, 0x20, 0x01}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.  */
+/* For SPARC, this is either a "jmpl %o7+8,%g0" or "jmpl %i7+8,%g0".
+
+   Note: this does not work for functions returning structures under SunOS.  */
+#define ABOUT_TO_RETURN(pc) \
+  ((read_memory_integer (pc, 4)|0x00040000) == 0x81c7e008)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 72
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES  \
+{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",      \
+  "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",      \
+  "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",      \
+  "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",      \
+                                                               \
+  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",      \
+  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",        \
+  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",      \
+  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",      \
+                                                                \
+  "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define        G0_REGNUM 0             /* %g0 */
+#define        G1_REGNUM 1             /* %g1 */
+#define O0_REGNUM 8            /* %o0 */
+#define        SP_REGNUM 14            /* Contains address of top of stack, \
+                                  which is also the bottom of the frame.  */
+#define        RP_REGNUM 15            /* Contains return address value, *before* \
+                                  any windows get switched.  */
+#define        O7_REGNUM 15            /* Last local reg not saved on stack frame */
+#define        L0_REGNUM 16            /* First local reg that's saved on stack frame
+                                  rather than in machine registers */
+#define        I0_REGNUM 24            /* %i0 */
+#define        FP_REGNUM 30            /* Contains address of executing stack frame */
+#define        I7_REGNUM 31            /* Last local reg saved on stack frame */
+#define        FP0_REGNUM 32           /* Floating point register 0 */
+#define        Y_REGNUM 64             /* Temp register for multiplication, etc.  */
+#define        PS_REGNUM 65            /* Contains processor status */
+#define        WIM_REGNUM 66           /* Window Invalid Mask (not really supported) */
+#define        TBR_REGNUM 67           /* Trap Base Register (not really supported) */
+#define        PC_REGNUM 68            /* Contains program counter */
+#define        NPC_REGNUM 69           /* Contains next PC */
+#define        FPS_REGNUM 70           /* Floating point status register */
+#define        CPS_REGNUM 71           /* Coprocessor status register */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (32*4+32*4+8*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+/* ?? */
+#define REGISTER_BYTE(N)  ((N)*4)
+
+/* The SPARC processor has register windows.  */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system?  A yes answer
+   implies that 1) The name of this register will not be the same in
+   other frames, and 2) This register is automatically "saved" (out
+   registers shifting into ins counts) upon subroutine calls and thus
+   there is no need to search more than one stack frame for it. */
+
+#define REGISTER_IN_WINDOW_P(regnum)   \
+  ((regnum) >= 8 && (regnum) < 32)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+/* On the SPARC, all regs are 4 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  */
+
+/* On the SPARC, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : \
+  builtin_type_int)
+
+/* Writing to %g0 is a noop (not an error or exception or anything like
+   that, however).  */
+
+#define CANNOT_STORE_REGISTER(regno) ((regno) == G0_REGNUM)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { target_write_memory ((SP)+(16*4), (char *)&(ADDR), 4); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF)             \
+  {                                                                       \
+    if (TYPE_CODE (TYPE) == TYPE_CODE_FLT)                                \
+      {                                                                           \
+       bcopy (((int *)(REGBUF))+FP0_REGNUM,                               \
+              (VALBUF), TYPE_LENGTH(TYPE));                               \
+      }                                                                           \
+    else                                                                  \
+      bcopy (((int *)(REGBUF))+8, (VALBUF), TYPE_LENGTH (TYPE));           \
+  }
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+/* On sparc, values are returned in register %o0.  */
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  {                                                                                 \
+    if (TYPE_CODE (TYPE) == TYPE_CODE_FLT)                                  \
+      /* Floating-point values are returned in the register pair */          \
+      /* formed by %f0 and %f1 (doubles are, anyway).  */                    \
+      write_register_bytes (REGISTER_BYTE (FP0_REGNUM), (VALBUF),           \
+                           TYPE_LENGTH (TYPE));                             \
+    else                                                                    \
+      /* Other values are returned in register %o0.  */                      \
+      write_register_bytes (REGISTER_BYTE (O0_REGNUM), (VALBUF),            \
+                           TYPE_LENGTH (TYPE));  \
+  }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+  (read_memory_integer (((int *)(REGBUF))[SP_REGNUM]+(16*4), 4))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* I don't know whether this will work for cross-debugging, even if you
+   do get the right reg.h.  */
+#include <machine/reg.h>
+
+#define GET_RWINDOW_REG(FRAME, REG) \
+  (read_memory_integer ((CORE_ADDR)&((struct rwindow *)FRAME)->REG, 4))
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the Sun 4, the frame-chain's nominal address
+   is held in the frame pointer register.
+
+   On the Sun4, the frame (in %fp) is %sp for the previous frame.
+   From the previous frame's %sp, we can find the previous frame's
+   %fp: it is in the save area just above the previous frame's %sp.
+
+   If we are setting up an arbitrary frame, we'll need to know where
+   it ends.  Hence the following.  This part of the frame cache
+   structure should be checked before it is assumed that this frame's
+   bottom is in the stack pointer.
+
+   If there isn't a frame below this one, the bottom of this frame is
+   in the stack pointer.
+
+   If there is a frame below this one, and the frame pointers are
+   identical, it's a leaf frame and the bottoms are the same also.
+
+   Otherwise the bottom of this frame is the top of the next frame.  */
+
+#define EXTRA_FRAME_INFO       FRAME_ADDR bottom;
+#define INIT_EXTRA_FRAME_INFO(fci)  \
+  (fci)->bottom =                                      \
+   ((fci)->next ?                                      \
+    ((fci)->frame == (fci)->next_frame ?               \
+     (fci)->next->bottom : (fci)->next->frame) :       \
+    read_register (SP_REGNUM));
+
+#define FRAME_CHAIN(thisframe) \
+   GET_RWINDOW_REG ((thisframe)->frame, rw_in[6])
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* Where is the PC for a specific frame */
+
+#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
+CORE_ADDR frame_saved_pc ();
+
+/* If the argument is on the stack, it will be here.  */
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_STRUCT_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+   Can set VAL to -1, meaning no way to tell.  */
+
+/* We can't tell how many args there are
+   now that the C compiler delays popping them.  */
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 68
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   The actual code is in sparc-tdep.c so we can debug it sanely.  */
+
+#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs)                \
+       sparc_frame_find_saved_regs ((fi), &(frame_saved_regs))
+extern void sparc_frame_find_saved_regs ();
+\f
+/* Things needed for making the inferior call functions.  */
+/*
+ * First of all, let me give my opinion of what the DUMMY_FRAME
+ * actually looks like.
+ *
+ *               |                                 |
+ *               |                                 |
+ *               + - - - - - - - - - - - - - - - - +<-- fp (level 0)
+ *               |                                 |
+ *               |                                 |
+ *               |                                 |
+ *               |                                 |
+ *               |  Frame of innermost program     |
+ *               |           function              |
+ *               |                                 |
+ *               |                                 |
+ *               |                                 |
+ *               |                                 |
+ *               |                                 |
+ *               |---------------------------------|<-- sp (level 0), fp (c)
+ *               |                                 |
+ *     DUMMY     |             fp0-31              |
+ *               |                                 |
+ *               |             ------              |<-- fp - 0x80
+ *     FRAME     |              g0-7               |<-- fp - 0xa0
+ *               |              i0-7               |<-- fp - 0xc0
+ *               |             other               |<-- fp - 0xe0
+ *               |               ?                 |
+ *               |               ?                 |
+ *               |---------------------------------|<-- sp' = fp - 0x140
+ *               |                                 |
+ * xcution start |                                 |
+ * sp' + 0x94 -->|        CALL_DUMMY (x code)      |
+ *               |                                 |
+ *               |                                 |
+ *               |---------------------------------|<-- sp'' = fp - 0x200
+ *               |  align sp to 8 byte boundary    |
+ *               |     ==> args to fn <==          |
+ *  Room for     |                                 |
+ * i & l's + agg | CALL_DUMMY_STACK_ADJUST = 0x0x44|
+ *               |---------------------------------|<-- final sp (variable)
+ *               |                                 |
+ *               |   Where function called will    |
+ *               |           build frame.          |
+ *               |                                 |
+ *               |                                 |
+ *
+ *   I understand everything in this picture except what the space
+ * between fp - 0xe0 and fp - 0x140 is used for.  Oh, and I don't
+ * understand why there's a large chunk of CALL_DUMMY that never gets
+ * executed (its function is superceeded by PUSH_DUMMY_FRAME; they
+ * are designed to do the same thing).
+ *
+ *   PUSH_DUMMY_FRAME saves the registers above sp' and pushes the
+ * register file stack down one.
+ *
+ *   call_function then writes CALL_DUMMY, pushes the args onto the
+ * stack, and adjusts the stack pointer.
+ *
+ *   run_stack_dummy then starts execution (in the middle of
+ * CALL_DUMMY, as directed by call_function).
+ */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME       sparc_push_dummy_frame ()
+#define POP_FRAME      sparc_pop_frame ()
+
+void sparc_push_dummy_frame (), sparc_pop_frame ();
+/* This sequence of words is the instructions
+
+   save %sp,-0x140,%sp
+   std %f30,[%fp-0x08]
+   std %f28,[%fp-0x10]
+   std %f26,[%fp-0x18]
+   std %f24,[%fp-0x20]
+   std %f22,[%fp-0x28]
+   std %f20,[%fp-0x30]
+   std %f18,[%fp-0x38]
+   std %f16,[%fp-0x40]
+   std %f14,[%fp-0x48]
+   std %f12,[%fp-0x50]
+   std %f10,[%fp-0x58]
+   std %f8,[%fp-0x60]
+   std %f6,[%fp-0x68]
+   std %f4,[%fp-0x70]
+   std %f2,[%fp-0x78]
+   std %f0,[%fp-0x80]
+   std %g6,[%fp-0x88]
+   std %g4,[%fp-0x90]
+   std %g2,[%fp-0x98]
+   std %g0,[%fp-0xa0]
+   std %i6,[%fp-0xa8]
+   std %i4,[%fp-0xb0]
+   std %i2,[%fp-0xb8]
+   std %i0,[%fp-0xc0]
+   nop ! stcsr [%fp-0xc4]
+   nop ! stfsr [%fp-0xc8]
+   nop ! wr    %npc,[%fp-0xcc]
+   nop ! wr    %pc,[%fp-0xd0]
+   rd  %tbr,%o0
+   st  %o0,[%fp-0xd4]
+   rd  %wim,%o1
+   st  %o0,[%fp-0xd8]
+   rd  %psr,%o0
+   st  %o0,[%fp-0xdc]
+   rd  %y,%o0
+   st  %o0,[%fp-0xe0]
+
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of
+       the following ld instruction.  *../
+
+   ld  [%sp+0x58],%o5
+   ld  [%sp+0x54],%o4
+   ld  [%sp+0x50],%o3
+   ld  [%sp+0x4c],%o2
+   ld  [%sp+0x48],%o1
+   call 0x00000000
+   ld  [%sp+0x44],%o0
+   nop
+   ta 1
+   nop
+
+   note that this is 192 bytes, which is a multiple of 8 (not only 4) bytes.
+   note that the `call' insn is a relative, not an absolute call.
+   note that the `nop' at the end is needed to keep the trap from
+        clobbering things (if NPC pointed to garbage instead).
+
+We actually start executing at the `sethi', since the pushing of the
+registers (as arguments) is done by PUSH_DUMMY_FRAME.  If this were
+real code, the arguments for the function called by the CALL would be
+pushed between the list of ST insns and the CALL, and we could allow
+it to execute through.  But the arguments have to be pushed by GDB
+after the PUSH_DUMMY_FRAME is done, and we cannot allow these ST
+insns to be performed again, lest the registers saved be taken for
+arguments.  */
+
+#define CALL_DUMMY { 0x9de3bee0, 0xfd3fbff8, 0xf93fbff0, 0xf53fbfe8,   \
+                    0xf13fbfe0, 0xed3fbfd8, 0xe93fbfd0, 0xe53fbfc8,    \
+                    0xe13fbfc0, 0xdd3fbfb8, 0xd93fbfb0, 0xd53fbfa8,    \
+                    0xd13fbfa0, 0xcd3fbf98, 0xc93fbf90, 0xc53fbf88,    \
+                    0xc13fbf80, 0xcc3fbf78, 0xc83fbf70, 0xc43fbf68,    \
+                    0xc03fbf60, 0xfc3fbf58, 0xf83fbf50, 0xf43fbf48,    \
+                    0xf03fbf40, 0x01000000, 0x01000000, 0x01000000,    \
+                    0x01000000, 0x91580000, 0xd027bf50, 0x93500000,    \
+                    0xd027bf4c, 0x91480000, 0xd027bf48, 0x91400000,    \
+                    0xd027bf44, 0xda03a058, 0xd803a054, 0xd603a050,    \
+                    0xd403a04c, 0xd203a048, 0x40000000, 0xd003a044,    \
+                    0x01000000, 0x91d02001, 0x01000000, 0x01000000}
+
+#define CALL_DUMMY_LENGTH 192
+
+#define CALL_DUMMY_START_OFFSET 148
+
+#define CALL_DUMMY_STACK_ADJUST 68
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.
+
+   For structs and unions, if the function was compiled with Sun cc,
+   it expects 'unimp' after the call.  But gcc doesn't use that
+   (twisted) convention.  So leave a nop there for gcc (FIX_CALL_DUMMY
+   can assume it is operating on a pristine CALL_DUMMY, not one that
+   has already been customized for a different function).  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{                                                                      \
+  *(int *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \
+  if (!gcc_p                                                            \
+      && (TYPE_CODE (type) == TYPE_CODE_STRUCT                         \
+         || TYPE_CODE (type) == TYPE_CODE_UNION))                      \
+    *(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff);  \
+}
+
+\f
+/* Sparc has no reliable single step ptrace call */
+
+#define NO_SINGLE_STEP 1
+extern void single_step ();
+
+/* We need two arguments (in general) to the "info frame" command.
+   Note that the definition of this macro implies that there exists a
+   function "setup_arbitrary_frame" in mach-dep.c */
+
+#define FRAME_SPECIFICATION_DYADIC
+
+/* To print every pair of float registers as a double, we use this hook.  */
+
+#define        PRINT_REGISTER_HOOK(regno)      \
+  if (((regno) >= FP0_REGNUM)          \
+   && ((regno) <  FP0_REGNUM + 32)     \
+   && (0 == (regno & 1))) {            \
+    char doublereg[8];         /* two float regs */    \
+    if (!read_relative_register_raw_bytes (i  , doublereg  )   \
+     && !read_relative_register_raw_bytes (i+1, doublereg+4)) {        \
+      printf("\t");                    \
+      print_floating (doublereg, builtin_type_double, stdout); \
+    }                                  \
+  }
+
diff --git a/gdb/tm-sun2.h b/gdb/tm-sun2.h
new file mode 100644 (file)
index 0000000..6d29462
--- /dev/null
@@ -0,0 +1,107 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "m-68k.h"
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Address of the end of stack space.  We get this from the system
+   include files. */
+#include <sys/types.h>
+#include <machine/vmparam.h>
+#define STACK_END_ADDR USRSTACK
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+  register int regnum;                             \
+  sp = push_word (sp, read_register (PC_REGNUM));   \
+  sp = push_word (sp, read_register (FP_REGNUM));   \
+  write_register (FP_REGNUM, sp);                  \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)  \
+    sp = push_word (sp, read_register (regnum));    \
+  sp = push_word (sp, read_register (PS_REGNUM));   \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                  \
+  register CORE_ADDR fp;                                        \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info *fi;                                                \
+  fi = get_frame_info (frame);                                  \
+  fp = fi->frame;                                               \
+  get_frame_saved_regs (fi, &fsr);                              \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)           \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                      \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+     moveml 0xfffc,-(sp)
+     clrw -(sp)
+     movew ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of
+       the following jsr instruction.  *../
+     jsr @#32323232
+     addl #69696969,sp
+     bpt
+     nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 24
+
+#define CALL_DUMMY_START_OFFSET 8
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 16) = nargs * 4;  \
+  *(int *)((char *) dummyname + 10) = fun; }
diff --git a/gdb/tm-sun2os4.h b/gdb/tm-sun2os4.h
new file mode 100644 (file)
index 0000000..bb1a061
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C) 1990, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "tm-sun2.h"
+#include "tm-sunos.h"
diff --git a/gdb/tm-sun3.h b/gdb/tm-sun3.h
new file mode 100644 (file)
index 0000000..4519d6a
--- /dev/null
@@ -0,0 +1,120 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HAVE_68881
+
+#include "tm-68k.h"
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Address of the end of stack space.  We get this from the system
+   include files. */
+#include <sys/types.h>
+#include <machine/vmparam.h>
+#define STACK_END_ADDR USRSTACK
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  char raw_buffer[12];                                                 \
+  sp = push_word (sp, read_register (PC_REGNUM));                      \
+  sp = push_word (sp, read_register (FP_REGNUM));                      \
+  write_register (FP_REGNUM, sp);                                      \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);    \
+      sp = push_bytes (sp, raw_buffer, 12); }                          \
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    sp = push_word (sp, read_register (regnum));                       \
+  sp = push_word (sp, read_register (PS_REGNUM));                      \
+  write_register (SP_REGNUM, sp);  }
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                         \
+  register CORE_ADDR fp;                                               \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info *fi;                                               \
+  char raw_buffer[12];                                                 \
+  fi = get_frame_info (frame);                                         \
+  fp = fi->frame;                                                      \
+  get_frame_saved_regs (fi, &fsr);                                     \
+  for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)                \
+    if (fsr.regs[regnum])                                              \
+      { read_memory (fsr.regs[regnum], raw_buffer, 12);                        \
+        write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+  for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)                  \
+    if (fsr.regs[regnum])                                              \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  if (fsr.regs[PS_REGNUM])                                             \
+    write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));             \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));         \
+  write_register (SP_REGNUM, fp + 8);                                  \
+  flush_cached_frames ();                                              \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),      \
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+     fmovem 0xff,-(sp)
+     moveml 0xfffc,-(sp)
+     clrw -(sp)
+     movew ccr,-(sp)
+     /..* The arguments are pushed at this point by GDB;
+       no code is needed in the dummy for this.
+       The CALL_DUMMY_START_OFFSET gives the position of 
+       the following jsr instruction.  *../
+     jsr @#32323232
+     addl #69696969,sp
+     trap #15
+     nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME.  If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments.  */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)     \
+{ *(int *)((char *) dummyname + 20) = nargs * 4;  \
+  *(int *)((char *) dummyname + 14) = fun; }
diff --git a/gdb/tm-sun386.h b/gdb/tm-sun386.h
new file mode 100644 (file)
index 0000000..60c8986
--- /dev/null
@@ -0,0 +1,305 @@
+/* Parameters for execution on a Sun 386i, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+#ifndef sun386
+#define sun386
+#endif
+#define SUNOS4
+#define USE_MACHINE_REG_H
+
+/* Perhaps some day this will work even without the following #define */
+#define COFF_ENCAPSULATE
+
+#ifdef COFF_ENCAPSULATE
+#define NAMES_HAVE_UNDERSCORE
+/* Avoid conflicts between "a.out.gnu.h" and <sys/exec.h> */
+#define _EXEC_
+#endif
+
+#define BROKEN_LARGE_ALLOCA
+
+/* sun386 ptrace seems unable to change the frame pointer */
+#define PTRACE_FP_BUG
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(frompc)   {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+  (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR 0xfc000000
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 1
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes -- not relevant on the 386.  */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* Largest integer type */
+#define LONGEST long
+
+/* Name of the builtin type for the LONGEST type above. */
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 35
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+/* the order of the first 8 registers must match the compiler's
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+#define REGISTER_NAMES { "gs", "fs", "es", "ds",               \
+                        "edi", "esi", "ebp", "esp",            \
+                        "ebx", "edx", "ecx", "eax",            \
+                        "retaddr", "trapnum", "errcode", "ip", \
+                        "cs", "ps", "sp", "ss",                \
+                        "fst0", "fst1", "fst2", "fst3",        \
+                        "fst4", "fst5", "fst6", "fst7",        \
+                        "fctrl", "fstat", "ftag", "fip",       \
+                        "fcs", "fopoff", "fopsel"              \
+                        }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define FP_REGNUM 6            /* Contains address of executing stack frame */
+#define SP_REGNUM 18           /* Contains address of top of stack */
+#define PS_REGNUM 17           /* Contains processor status */
+#define PC_REGNUM 15           /* Contains program counter */
+#define FP0_REGNUM 20          /* Floating point register 0 */
+#define FPC_REGNUM 28          /* 80387 control register */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (20*4+8*10+7*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) \
+ ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 160   \
+  : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 10) + 80 \
+  : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+#define REGISTER_RAW_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 10 : 4)
+
+/* Number of bytes of storage in the program's representation
+   for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) (((unsigned)((N) - FP0_REGNUM)) < 8)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+    i387_to_double ((FROM), (TO));                     \
+  else                                                 \
+    bcopy ((FROM), (TO), 4); }
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+    double_to_i387 ((FROM), (TO));     \
+  else                                 \
+    bcopy ((FROM), (TO), 4); }
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)((N) - FP0_REGNUM)) < 8 ? builtin_type_double : builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { (SP) -= sizeof (ADDR);             \
+    write_memory ((SP), &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (REGBUF + REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+#define FRAME_CHAIN(thisframe) \
+  (outside_startup_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ (FRAMELESS) = frameless_look_for_prologue (FI); }
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  { i386_pop_frame (); }
+
+/* this is 
+ *   call 11223344 (32 bit relative)
+ *   int3
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)   \
+{ \
+       *(int *)((char *)(dummyname) + 1) = (int)(fun) - (pc) - 5; \
+}
diff --git a/gdb/tm-sun3os4.h b/gdb/tm-sun3os4.h
new file mode 100644 (file)
index 0000000..5d89d15
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C) 1990, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "tm-sun3.h"
+#include "tm-sunos.h"
diff --git a/gdb/tm-sun4os4.h b/gdb/tm-sun4os4.h
new file mode 100644 (file)
index 0000000..971bb4f
--- /dev/null
@@ -0,0 +1,24 @@
+/* Macro definitions for GDB for a Sun 4 running sunos 4.
+   Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "tm-sparc.h"
+#include "tm-sunos.h"
+
+#undef STACK_END_ADDRESS
+#define STACK_END_ADDRESS 0xf8000000
diff --git a/gdb/tm-sunos.h b/gdb/tm-sunos.h
new file mode 100644 (file)
index 0000000..f33e352
--- /dev/null
@@ -0,0 +1,26 @@
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is for SunOS version 4, not for earlier versions.  */
+
+#define CLEAR_SOLIB clear_solib
+
+/* If we can't set a breakpoint, and it's in a shared library, just
+   disable it.  */
+#define DISABLE_UNSETTABLE_BREAK(addr) solib_address(addr)
+extern int solib_address ();                   /* solib.c */
diff --git a/gdb/tm-symmetry.h b/gdb/tm-symmetry.h
new file mode 100644 (file)
index 0000000..0030b61
--- /dev/null
@@ -0,0 +1,488 @@
+/* Definitions to make GDB run on a Sequent Symmetry under dynix 3.0,
+   with Weitek 1167 and i387 support.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Symmetry version by Jay Vosburgh (uunet!sequent!fubar) */
+
+/* I don't know if this will work for cross-debugging, even if you do get
+   a copy of the right include file.  */
+#include <machine/reg.h>
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  From m-i386.h */
+
+#define SKIP_PROLOGUE(frompc)   {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+  read_memory_integer(read_register(SP_REGNUM), 4)
+
+/* I don't know the real values for these.  */
+#define TARGET_UPAGES UPAGES
+#define TARGET_NBPG NBPG
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0x40000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.  */
+/* For Symmetry, this is really the 'leave' instruction, which */
+/* is right before the ret */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc9)
+
+/* Return 1 if P points to an invalid floating point value.
+*/
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* code for 80387 fpu.  Functions are from i386-dep.c, copied into
+ * symm-dep.c.
+ */
+#define FLOAT_INFO { i386_float_info(); }
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+#define NUM_REGS 49
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+/* Symmetry registers are in this weird order to match the register
+   numbers in the symbol table entries.  If you change the order,
+   things will probably break mysteriously for no apparent reason.
+   Also note that the st(0)...st(7) 387 registers are represented as
+   st0...st7.  */
+
+#define REGISTER_NAMES { "eax", "edx", "ecx", "st0", "st1", \
+                            "ebx", "esi", "edi", "st2", "st3", \
+                            "st4", "st5", "st6", "st7", "esp", \
+                            "ebp", "eip", "eflags", "fp1", "fp2", \
+                            "fp3", "fp4", "fp5", "fp6", "fp7", \
+                            "fp8", "fp9", "fp10", "fp11", "fp12", \
+                            "fp13", "fp14", "fp15", "fp16", "fp17", \
+                            "fp18", "fp19", "fp20", "fp21", "fp22", \
+                            "fp23", "fp24", "fp25", "fp26", "fp27", \
+                            "fp28", "fp29", "fp30", "fp31" }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define FP1_REGNUM 18          /* first 1167 register */
+#define SP_REGNUM 14           /* Contains address of top of stack */
+#define FP_REGNUM 15           /* Contains address of executing stack frame */
+#define PC_REGNUM 16           /* Contains program counter */
+#define PS_REGNUM 17           /* Contains processor status */
+
+/* The magic numbers below are offsets into u_ar0 in the user struct.
+ * They live in <machine/reg.h>.  Gdb calls this macro with blockend
+ * holding u.u_ar0 - KERNEL_U_ADDR.  Only the registers listed are
+ * saved in the u area (along with a few others that aren't useful
+ * here.  See <machine/reg.h>).
+ */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ struct user foo;     /* needed for finding fpu regs */ \
+switch (regno) { \
+    case 0: \
+      addr = blockend + EAX * sizeof(int); break; \
+  case 1: \
+      addr = blockend + EDX * sizeof(int); break; \
+  case 2: \
+      addr = blockend + ECX * sizeof(int); break; \
+  case 3:                      /* st(0) */ \
+      addr = blockend - \
+         ((int)&foo.u_fpusave.fpu_stack[0][0] - (int)&foo); \
+      break; \
+  case 4:                      /* st(1) */ \
+      addr = blockend - \
+         ((int) &foo.u_fpusave.fpu_stack[1][0] - (int)&foo); \
+      break; \
+  case 5: \
+      addr = blockend + EBX * sizeof(int); break; \
+  case 6: \
+      addr = blockend + ESI * sizeof(int); break; \
+  case 7: \
+      addr = blockend + EDI * sizeof(int); break; \
+  case 8:                      /* st(2) */ \
+      addr = blockend - \
+         ((int) &foo.u_fpusave.fpu_stack[2][0] - (int)&foo); \
+      break; \
+  case 9:                      /* st(3) */ \
+      addr = blockend - \
+         ((int) &foo.u_fpusave.fpu_stack[3][0] - (int)&foo); \
+      break; \
+  case 10:                     /* st(4) */ \
+      addr = blockend - \
+         ((int) &foo.u_fpusave.fpu_stack[4][0] - (int)&foo); \
+      break; \
+  case 11:                     /* st(5) */ \
+      addr = blockend - \
+         ((int) &foo.u_fpusave.fpu_stack[5][0] - (int)&foo); \
+      break; \
+  case 12:                     /* st(6) */ \
+      addr = blockend - \
+         ((int) &foo.u_fpusave.fpu_stack[6][0] - (int)&foo); \
+      break; \
+  case 13:                     /* st(7) */ \
+      addr = blockend - \
+         ((int) &foo.u_fpusave.fpu_stack[7][0] - (int)&foo); \
+      break; \
+  case 14: \
+      addr = blockend + ESP * sizeof(int); break; \
+  case 15: \
+      addr = blockend + EBP * sizeof(int); break; \
+  case 16: \
+      addr = blockend + EIP * sizeof(int); break; \
+  case 17: \
+      addr = blockend + FLAGS * sizeof(int); break; \
+  case 18:                     /* fp1 */ \
+  case 19:                     /* fp2 */ \
+  case 20:                     /* fp3 */ \
+  case 21:                     /* fp4 */ \
+  case 22:                     /* fp5 */ \
+  case 23:                     /* fp6 */ \
+  case 24:                     /* fp7 */ \
+  case 25:                     /* fp8 */ \
+  case 26:                     /* fp9 */ \
+  case 27:                     /* fp10 */ \
+  case 28:                     /* fp11 */ \
+  case 29:                     /* fp12 */ \
+  case 30:                     /* fp13 */ \
+  case 31:                     /* fp14 */ \
+  case 32:                     /* fp15 */ \
+  case 33:                     /* fp16 */ \
+  case 34:                     /* fp17 */ \
+  case 35:                     /* fp18 */ \
+  case 36:                     /* fp19 */ \
+  case 37:                     /* fp20 */ \
+  case 38:                     /* fp21 */ \
+  case 39:                     /* fp22 */ \
+  case 40:                     /* fp23 */ \
+  case 41:                     /* fp24 */ \
+  case 42:                     /* fp25 */ \
+  case 43:                     /* fp26 */ \
+  case 44:                     /* fp27 */ \
+  case 45:                     /* fp28 */ \
+  case 46:                     /* fp29 */ \
+  case 47:                     /* fp30 */ \
+  case 48:                     /* fp31 */ \
+     addr = blockend - \
+        ((int) &foo.u_fpasave.fpa_regs[(regno)-18] - (int)&foo); \
+  } \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+/* 10 i386 registers, 8 i387 registers, and 31 Weitek 1167 registers */
+#define REGISTER_BYTES ((10 * 4) + (8 * 10) + (31 * 4))
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N)               \
+((N < 3) ? (N * 4) :                   \
+(N < 5) ? (((N - 2) * 10) + 2) :       \
+(N < 8) ? (((N - 5) * 4) + 32) :       \
+(N < 14) ? (((N - 8) * 10) + 44) :     \
+    (((N - 14) * 4) + 104))
+
+/* Number of bytes of storage in the actual machine representation
+ * for register N.  All registers are 4 bytes, except 387 st(0) - st(7),
+ * which are 80 bits each. 
+ */
+
+#define REGISTER_RAW_SIZE(N) \
+((N < 3) ? 4 : \
+(N < 5) ? 10 : \
+(N < 8) ? 4 :  \
+(N < 14) ? 10 :        \
+    4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the vax, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) \
+((N < 3) ? 0 : \
+(N < 5) ? 1  : \
+(N < 8) ? 0  : \
+(N < 14) ? 1 : \
+    0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+((REGNUM < 3) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 5) ? i387_to_double((FROM), (TO)) : \
+(REGNUM < 8) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 14) ? i387_to_double((FROM), (TO)) : \
+    bcopy ((FROM), (TO), 4))
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+((REGNUM < 3) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 5) ? double_to_i387((FROM), (TO)) : \
+(REGNUM < 8) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 14) ? double_to_i387((FROM), (TO)) : \
+    bcopy ((FROM), (TO), 4))
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+((N < 3) ? builtin_type_int : \
+(N < 5) ? builtin_type_double : \
+(N < 8) ? builtin_type_int : \
+(N < 14) ? builtin_type_double : \
+    builtin_type_int)
+
+/* from m-i386.h */
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { (SP) -= sizeof (ADDR);             \
+    write_memory ((SP), &(ADDR), sizeof (ADDR)); \
+    write_register(0, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  symmetry_extract_return_value(TYPE, REGBUF, VALBUF)
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* On Symmetry, %ebp points to caller's %ebp, and the return address
+   is right on top of that.
+*/
+
+#define FRAME_CHAIN(thisframe)  \
+  (outside_startup_file ((thisframe)->pc) ? \
+   read_memory_integer((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(fi) (read_memory_integer((fi)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.
+  
+   The weirdness in the "addl $imm8" case is due to gcc sometimes
+   issuing "addl $-int" after function call returns; this would
+   produce ridiculously huge arg counts.  */
+
+#define FRAME_NUM_ARGS(numargs, fi)  \
+{ \
+  int op = read_memory_integer(FRAME_SAVED_PC((fi)), 4); \
+  int narg; \
+  if ((op & 0xff) == 0x59) /* 0x59  'popl %ecx' */ \
+    { \
+      numargs = 1; \
+    } \
+  else if ((op & 0xffff) == 0xc483) /* 0xc483 'addl $imm8' */ \
+    { \
+      narg = ((op >> 16) & 0xff); \
+      numargs = (narg >= 128) ? -1 : narg / 4; \
+    } \
+  else if ((op & 0xffff) == 0xc481) /* 0xc481 'addl $imm32' */ \
+    { \
+      narg = read_memory_integer(FRAME_SAVED_PC((fi))+2,4); \
+      numargs = (narg < 0) ? -1 : narg / 4; \
+    } \
+  else \
+    { \
+      numargs = -1; \
+    } \
+}
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+\f
+/* Things needed for making the inferior call functions.  */
+
+#define PUSH_DUMMY_FRAME \
+{  CORE_ADDR sp = read_register (SP_REGNUM); \
+  int regnum; \
+  sp = push_word (sp, read_register (PC_REGNUM)); \
+  sp = push_word (sp, read_register (FP_REGNUM)); \
+  write_register (FP_REGNUM, sp); \
+  for (regnum = 0; regnum < NUM_REGS; regnum++) \
+    sp = push_word (sp, read_register (regnum)); \
+  write_register (SP_REGNUM, sp); \
+}
+
+#define POP_FRAME  \
+{ \
+  FRAME frame = get_current_frame (); \
+  CORE_ADDR fp; \
+  int regnum; \
+  struct frame_saved_regs fsr; \
+  struct frame_info *fi; \
+  fi = get_frame_info (frame); \
+  fp = fi->frame; \
+  get_frame_saved_regs (fi, &fsr); \
+  for (regnum = 0; regnum < NUM_REGS; regnum++) { \
+      CORE_ADDR adr; \
+      adr = fsr.regs[regnum]; \
+      if (adr) \
+       write_register (regnum, read_memory_integer (adr, 4)); \
+  } \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+  write_register (SP_REGNUM, fp + 8); \
+  flush_cached_frames (); \
+  set_current_frame ( create_new_frame (read_register (FP_REGNUM), \
+                                       read_pc ())); \
+}
+
+/* from i386-dep.c, worked better than my original... */
+/* This sequence of words is the instructions
+ * call (32-bit offset)
+ * int 3
+ * This is 6 bytes.
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)   \
+{ \
+       int from, to, delta, loc; \
+       loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+       from = loc + 5; \
+       to = (int)(fun); \
+       delta = to - from; \
+       *(int *)((char *)(dummyname) + 1) = delta; \
+}
diff --git a/gdb/tm-umax.h b/gdb/tm-umax.h
new file mode 100644 (file)
index 0000000..4929065
--- /dev/null
@@ -0,0 +1,405 @@
+/* Definitions to make GDB run on an encore under umax 4.2
+   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Exec files and symbol tables are in COFF format */
+
+#define COFF_FORMAT
+
+/* Need to get function ends by adding this to epilogue address from .bf
+   record, not using x_fsize field.  */
+#define FUNCTION_EPILOGUE_SIZE 4
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc)                              \
+{ register unsigned char op = read_memory_integer (pc, 1);     \
+  if (op == 0x82) { op = read_memory_integer (pc+2,1);  \
+                   if ((op & 0x80) == 0) pc += 3;      \
+                   else if ((op & 0xc0) == 0x80) pc += 4;      \
+                   else pc += 6;                       \
+                  }                                    \
+}
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+       read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space.  */
+
+#define STACK_END_ADDR (0xfffff000)
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {0xf2}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
+
+#ifndef NaN
+#include <nan.h>
+#endif NaN
+
+/* Return 1 if P points to an invalid floating point value.  */
+/* Surely wrong for cross-debugging.  */
+#define INVALID_FLOAT(p, s) \
+        ((s == sizeof (float))?        \
+               NaF (*(float *) p) :    \
+               NaD (*(double *) p))
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS               25
+
+#define NUM_GENERAL_REGS       8
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",        \
+                       "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+                       "sp", "fp", "pc", "ps",                         \
+                       "fsr",                                          \
+                       "l0", "l1", "l2", "l3", "xx",                   \
+                       }
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define FP0_REGNUM 8           /* Floating point register 0 */
+#define SP_REGNUM 16           /* Contains address of top of stack */
+#define AP_REGNUM FP_REGNUM
+#define FP_REGNUM 17           /* Contains address of executing stack frame */
+#define PC_REGNUM 18           /* Contains program counter */
+#define PS_REGNUM 19           /* Contains processor status */
+#define FPS_REGNUM 20          /* Floating point status register */
+#define LP0_REGNUM 21          /* Double register 0 (same as FP0) */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+       LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the 32000, all regs are 4 bytes
+   except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+       (((N) < FP0_REGNUM) ?                           \
+               builtin_type_int :                      \
+               ((N) < FP0_REGNUM + 8) ?                \
+                       builtin_type_float :            \
+                       ((N) < LP0_REGNUM) ?            \
+                               builtin_type_int :      \
+                               builtin_type_double)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function.
+
+   On this machine this is a no-op, because gcc isn't used on it
+   yet.  So this calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the ns32000 series, the frame's nominal address is the FP
+   value, and at that address is saved previous FP value as a 4-byte word.  */
+
+#define FRAME_CHAIN(thisframe)  \
+  (outside_startup_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* Compute base of arguments. */
+
+#define FRAME_ARGS_ADDRESS(fi) \
+  ((ns32k_get_enter_addr ((fi)->pc) > 1) ? \
+       ((fi)->frame) : (read_register (SP_REGNUM) - 4))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Get the address of the enter opcode for this function, if it is active.
+   Returns positive address > 1 if pc is between enter/exit,
+   1 if pc before enter or after exit, 0 otherwise. */
+
+#ifndef CORE_ADDR
+#include "defs.h"   /* Make sure CORE_ADDR is defined.  */
+#endif
+
+extern CORE_ADDR ns32k_get_enter_addr ();
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.
+   Encore's C compiler often reuses same area on stack for args,
+   so this will often not work properly.  If the arg names
+   are known, it's likely most of them will be printed. */
+
+#define FRAME_NUM_ARGS(numargs, fi)                    \
+{ CORE_ADDR    pc;                                     \
+  CORE_ADDR    enter_addr;                             \
+  unsigned int insn;                                   \
+  unsigned int addr_mode;                              \
+  int width;                                           \
+                                                       \
+  numargs = -1;                                                \
+  enter_addr = ns32k_get_enter_addr ((fi)->pc);                \
+  if (enter_addr > 0)                                  \
+    {                                                  \
+      pc = (enter_addr == 1) ?                         \
+       SAVED_PC_AFTER_CALL (fi) :                      \
+       FRAME_SAVED_PC (fi);                            \
+      insn = read_memory_integer (pc,2);               \
+      addr_mode = (insn >> 11) & 0x1f;                 \
+      insn = insn & 0x7ff;                             \
+      if ((insn & 0x7fc) == 0x57c &&                   \
+               addr_mode == 0x14) /* immediate */      \
+       {                                               \
+         if (insn == 0x57c) /* adjspb */               \
+               width = 1;                              \
+         else if (insn == 0x57d) /* adjspw */          \
+               width = 2;                              \
+         else if (insn == 0x57f) /* adjspd */          \
+               width = 4;                              \
+         numargs = read_memory_integer (pc+2,width);   \
+         if (width > 1)                                \
+           flip_bytes (&numargs, width);               \
+         numargs = - sign_extend (numargs, width*8) / 4;\
+       }                                               \
+    }                                                  \
+}
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)    \
+{                                                              \
+  register int regmask, regnum;                                \
+  int          localcount;                                     \
+  register CORE_ADDR   enter_addr;                             \
+  register CORE_ADDR   next_addr;                              \
+                                                               \
+  bzero (&(frame_saved_regs), sizeof (frame_saved_regs));      \
+  enter_addr = ns32k_get_enter_addr ((frame_info)->pc);                \
+  if (enter_addr > 1)                                          \
+    {                                                          \
+      regmask = read_memory_integer (enter_addr+1, 1) & 0xff;  \
+      localcount = ns32k_localcount (enter_addr);              \
+      next_addr = (frame_info)->frame + localcount;            \
+      for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)    \
+       (frame_saved_regs).regs[regnum] = (regmask & 1) ?       \
+                                         (next_addr -= 4) : 0; \
+      (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4;\
+      (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;\
+      (frame_saved_regs).regs[FP_REGNUM] =                     \
+                 (read_memory_integer ((frame_info)->frame, 4));\
+    }                                                          \
+  else if (enter_addr == 1)                                    \
+    {                                                          \
+      CORE_ADDR sp = read_register (SP_REGNUM);                        \
+      (frame_saved_regs).regs[PC_REGNUM] = sp;                 \
+      (frame_saved_regs).regs[SP_REGNUM] = sp + 4;             \
+    }                                                          \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+  register int regnum;                             \
+  sp = push_word (sp, read_register (PC_REGNUM));   \
+  sp = push_word (sp, read_register (FP_REGNUM));   \
+  write_register (FP_REGNUM, sp);                  \
+  for (regnum = 0; regnum < 8; regnum++)  \
+    sp = push_word (sp, read_register (regnum));    \
+  write_register (SP_REGNUM, sp);                      \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                  \
+  register CORE_ADDR fp;                                        \
+  register int regnum;                                          \
+  struct frame_saved_regs fsr;                                  \
+  struct frame_info *fi;                                                \
+  fi = get_frame_info (frame);                                  \
+  fp = fi->frame;                                               \
+  get_frame_saved_regs (fi, &fsr);                              \
+  for (regnum = 0; regnum < 8; regnum++)                        \
+    if (fsr.regs[regnum])                                       \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));   \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+                                      read_pc ())); }
+
+/* This sequence of words is the instructions
+     enter     0xff,0          82 ff 00
+     jsr       @0x00010203     7f ae c0 01 02 03
+     adjspd    0x69696969      7f a5 01 02 03 04
+     bpt                       f2
+   Note this is 16 bytes.  */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET        3
+#define CALL_DUMMY_LENGTH      16
+#define CALL_DUMMY_ADDR                5
+#define CALL_DUMMY_NARGS       11
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)                   \
+{                                                              \
+       int     flipped;                                        \
+       flipped = fun | 0xc0000000;                             \
+       flip_bytes (&flipped, 4);                               \
+       *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped;    \
+       flipped = - nargs * 4;                                  \
+       flip_bytes (&flipped, 4);                               \
+       *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped;   \
+}
diff --git a/gdb/tm-vax.h b/gdb/tm-vax.h
new file mode 100644 (file)
index 0000000..c7a91b4
--- /dev/null
@@ -0,0 +1,377 @@
+/* Definitions to make GDB run on a vax under 4.2bsd.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* There is one known bug with VAX support that I don't know how to
+   fix:  if you do a backtrace from a signal handler, you get something
+   like:
+#0  0xbc in kill (592, 3)
+#1  0x7f in hand (...) (...)
+#2  0x7fffec7e in ?? (2, 0, 2147478112, 94)
+                  ^^ GDB doesn't know about sigtramp
+#3  0x7fffec70 in ?? (592, 2)
+    ^^^^^^^^^^ wrong address
+#4  0xae in main (...) (...)
+
+when the correct backtrace (as given by adb) is:
+_kill(250,3) from _hand+21
+_hand(2,0,7fffea60,5e) from 7fffec7e
+sigtramp(2,0,7fffea60,5e) from _kill+4
+_kill(250,2) from _main+2e
+_main(1,7fffeac4,7fffeacc) from start+3d
+
+If anyone knows enough about VAX BSD to fix this, please send the
+fix to bug-gdb@prep.ai.mit.edu.  */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Define this if the C compiler puts an underscore at the front
+   of external names before giving them to the linker.  */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format.  */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+   Zero on most machines.  */
+
+#define FUNCTION_START_OFFSET 2
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+#define SKIP_PROLOGUE(pc)      \
+{ register int op = (unsigned char) read_memory_integer (pc, 1);  \
+  if (op == 0x11) pc += 2;  /* skip brb */                       \
+  if (op == 0x31) pc += 3;  /* skip brw */                       \
+  if (op == 0xC2 &&                                              \
+      ((unsigned char) read_memory_integer (pc+2, 1)) == 0x5E)   \
+    pc += 3;  /* skip subl2 */                                   \
+  if (op == 0x9E &&                                              \
+      ((unsigned char) read_memory_integer (pc+1, 1)) == 0xAE &&  \
+      ((unsigned char) read_memory_integer(pc+3, 1)) == 0x5E)    \
+     pc += 4;  /* skip movab */                                          \
+  if (op == 0x9E &&                                              \
+      ((unsigned char) read_memory_integer (pc+1, 1)) == 0xCE &&  \
+      ((unsigned char) read_memory_integer(pc+4, 1)) == 0x5E)    \
+    pc += 5;  /* skip movab */                                   \
+  if (op == 0x9E &&                                              \
+      ((unsigned char) read_memory_integer (pc+1, 1)) == 0xEE &&  \
+      ((unsigned char) read_memory_integer(pc+6, 1)) == 0x5E)    \
+    pc += 7;  /* skip movab */                                   \
+}
+
+/* Immediately after a function call, return the saved pc.
+   Can't always go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
+
+#define TARGET_UPAGES 10
+#define TARGET_NBPG 512
+#define STACK_END_ADDR (0x80000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* On the VAX, sigtramp is in the u area.  Can't check the exact
+   addresses because for cross-debugging we don't have VAX include
+   files around.  This should be close enough.  */
+#define IN_SIGTRAMP(pc, name) ((pc) >= STACK_END_ADDR && (pc < 0x80000000))
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+#define BREAKPOINT {3}
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.  */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.  */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 04)
+
+/* Return 1 if P points to an invalid floating point value.
+   LEN is the length in bytes -- not relevant on the Vax.  */
+
+#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 17
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", "ps"}
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define AP_REGNUM 12
+#define FP_REGNUM 13           /* Contains address of executing stack frame */
+#define SP_REGNUM 14           /* Contains address of top of stack */
+#define PC_REGNUM 15           /* Contains program counter */
+#define PS_REGNUM 16           /* Contains processor status */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (17*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the vax, all regs are 4 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+   for register N.  On the vax, all regs are 4 bytes.  */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)    \
+  bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)        \
+  bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+  { write_register (1, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+   the address in which a function should return its structure value,
+   as a CORE_ADDR (or an expression that can be used as one).  */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address
+   and produces the frame's chain-pointer.
+
+   FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+   and produces the nominal address of the caller frame.
+
+   However, if FRAME_CHAIN_VALID returns zero,
+   it means the given frame is the outermost one and has no caller.
+   In that case, FRAME_CHAIN_COMBINE is not used.  */
+
+/* In the case of the Vax, the frame's nominal address is the FP value,
+   and 12 bytes later comes the saved previous FP value as a 4-byte word.  */
+
+#define FRAME_CHAIN(thisframe)  \
+  (outside_startup_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame + 12, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+/* On the vax, all functions have frames.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS)  {(FRAMELESS) = 0;}
+
+/* Saved Pc.  */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 16, 4))
+
+/* Cannot find the AP register value directly from the FP value.  Must
+   find it saved in the frame called by this one, or in the AP
+   register for the innermost frame.  However, there is no way to tell
+   the difference between the innermost frame and a frame for which we
+   just don't know the frame that it called (e.g. "info frame
+   0x7ffec789").  For the sake of argument suppose that the stack is
+   somewhat trashed (which is one reason that "info frame" exists).
+   So return 0 (indicating we don't know the address of
+   the arglist) if we don't know what frame this frame calls.  */
+#define FRAME_ARGS_ADDRESS_CORRECT(fi) \
+ (((fi)->next_frame                                  \
+   ? read_memory_integer ((fi)->next_frame + 8, 4)   \
+   : /* read_register (AP_REGNUM) */ 0))
+
+/* In most of GDB, getting the args address is too important to
+   just say "I don't know".  This is sometimes wrong for functions
+   that aren't on top of the stack, but c'est la vie.  */
+#define FRAME_ARGS_ADDRESS(fi) \
+ (((fi)->next_frame                                  \
+   ? read_memory_integer ((fi)->next_frame + 8, 4)   \
+   : read_register (AP_REGNUM) /* 0 */))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+   Can return -1, meaning no way to tell.  */
+
+#define FRAME_NUM_ARGS(numargs, fi)  \
+{ numargs = (0xff & read_memory_integer (FRAME_ARGS_ADDRESS (fi), 1)); }
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 4
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum;     \
+  register int regmask = read_memory_integer ((frame_info)->frame+4, 4) >> 16; \
+  register CORE_ADDR next_addr;     \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);     \
+  next_addr = (frame_info)->frame + 16;     \
+  /* Regmask's low bit is for register 0,     \
+     which is the first one that would be pushed.  */     \
+  for (regnum = 0; regnum < 12; regnum++, regmask >>= 1)  \
+    (frame_saved_regs).regs[regnum] = (regmask & 1) ? (next_addr += 4) : 0;  \
+  (frame_saved_regs).regs[SP_REGNUM] = next_addr + 4;  \
+  if (read_memory_integer ((frame_info)->frame + 4, 4) & 0x20000000)   \
+    (frame_saved_regs).regs[SP_REGNUM] += 4 + 4 * read_memory_integer (next_addr + 4, 4);  \
+  (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 16;  \
+  (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 12;  \
+  (frame_saved_regs).regs[AP_REGNUM] = (frame_info)->frame + 8;  \
+  (frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4;  \
+}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc.  */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+  register int regnum;                             \
+  sp = push_word (sp, 0); /* arglist */                    \
+  for (regnum = 11; regnum >= 0; regnum--)         \
+    sp = push_word (sp, read_register (regnum));    \
+  sp = push_word (sp, read_register (PC_REGNUM));   \
+  sp = push_word (sp, read_register (FP_REGNUM));   \
+  sp = push_word (sp, read_register (AP_REGNUM));   \
+  sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef)   \
+                     + 0x2fff0000);                \
+  sp = push_word (sp, 0);                          \
+  write_register (SP_REGNUM, sp);                  \
+  write_register (FP_REGNUM, sp);                  \
+  write_register (AP_REGNUM, sp + 17 * sizeof (int)); }
+
+/* Discard from the stack the innermost frame, restoring all registers.  */
+
+#define POP_FRAME  \
+{ register CORE_ADDR fp = read_register (FP_REGNUM);            \
+  register int regnum;                                          \
+  register int regmask = read_memory_integer (fp + 4, 4);       \
+  write_register (PS_REGNUM,                                    \
+                 (regmask & 0xffff)                             \
+                 | (read_register (PS_REGNUM) & 0xffff0000));   \
+  write_register (PC_REGNUM, read_memory_integer (fp + 16, 4));  \
+  write_register (FP_REGNUM, read_memory_integer (fp + 12, 4));  \
+  write_register (AP_REGNUM, read_memory_integer (fp + 8, 4));   \
+  fp += 16;                                                     \
+  for (regnum = 0; regnum < 12; regnum++)                       \
+    if (regmask & (0x10000 << regnum))                          \
+      write_register (regnum, read_memory_integer (fp += 4, 4)); \
+  fp = fp + 4 + ((regmask >> 30) & 3);                          \
+  if (regmask & 0x20000000)                                     \
+    { regnum = read_memory_integer (fp, 4);                     \
+      fp += (regnum + 1) * 4; }                                         \
+  write_register (SP_REGNUM, fp);                               \
+  flush_cached_frames ();                                       \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+     calls #69, @#32323232
+     bpt
+   Note this is 8 bytes.  */
+
+#define CALL_DUMMY {0x329f69fb, 0x03323232}
+
+#define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p)   \
+{ *((char *) dummyname + 1) = nargs;           \
+  *(int *)((char *) dummyname + 3) = fun; }
diff --git a/gdb/tm-vxworks68.h b/gdb/tm-vxworks68.h
new file mode 100755 (executable)
index 0000000..a3cd7c2
--- /dev/null
@@ -0,0 +1,48 @@
+/* Parameters for execution on VxWorks 68k's, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define        GDBINIT_FILENAME        ".vxgdbinit"
+
+#define        DEFAULT_PROMPT          "(vxgdb) "
+
+/* Kludge... */
+#include "tm-sun3.h"
+
+/* We have more complex, useful breakpoints on the target.  */
+#undef DECR_PC_AFTER_BREAK
+#define        DECR_PC_AFTER_BREAK     0
+
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+#undef FRAME_CHAIN
+#undef FRAME_CHAIN_VALID
+
+/* Takes the current frame-struct pointer and returns the chain-pointer
+   to get to the calling frame.
+
+   If our current frame pointer is zero, we're at the top; else read out
+   the saved FP from memory pointed to by the current FP.  */
+
+#define FRAME_CHAIN(thisframe) ((thisframe)->frame? read_memory_integer ((thisframe)->frame, 4): 0)
+
+/* If the chain pointer is zero (either because the saved value fetched
+   by FRAME_CHAIN was zero, or because the current FP was zero so FRAME_CHAIN
+   never fetched anything), we are at the top of the stack.  */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
diff --git a/gdb/tm-vxworks960.h b/gdb/tm-vxworks960.h
new file mode 100755 (executable)
index 0000000..fc5c214
--- /dev/null
@@ -0,0 +1,48 @@
+/* Parameters for VxWorks Intel 960's, for GDB, the GNU debugger.
+   Copyright (C) 1986-1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "tm-i960.h"
+
+#define        GDBINIT_FILENAME        ".vxgdbinit"
+
+#define        DEFAULT_PROMPT          "(vxgdb) "
+
+/* We have more complex, useful breakpoints on the target.
+   Amount ip must be decremented by after a breakpoint.  */
+
+#define        DECR_PC_AFTER_BREAK     0
+
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
+
+/* Breakpoint patching is handled at the target end in VxWorks.  */
+/* #define BREAKPOINT {0x00, 0x3e, 0x00, 0x66} */
+
+/* Not needed, because we don't support core files:
+       #define KERNEL_U_ADDR
+       #define REGISTER_U_ADDR(addr, blockend, regno)
+ */
+
+/* Address of end of stack space.
+       This doesn't matter for VxWorks, because it's only used
+       in manipulation of core files, which we don't support.  */
+
+/* #define STACK_END_ADDR (0xfe000000) */
diff --git a/gdb/umax-xdep.c b/gdb/umax-xdep.c
new file mode 100644 (file)
index 0000000..f3504da
--- /dev/null
@@ -0,0 +1,139 @@
+/* umax host stuff.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+#include <sys/ptrace.h>
+#define PTRACE_ATTACH PT_ATTACH
+#define PTRACE_DETACH PT_FREEPROC
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* Work with core dump and executable files, for GDB. 
+   This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+      /* 4.2-style (and perhaps also sysV-style) core dump file.  */
+      {
+       struct ptrace_user u;
+       int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name (filename);
+       data_start = exec_data_start;
+
+       data_end = data_start + u.pt_dsize;
+       stack_start = stack_end - u.pt_ssize;
+       data_offset = sizeof u;
+       stack_offset = data_offset + u.pt_dsize;
+       reg_offset = 0;
+
+       bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
+       printf ("Core file is from \"%s\".\n", u.pt_comm);
+       if (u.pt_signal > 0)
+         printf ("Program terminated with signal %d, %s.\n",
+                       u.pt_signal,
+                       u.pt_signal < NSIG
+                       ? sys_siglist[u.pt_signal]
+                       : "(undocumented)");
+
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < NUM_REGS; regno++)
+           {
+             char buf[MAX_REGISTER_RAW_SIZE];
+
+             val = lseek (corechan, register_addr (regno, reg_offset), 0);
+             if (val < 0)
+               perror_with_name (filename);
+
+             val = myread (corechan, buf, sizeof buf);
+             if (val < 0)
+               perror_with_name (filename);
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
diff --git a/gdb/utils.c b/gdb/utils.c
new file mode 100644 (file)
index 0000000..1441db1
--- /dev/null
@@ -0,0 +1,1294 @@
+/* General utility routines for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include "defs.h"
+#include "param.h"
+#include "signals.h"
+#include "gdbcmd.h"
+#include "terminal.h"
+#include <varargs.h>
+#include <ctype.h>
+#include <string.h>
+#include "bfd.h"
+#include "target.h"
+
+extern volatile void return_to_top_level ();
+extern volatile void exit ();
+extern char *gdb_readline ();
+extern char *getenv();
+extern char *malloc();
+extern char *realloc();
+
+/* If this definition isn't overridden by the header files, assume
+   that isatty and fileno exist on this system.  */
+#ifndef ISATTY
+#define ISATTY(FP)     (isatty (fileno (FP)))
+#endif
+
+#ifdef MISSING_VPRINTF
+#ifdef __GNU_LIBRARY
+#undef MISSING_VPRINTF
+#else  /* !__GNU_LIBRARY */
+
+#ifndef vfprintf
+#define vfprintf(file, format, ap) _doprnt (format, ap, file)
+#endif /* vfprintf */
+
+#ifndef vprintf
+/* Can't #define it since printcmd.c needs it */
+void
+vprintf (format, ap)
+     char *format; void *ap;
+{
+  vfprintf (stdout, format, ap);
+}
+#endif /* vprintf */
+
+#endif /* GNU_LIBRARY */
+#endif /* MISSING_VPRINTF */
+
+void error ();
+void fatal ();
+
+/* Chain of cleanup actions established with make_cleanup,
+   to be executed if an error happens.  */
+
+static struct cleanup *cleanup_chain;
+
+/* Nonzero means a quit has been requested.  */
+
+int quit_flag;
+
+/* Nonzero means quit immediately if Control-C is typed now,
+   rather than waiting until QUIT is executed.  */
+
+int immediate_quit;
+
+/* Nonzero means that encoded C++ names should be printed out in their
+   C++ form rather than raw.  */
+
+int demangle = 1;
+
+/* Nonzero means that encoded C++ names should be printed out in their
+   C++ form even in assembler language displays.  If this is set, but
+   DEMANGLE is zero, names are printed raw, i.e. DEMANGLE controls.  */
+
+int asm_demangle = 0;
+
+/* Nonzero means that strings with character values >0x7F should be printed
+   as octal escapes.  Zero means just print the value (e.g. it's an
+   international character, and the terminal or window can cope.)  */
+
+int sevenbit_strings = 0;
+\f
+/* Add a new cleanup to the cleanup_chain,
+   and return the previous chain pointer
+   to be passed later to do_cleanups or discard_cleanups.
+   Args are FUNCTION to clean up with, and ARG to pass to it.  */
+
+struct cleanup *
+make_cleanup (function, arg)
+     void (*function) ();
+     int arg;
+{
+  register struct cleanup *new
+    = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+  register struct cleanup *old_chain = cleanup_chain;
+
+  new->next = cleanup_chain;
+  new->function = function;
+  new->arg = arg;
+  cleanup_chain = new;
+
+  return old_chain;
+}
+
+/* Discard cleanups and do the actions they describe
+   until we get back to the point OLD_CHAIN in the cleanup_chain.  */
+
+void
+do_cleanups (old_chain)
+     register struct cleanup *old_chain;
+{
+  register struct cleanup *ptr;
+  while ((ptr = cleanup_chain) != old_chain)
+    {
+      (*ptr->function) (ptr->arg);
+      cleanup_chain = ptr->next;
+      free (ptr);
+    }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+   until we get back to the point OLD_CHAIN in the cleanup_chain.  */
+
+void
+discard_cleanups (old_chain)
+     register struct cleanup *old_chain;
+{
+  register struct cleanup *ptr;
+  while ((ptr = cleanup_chain) != old_chain)
+    {
+      cleanup_chain = ptr->next;
+      free (ptr);
+    }
+}
+
+/* Set the cleanup_chain to 0, and return the old cleanup chain.  */
+struct cleanup *
+save_cleanups ()
+{
+  struct cleanup *old_chain = cleanup_chain;
+
+  cleanup_chain = 0;
+  return old_chain;
+}
+
+/* Restore the cleanup chain from a previously saved chain.  */
+void
+restore_cleanups (chain)
+     struct cleanup *chain;
+{
+  cleanup_chain = chain;
+}
+
+/* This function is useful for cleanups.
+   Do
+
+     foo = xmalloc (...);
+     old_chain = make_cleanup (free_current_contents, &foo);
+
+   to arrange to free the object thus allocated.  */
+
+void
+free_current_contents (location)
+     char **location;
+{
+  free (*location);
+}
+\f
+/* Print an error message and return to command level.
+   The first argument STRING is the error message, used as a fprintf string,
+   and the remaining args are passed as arguments to it.  */
+
+/* VARARGS */
+void
+error (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *string;
+
+  va_start (args);
+  target_terminal_ours ();
+  fflush (stdout);
+  string = va_arg (args, char *);
+  vfprintf (stderr, string, args);
+  fprintf (stderr, "\n");
+  va_end (args);
+  return_to_top_level ();
+}
+
+/* Print an error message and exit reporting failure.
+   This is for a error that we cannot continue from.
+   The arguments are printed a la printf.  */
+
+/* VARARGS */
+void
+fatal (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *string;
+
+  va_start (args);
+  string = va_arg (args, char *);
+  fprintf (stderr, "gdb: ");
+  vfprintf (stderr, string, args);
+  fprintf (stderr, "\n");
+  va_end (args);
+  exit (1);
+}
+
+/* Print an error message and exit, dumping core.
+   The arguments are printed a la printf ().  */
+/* VARARGS */
+void
+fatal_dump_core (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *string;
+
+  va_start (args);
+  string = va_arg (args, char *);
+  /* "internal error" is always correct, since GDB should never dump
+     core, no matter what the input.  */
+  fprintf (stderr, "gdb internal error: ");
+  vfprintf (stderr, string, args);
+  fprintf (stderr, "\n");
+  va_end (args);
+
+  signal (SIGQUIT, SIG_DFL);
+  kill (getpid (), SIGQUIT);
+  /* We should never get here, but just in case...  */
+  exit (1);
+}
+\f
+/* Memory management stuff (malloc friends).  */
+
+#if defined (NO_MALLOC_CHECK)
+void
+init_malloc ()
+{}
+#else /* Have mcheck().  */
+static void
+malloc_botch ()
+{
+  fatal_dump_core ("Memory corruption");
+}
+
+void
+init_malloc ()
+{
+  mcheck (malloc_botch);
+}
+#endif /* Have mcheck().  */
+
+/* Like malloc but get error if no storage available.  */
+
+#ifdef __STDC__
+void *
+#else
+char *
+#endif
+xmalloc (size)
+     long size;
+{
+  register char *val;
+
+  /* At least one place (dbxread.c:condense_misc_bunches where misc_count == 0)
+     GDB wants to allocate zero bytes.  */
+  if (size == 0)
+    return NULL;
+  
+  val = (char *) malloc (size);
+  if (!val)
+    fatal ("virtual memory exhausted.", 0);
+  return val;
+}
+
+/* Like realloc but get error if no storage available.  */
+
+#ifdef __STDC__
+void *
+#else
+char *
+#endif
+xrealloc (ptr, size)
+     char *ptr;
+     long size;
+{
+  register char *val = (char *) realloc (ptr, size);
+  if (!val)
+    fatal ("virtual memory exhausted.", 0);
+  return val;
+}
+
+/* Print the system error message for errno, and also mention STRING
+   as the file name for which the error was encountered.
+   Then return to command level.  */
+
+void
+perror_with_name (string)
+     char *string;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  char *err;
+  char *combined;
+
+  if (errno < sys_nerr)
+    err = sys_errlist[errno];
+  else
+    err = "unknown error";
+
+  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+  strcpy (combined, string);
+  strcat (combined, ": ");
+  strcat (combined, err);
+
+  /* I understand setting these is a matter of taste.  Still, some people
+     may clear errno but not know about bfd_error.  Doing this here is not
+     unreasonable. */
+  bfd_error = no_error;
+  errno = 0;
+
+  error ("%s.", combined);
+}
+
+/* Print the system error message for ERRCODE, and also mention STRING
+   as the file name for which the error was encountered.  */
+
+void
+print_sys_errmsg (string, errcode)
+     char *string;
+     int errcode;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  char *err;
+  char *combined;
+
+  if (errcode < sys_nerr)
+    err = sys_errlist[errcode];
+  else
+    err = "unknown error";
+
+  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+  strcpy (combined, string);
+  strcat (combined, ": ");
+  strcat (combined, err);
+
+  printf ("%s.\n", combined);
+}
+
+/* Control C eventually causes this to be called, at a convenient time.  */
+
+void
+quit ()
+{
+  target_terminal_ours ();
+#ifdef HAVE_TERMIO
+  ioctl (fileno (stdout), TCFLSH, 1);
+#else /* not HAVE_TERMIO */
+  ioctl (fileno (stdout), TIOCFLUSH, 0);
+#endif /* not HAVE_TERMIO */
+#ifdef TIOCGPGRP
+  error ("Quit");
+#else
+  error ("Quit (expect signal %d when inferior is resumed)", SIGINT);
+#endif /* TIOCGPGRP */
+}
+
+/* Control C comes here */
+
+void
+request_quit ()
+{
+  quit_flag = 1;
+
+#ifdef USG
+  /* Restore the signal handler.  */
+  signal (SIGINT, request_quit);
+#endif
+
+  if (immediate_quit)
+    quit ();
+}
+\f
+/* My replacement for the read system call.
+   Used like `read' but keeps going if `read' returns too soon.  */
+
+int
+myread (desc, addr, len)
+     int desc;
+     char *addr;
+     int len;
+{
+  register int val;
+  int orglen = len;
+
+  while (len > 0)
+    {
+      val = read (desc, addr, len);
+      if (val < 0)
+       return val;
+      if (val == 0)
+       return orglen - len;
+      len -= val;
+      addr += val;
+    }
+  return orglen;
+}
+\f
+/* Make a copy of the string at PTR with SIZE characters
+   (and add a null character at the end in the copy).
+   Uses malloc to get the space.  Returns the address of the copy.  */
+
+char *
+savestring (ptr, size)
+     char *ptr;
+     int size;
+{
+  register char *p = (char *) xmalloc (size + 1);
+  bcopy (ptr, p, size);
+  p[size] = 0;
+  return p;
+}
+
+char *
+strsave (ptr)
+     char *ptr;
+{
+  return savestring (ptr, strlen (ptr));
+}
+
+char *
+concat (s1, s2, s3)
+     char *s1, *s2, *s3;
+{
+  register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+  register char *val = (char *) xmalloc (len);
+  strcpy (val, s1);
+  strcat (val, s2);
+  strcat (val, s3);
+  return val;
+}
+
+void
+print_spaces (n, file)
+     register int n;
+     register FILE *file;
+{
+  while (n-- > 0)
+    fputc (' ', file);
+}
+
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+   Takes three args which are given to printf to print the question.
+   The first, a control string, should end in "? ".
+   It should not say how to answer, because we do that.  */
+
+/* VARARGS */
+int
+query (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *ctlstr;
+  register int answer;
+  register int ans2;
+
+  /* Automatically answer "yes" if input is not from a terminal.  */
+  if (!input_from_terminal_p ())
+    return 1;
+
+  while (1)
+    {
+      va_start (args);
+      ctlstr = va_arg (args, char *);
+      vfprintf (stdout, ctlstr, args);
+      va_end (args);
+      printf ("(y or n) ");
+      fflush (stdout);
+      answer = fgetc (stdin);
+      clearerr (stdin);                /* in case of C-d */
+      if (answer == EOF)       /* C-d */
+        return 1;
+      if (answer != '\n')      /* Eat rest of input line, to EOF or newline */
+       do 
+         {
+           ans2 = fgetc (stdin);
+           clearerr (stdin);
+         }
+        while (ans2 != EOF && ans2 != '\n');
+      if (answer >= 'a')
+       answer -= 040;
+      if (answer == 'Y')
+       return 1;
+      if (answer == 'N')
+       return 0;
+      printf ("Please answer y or n.\n");
+    }
+}
+\f
+/* Parse a C escape sequence.  STRING_PTR points to a variable
+   containing a pointer to the string to parse.  That pointer
+   should point to the character after the \.  That pointer
+   is updated past the characters we use.  The value of the
+   escape sequence is returned.
+
+   A negative value means the sequence \ newline was seen,
+   which is supposed to be equivalent to nothing at all.
+
+   If \ is followed by a null character, we return a negative
+   value and leave the string pointer pointing at the null character.
+
+   If \ is followed by 000, we return 0 and leave the string pointer
+   after the zeros.  A value of 0 does not mean end of string.  */
+
+int
+parse_escape (string_ptr)
+     char **string_ptr;
+{
+  register int c = *(*string_ptr)++;
+  switch (c)
+    {
+    case 'a':
+      return '\a';
+    case 'b':
+      return '\b';
+    case 'e':
+      return 033;
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    case 'v':
+      return '\v';
+    case '\n':
+      return -2;
+    case 0:
+      (*string_ptr)--;
+      return 0;
+    case '^':
+      c = *(*string_ptr)++;
+      if (c == '\\')
+       c = parse_escape (string_ptr);
+      if (c == '?')
+       return 0177;
+      return (c & 0200) | (c & 037);
+      
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+      {
+       register int i = c - '0';
+       register int count = 0;
+       while (++count < 3)
+         {
+           if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+             {
+               i *= 8;
+               i += c - '0';
+             }
+           else
+             {
+               (*string_ptr)--;
+               break;
+             }
+         }
+       return i;
+      }
+    default:
+      return c;
+    }
+}
+\f
+/* Print the character CH on STREAM as part of the contents
+   of a literal string whose delimiter is QUOTER.  */
+
+void
+printchar (ch, stream, quoter)
+     unsigned char ch;
+     FILE *stream;
+     int quoter;
+{
+  register int c = ch;
+
+  if (c < 040 || (sevenbit_strings && c >= 0177))
+    switch (c)
+      {
+      case '\n':
+       fputs_filtered ("\\n", stream);
+       break;
+      case '\b':
+       fputs_filtered ("\\b", stream);
+       break;
+      case '\t':
+       fputs_filtered ("\\t", stream);
+       break;
+      case '\f':
+       fputs_filtered ("\\f", stream);
+       break;
+      case '\r':
+       fputs_filtered ("\\r", stream);
+       break;
+      case '\033':
+       fputs_filtered ("\\e", stream);
+       break;
+      case '\007':
+       fputs_filtered ("\\a", stream);
+       break;
+      default:
+       fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
+       break;
+      }
+  else
+    {
+      if (c == '\\' || c == quoter)
+       fputs_filtered ("\\", stream);
+      fprintf_filtered (stream, "%c", c);
+    }
+}
+\f
+/* Number of lines per page or UINT_MAX if paging is disabled.  */
+static unsigned int lines_per_page;
+/* Number of chars per line or UNIT_MAX is line folding is disabled.  */
+static unsigned int chars_per_line;
+/* Current count of lines printed on this page, chars on this line.  */
+static unsigned int lines_printed, chars_printed;
+
+/* Buffer and start column of buffered text, for doing smarter word-
+   wrapping.  When someone calls wrap_here(), we start buffering output
+   that comes through fputs_filtered().  If we see a newline, we just
+   spit it out and forget about the wrap_here().  If we see another
+   wrap_here(), we spit it out and remember the newer one.  If we see
+   the end of the line, we spit out a newline, the indent, and then
+   the buffered output.
+
+   wrap_column is the column number on the screen where wrap_buffer begins.
+     When wrap_column is zero, wrapping is not in effect.
+   wrap_buffer is malloc'd with chars_per_line+2 bytes. 
+     When wrap_buffer[0] is null, the buffer is empty.
+   wrap_pointer points into it at the next character to fill.
+   wrap_indent is the string that should be used as indentation if the
+     wrap occurs.  */
+
+static char *wrap_buffer, *wrap_pointer, *wrap_indent;
+static int wrap_column;
+
+/* Get the number of lines to print with commands like "list".
+   This is based on guessing how many long (i.e. more than chars_per_line
+   characters) lines there will be.  To be completely correct, "list"
+   and friends should be rewritten to count characters and see where
+   things are wrapping, but that would be a fair amount of work.  */
+int
+lines_to_list ()
+{
+  /* RMS didn't like the following algorithm.  Let's set it back to
+     10 and see if anyone else complains.  */
+  /* return lines_per_page == UINT_MAX ? 10 : lines_per_page / 2; */
+  return 10;
+}
+
+static void 
+set_width_command (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  if (!wrap_buffer)
+    {
+      wrap_buffer = (char *) xmalloc (chars_per_line + 2);
+      wrap_buffer[0] = '\0';
+    }
+  else
+    wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2);
+  wrap_pointer = wrap_buffer;  /* Start it at the beginning */
+}
+
+static void
+prompt_for_continue ()
+{
+  immediate_quit++;
+  gdb_readline ("---Type <return> to continue---", 0);
+  chars_printed = lines_printed = 0;
+  immediate_quit--;
+}
+
+/* Reinitialize filter; ie. tell it to reset to original values.  */
+
+void
+reinitialize_more_filter ()
+{
+  lines_printed = 0;
+  chars_printed = 0;
+}
+
+/* Indicate that if the next sequence of characters overflows the line,
+   a newline should be inserted here rather than when it hits the end. 
+   If INDENT is nonzero, it is a string to be printed to indent the
+   wrapped part on the next line.  INDENT must remain accessible until
+   the next call to wrap_here() or until a newline is printed through
+   fputs_filtered().
+
+   If the line is already overfull, we immediately print a newline and
+   the indentation, and disable further wrapping.
+
+   INDENT should not contain tabs, as that
+   will mess up the char count on the next line.  FIXME.  */
+
+void
+wrap_here(indent)
+  char *indent;
+{
+  if (wrap_buffer[0])
+    {
+      *wrap_pointer = '\0';
+      fputs (wrap_buffer, stdout);
+    }
+  wrap_pointer = wrap_buffer;
+  wrap_buffer[0] = '\0';
+  if (chars_printed >= chars_per_line)
+    {
+      puts_filtered ("\n");
+      puts_filtered (indent);
+      wrap_column = 0;
+    }
+  else
+    {
+      wrap_column = chars_printed;
+      wrap_indent = indent;
+    }
+}
+
+/* Like fputs but pause after every screenful, and can wrap at points
+   other than the final character of a line.
+   Unlike fputs, fputs_filtered does not return a value.
+   It is OK for LINEBUFFER to be NULL, in which case just don't print
+   anything.
+
+   Note that a longjmp to top level may occur in this routine
+   (since prompt_for_continue may do so) so this routine should not be
+   called when cleanups are not in place.  */
+
+void
+fputs_filtered (linebuffer, stream)
+     char *linebuffer;
+     FILE *stream;
+{
+  char *lineptr;
+
+  if (linebuffer == 0)
+    return;
+  
+  /* Don't do any filtering if it is disabled.  */
+  if (stream != stdout
+   || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
+    {
+      fputs (linebuffer, stream);
+      return;
+    }
+
+  /* Go through and output each character.  Show line extension
+     when this is necessary; prompt user for new page when this is
+     necessary.  */
+  
+  lineptr = linebuffer;
+  while (*lineptr)
+    {
+      /* Possible new page.  */
+      if (lines_printed >= lines_per_page - 1)
+       prompt_for_continue ();
+
+      while (*lineptr && *lineptr != '\n')
+       {
+         /* Print a single line.  */
+         if (*lineptr == '\t')
+           {
+             if (wrap_column)
+               *wrap_pointer++ = '\t';
+             else
+               putc ('\t', stream);
+             /* Shifting right by 3 produces the number of tab stops
+                we have already passed, and then adding one and
+                shifting left 3 advances to the next tab stop.  */
+             chars_printed = ((chars_printed >> 3) + 1) << 3;
+             lineptr++;
+           }
+         else
+           {
+             if (wrap_column)
+               *wrap_pointer++ = *lineptr;
+             else
+               putc (*lineptr, stream);
+             chars_printed++;
+             lineptr++;
+           }
+      
+         if (chars_printed >= chars_per_line)
+           {
+             unsigned int save_chars = chars_printed;
+
+             chars_printed = 0;
+             lines_printed++;
+             /* If we aren't actually wrapping, don't output newline --
+                if chars_per_line is right, we probably just overflowed
+                anyway; if it's wrong, let us keep going.  */
+             if (wrap_column)
+               putc ('\n', stream);
+
+             /* Possible new page.  */
+             if (lines_printed >= lines_per_page - 1)
+               prompt_for_continue ();
+
+             /* Now output indentation and wrapped string */
+             if (wrap_column)
+               {
+                 if (wrap_indent)
+                   fputs (wrap_indent, stream);
+                 *wrap_pointer = '\0';         /* Null-terminate saved stuff */
+                 fputs (wrap_buffer, stream);  /* and eject it */
+                 /* FIXME, this strlen is what prevents wrap_indent from
+                    containing tabs.  However, if we recurse to print it
+                    and count its chars, we risk trouble if wrap_indent is
+                    longer than (the user settable) chars_per_line. 
+                    Note also that this can set chars_printed > chars_per_line
+                    if we are printing a long string.  */
+                 chars_printed = strlen (wrap_indent)
+                               + (save_chars - wrap_column);
+                 wrap_pointer = wrap_buffer;   /* Reset buffer */
+                 wrap_buffer[0] = '\0';
+                 wrap_column = 0;              /* And disable fancy wrap */
+               }
+           }
+       }
+
+      if (*lineptr == '\n')
+       {
+         chars_printed = 0;
+         wrap_here ("");       /* Spit out chars, cancel further wraps */
+         lines_printed++;
+         putc ('\n', stream);
+         lineptr++;
+       }
+    }
+}
+
+
+/* fputs_demangled is a variant of fputs_filtered that
+   demangles g++ names.*/
+
+void
+fputs_demangled (linebuffer, stream, arg_mode)
+     char *linebuffer;
+     FILE *stream;
+     int arg_mode;
+{
+#ifdef __STDC__
+  extern char *cplus_demangle (const char *, int);
+#else
+  extern char *cplus_demangle ();
+#endif
+#define SYMBOL_MAX 1024
+
+#define SYMBOL_CHAR(c) (isascii(c) && (isalnum(c) || (c) == '_' || (c) == '$'))
+
+  char buf[SYMBOL_MAX+1];
+# define SLOP 5                /* How much room to leave in buf */
+  char *p;
+
+  if (linebuffer == NULL)
+    return;
+
+  /* If user wants to see raw output, no problem.  */
+  if (!demangle) {
+    fputs_filtered (linebuffer, stream);
+  }
+
+  p = linebuffer;
+
+  while ( *p != (char) 0 ) {
+    int i = 0;
+
+    /* collect non-interesting characters into buf */
+    while ( *p != (char) 0 && !SYMBOL_CHAR(*p) && i < (int)sizeof(buf)-SLOP ) {
+      buf[i++] = *p;
+      p++;
+    }
+    if (i > 0) {
+      /* output the non-interesting characters without demangling */
+      buf[i] = (char) 0;
+      fputs_filtered(buf, stream);
+      i = 0;  /* reset buf */
+    }
+
+    /* and now the interesting characters */
+    while (i < SYMBOL_MAX
+     && *p != (char) 0
+     && SYMBOL_CHAR(*p)
+     && i < (int)sizeof(buf) - SLOP) {
+      buf[i++] = *p;
+      p++;
+    }
+    buf[i] = (char) 0;
+    if (i > 0) {
+      char * result;
+      
+      if ( (result = cplus_demangle(buf, arg_mode)) != NULL ) {
+       fputs_filtered(result, stream);
+       free(result);
+      }
+      else {
+       fputs_filtered(buf, stream);
+      }
+    }
+  }
+}
+
+/* Print a variable number of ARGS using format FORMAT.  If this
+   information is going to put the amount written (since the last call
+   to INITIALIZE_MORE_FILTER or the last page break) over the page size,
+   print out a pause message and do a gdb_readline to get the users
+   permision to continue.
+
+   Unlike fprintf, this function does not return a value.
+
+   We implement three variants, vfprintf (takes a vararg list and stream),
+   fprintf (takes a stream to write on), and printf (the usual).
+
+   Note that this routine has a restriction that the length of the
+   final output line must be less than 255 characters *or* it must be
+   less than twice the size of the format string.  This is a very
+   arbitrary restriction, but it is an internal restriction, so I'll
+   put it in.  This means that the %s format specifier is almost
+   useless; unless the caller can GUARANTEE that the string is short
+   enough, fputs_filtered should be used instead.
+
+   Note also that a longjmp to top level may occur in this routine
+   (since prompt_for_continue may do so) so this routine should not be
+   called when cleanups are not in place.  */
+
+#if !defined(MISSING_VPRINTF) || defined (vsprintf)
+/* VARARGS */
+void
+vfprintf_filtered (stream, format, args)
+     va_list args;
+#else
+void fprintf_filtered (stream, format, arg1, arg2, arg3, arg4, arg5, arg6)
+#endif
+     FILE *stream;
+     char *format;
+{
+  static char *linebuffer = (char *) 0;
+  static int line_size;
+  int format_length;
+
+  format_length = strlen (format);
+
+  /* Allocated linebuffer for the first time.  */
+  if (!linebuffer)
+    {
+      linebuffer = (char *) xmalloc (255);
+      line_size = 255;
+    }
+
+  /* Reallocate buffer to a larger size if this is necessary.  */
+  if (format_length * 2 > line_size)
+    {
+      line_size = format_length * 2;
+
+      /* You don't have to copy.  */
+      free (linebuffer);
+      linebuffer = (char *) xmalloc (line_size);
+    }
+
+
+  /* This won't blow up if the restrictions described above are
+     followed.   */
+#if !defined(MISSING_VPRINTF) || defined (vsprintf)
+  (void) vsprintf (linebuffer, format, args);
+#else
+  (void) sprintf (linebuffer, format, arg1, arg2, arg3, arg4, arg5, arg6);
+#endif
+
+  fputs_filtered (linebuffer, stream);
+}
+
+#if !defined(MISSING_VPRINTF) || defined (vsprintf)
+/* VARARGS */
+void
+fprintf_filtered (va_alist)
+     va_dcl
+{
+  va_list args;
+  FILE *stream;
+  char *format;
+
+  va_start (args);
+  stream = va_arg (args, FILE *);
+  format = va_arg (args, char *);
+
+  /* This won't blow up if the restrictions described above are
+     followed.   */
+  (void) vfprintf_filtered (stream, format, args);
+  va_end (args);
+}
+
+/* VARARGS */
+void
+printf_filtered (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *format;
+
+  va_start (args);
+  format = va_arg (args, char *);
+
+  (void) vfprintf_filtered (stdout, format, args);
+  va_end (args);
+}
+#else
+void
+printf_filtered (format, arg1, arg2, arg3, arg4, arg5, arg6)
+     char *format;
+     int arg1, arg2, arg3, arg4, arg5, arg6;
+{
+  fprintf_filtered (stdout, format, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+#endif
+
+/* Easy */
+
+void
+puts_filtered (string)
+     char *string;
+{
+  fputs_filtered (string, stdout);
+}
+
+/* Return a pointer to N spaces and a null.  The pointer is good
+   until the next call to here.  */
+char *
+n_spaces (n)
+     int n;
+{
+  register char *t;
+  static char *spaces;
+  static int max_spaces;
+
+  if (n > max_spaces)
+    {
+      if (spaces)
+       free (spaces);
+      spaces = malloc (n+1);
+      for (t = spaces+n; t != spaces;)
+       *--t = ' ';
+      spaces[n] = '\0';
+      max_spaces = n;
+    }
+
+  return spaces + max_spaces - n;
+}
+
+/* Print N spaces.  */
+void
+print_spaces_filtered (n, stream)
+     int n;
+     FILE *stream;
+{
+  fputs_filtered (n_spaces (n), stream);
+}
+\f
+/* C++ demangler stuff.  */
+char *cplus_demangle ();
+
+/* Print NAME on STREAM, demangling if necessary.  */
+void
+fprint_symbol (stream, name)
+     FILE *stream;
+     char *name;
+{
+  char *demangled;
+  if ((!demangle) || NULL == (demangled = cplus_demangle (name, 1)))
+    fputs_filtered (name, stream);
+  else
+    {
+      fputs_filtered (demangled, stream);
+      free (demangled);
+    }
+}
+\f
+#if !defined (USG_UTILS)
+#define USG_UTILS defined (USG)
+#endif
+
+#if USG_UTILS
+bcopy (from, to, count)
+char *from, *to;
+{
+       memcpy (to, from, count);
+}
+
+bcmp (from, to, count)
+{
+       return (memcmp (to, from, count));
+}
+
+bzero (to, count)
+char *to;
+{
+       while (count--)
+               *to++ = 0;
+}
+
+getwd (buf)
+char *buf;
+{
+  getcwd (buf, MAXPATHLEN);
+}
+
+char *
+index (s, c)
+     char *s;
+{
+  char *strchr ();
+  return strchr (s, c);
+}
+
+char *
+rindex (s, c)
+     char *s;
+{
+  char *strrchr ();
+  return strrchr (s, c);
+}
+#endif /* USG_UTILS.  */
+
+#if !defined (QUEUE_MISSING)
+#define QUEUE_MISSING defined (USG)
+#endif
+
+#if QUEUE_MISSING
+/* Queue routines */
+
+struct queue {
+       struct queue *forw;
+       struct queue *back;
+};
+
+insque (item, after)
+struct queue *item;
+struct queue *after;
+{
+       item->forw = after->forw;
+       after->forw->back = item;
+
+       item->back = after;
+       after->forw = item;
+}
+
+remque (item)
+struct queue *item;
+{
+       item->forw->back = item->back;
+       item->back->forw = item->forw;
+}
+#endif /* QUEUE_MISSING */
+\f
+/* Simple implementation of strstr, since some implementations lack it. */
+char *
+strstr (in, find)
+     const char *in, *find;
+{
+  register char *p = in - 1;
+
+  while (0 != (p = strchr (p+1, *find))) {
+    if (strcmp (p, find))
+      return p;
+  }
+  return 0;
+}
+\f
+void
+_initialize_utils ()
+{
+  struct cmd_list_element *c;
+
+  c = add_set_cmd ("width", class_support, var_uinteger, 
+                 (char *)&chars_per_line,
+                 "Set number of characters gdb thinks are in a line.",
+                 &setlist);
+  add_show_from_set (c, &showlist);
+  c->function = set_width_command;
+
+  add_show_from_set
+    (add_set_cmd ("height", class_support,
+                 var_uinteger, (char *)&lines_per_page,
+                 "Set number of lines gdb thinks are in a page.", &setlist),
+     &showlist);
+  
+  /* These defaults will be used if we are unable to get the correct
+     values from termcap.  */
+  lines_per_page = 24;
+  chars_per_line = 80;
+  /* Initialize the screen height and width from termcap.  */
+  {
+    char *termtype = getenv ("TERM");
+
+    /* Positive means success, nonpositive means failure.  */
+    int status;
+
+    /* 2048 is large enough for all known terminals, according to the
+       GNU termcap manual.  */
+    char term_buffer[2048];
+
+    if (termtype)
+      {
+       status = tgetent (term_buffer, termtype);
+       if (status > 0)
+         {
+           int val;
+           
+           val = tgetnum ("li");
+           if (val >= 0)
+             lines_per_page = val;
+           else
+             /* The number of lines per page is not mentioned
+                in the terminal description.  This probably means
+                that paging is not useful (e.g. emacs shell window),
+                so disable paging.  */
+             lines_per_page = UINT_MAX;
+           
+           val = tgetnum ("co");
+           if (val >= 0)
+             chars_per_line = val;
+         }
+      }
+  }
+
+  set_width_command ((char *)NULL, 0, c);
+
+  add_show_from_set
+    (add_set_cmd ("demangle", class_support, var_boolean, 
+                 (char *)&demangle,
+               "Set demangling of encoded C++ names when displaying symbols.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("sevenbit-strings", class_support, var_boolean, 
+                 (char *)&sevenbit_strings,
+   "Set printing of 8-bit characters in strings as \\nnn.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("asm-demangle", class_support, var_boolean, 
+                 (char *)&asm_demangle,
+       "Set demangling of C++ names in disassembly listings.",
+                 &setlist),
+     &showlist);
+}
diff --git a/gdb/valarith.c b/gdb/valarith.c
new file mode 100644 (file)
index 0000000..6269def
--- /dev/null
@@ -0,0 +1,694 @@
+/* Perform arithmetic and other operations on values, for GDB.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "param.h"
+#include "value.h"
+#include "expression.h"
+#include "target.h"
+#include <string.h>
+
+\f
+value value_x_binop ();
+value value_subscripted_rvalue ();
+
+value
+value_add (arg1, arg2)
+       value arg1, arg2;
+{
+  register value val, valint, valptr;
+  register int len;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+       || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR)
+      &&
+      (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT
+       || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT))
+    /* Exactly one argument is a pointer, and one is an integer.  */
+    {
+      if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
+       {
+         valptr = arg1;
+         valint = arg2;
+       }
+      else
+       {
+         valptr = arg2;
+         valint = arg1;
+       }
+      len = TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (valptr)));
+      if (len == 0) len = 1;   /* For (void *) */
+      val = value_from_long (builtin_type_long,
+                            value_as_long (valptr)
+                            + (len * value_as_long (valint)));
+      VALUE_TYPE (val) = VALUE_TYPE (valptr);
+      return val;
+    }
+
+  return value_binop (arg1, arg2, BINOP_ADD);
+}
+
+value
+value_sub (arg1, arg2)
+       value arg1, arg2;
+{
+  register value val;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
+    {
+      if (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)
+       {
+         /* pointer - integer.  */
+         val = value_from_long
+           (builtin_type_long,
+            value_as_long (arg1)
+            - (TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)))
+               * value_as_long (arg2)));
+         VALUE_TYPE (val) = VALUE_TYPE (arg1);
+         return val;
+       }
+      else if (VALUE_TYPE (arg1) == VALUE_TYPE (arg2))
+       {
+         /* pointer to <type x> - pointer to <type x>.  */
+         val = value_from_long
+           (builtin_type_long,
+            (value_as_long (arg1) - value_as_long (arg2))
+            / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))));
+         return val;
+       }
+      else
+       {
+         error ("\
+First argument of `-' is a pointer and second argument is neither\n\
+an integer nor a pointer of the same type.");
+       }
+    }
+
+  return value_binop (arg1, arg2, BINOP_SUB);
+}
+
+/* Return the value of ARRAY[IDX].  */
+
+value
+value_subscript (array, idx)
+     value array, idx;
+{
+  if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY
+      && VALUE_LVAL (array) != lval_memory)
+    return value_subscripted_rvalue (array, idx);
+  else
+    return value_ind (value_add (array, idx));
+}
+
+/* Return the value of EXPR[IDX], expr an aggregate rvalue
+   (eg, a vector register).  This routine used to promote floats
+   to doubles, but no longer does.  */
+
+value
+value_subscripted_rvalue (array, idx)
+     value array, idx;
+{
+  struct type *elt_type = TYPE_TARGET_TYPE (VALUE_TYPE (array));
+  int elt_size = TYPE_LENGTH (elt_type);
+  int elt_offs = elt_size * value_as_long (idx);
+  value v;
+
+  if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array)))
+    error ("no such vector element");
+
+  v = allocate_value (elt_type);
+  bcopy (VALUE_CONTENTS (array) + elt_offs, VALUE_CONTENTS (v), elt_size);
+
+  if (VALUE_LVAL (array) == lval_internalvar)
+    VALUE_LVAL (v) = lval_internalvar_component;
+  else
+    VALUE_LVAL (v) = not_lval;
+  VALUE_ADDRESS (v) = VALUE_ADDRESS (array);
+  VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs;
+  VALUE_BITSIZE (v) = elt_size * 8;
+  return v;
+}
+\f
+/* Check to see if either argument is a structure.  This is called so
+   we know whether to go ahead with the normal binop or look for a 
+   user defined function instead.
+
+   For now, we do not overload the `=' operator.  */
+
+int
+binop_user_defined_p (op, arg1, arg2)
+     enum exp_opcode op;
+     value arg1, arg2;
+{
+  if (op == BINOP_ASSIGN)
+    return 0;
+  return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
+         || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_STRUCT
+         || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
+             && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT)
+         || (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_REF
+             && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_STRUCT));
+}
+
+/* Check to see if argument is a structure.  This is called so
+   we know whether to go ahead with the normal unop or look for a 
+   user defined function instead.
+
+   For now, we do not overload the `&' operator.  */
+
+int unop_user_defined_p (op, arg1)
+     enum exp_opcode op;
+     value arg1;
+{
+  if (op == UNOP_ADDR)
+    return 0;
+  return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
+         || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
+             && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT));
+}
+
+/* We know either arg1 or arg2 is a structure, so try to find the right
+   user defined function.  Create an argument vector that calls 
+   arg1.operator @ (arg1,arg2) and return that value (where '@' is any
+   binary operator which is legal for GNU C++).  */
+
+value
+value_x_binop (arg1, arg2, op, otherop)
+     value arg1, arg2;
+     enum exp_opcode op, otherop;
+{
+  value * argvec;
+  char *ptr;
+  char tstr[13];
+  int static_memfuncp;
+
+  COERCE_ENUM (arg1);
+  COERCE_ENUM (arg2);
+
+  /* now we know that what we have to do is construct our
+     arg vector and find the right function to call it with.  */
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
+    error ("Can't do that binary op on that type");  /* FIXME be explicit */
+
+  argvec = (value *) alloca (sizeof (value) * 4);
+  argvec[1] = value_addr (arg1);
+  argvec[2] = arg2;
+  argvec[3] = 0;
+
+  /* make the right function name up */  
+  strcpy(tstr, "operator__");
+  ptr = tstr+8;
+  switch (op)
+    {
+    case BINOP_ADD:    strcpy(ptr,"+"); break;
+    case BINOP_SUB:    strcpy(ptr,"-"); break;
+    case BINOP_MUL:    strcpy(ptr,"*"); break;
+    case BINOP_DIV:    strcpy(ptr,"/"); break;
+    case BINOP_REM:    strcpy(ptr,"%"); break;
+    case BINOP_LSH:    strcpy(ptr,"<<"); break;
+    case BINOP_RSH:    strcpy(ptr,">>"); break;
+    case BINOP_LOGAND: strcpy(ptr,"&"); break;
+    case BINOP_LOGIOR: strcpy(ptr,"|"); break;
+    case BINOP_LOGXOR: strcpy(ptr,"^"); break;
+    case BINOP_AND:    strcpy(ptr,"&&"); break;
+    case BINOP_OR:     strcpy(ptr,"||"); break;
+    case BINOP_MIN:    strcpy(ptr,"<?"); break;
+    case BINOP_MAX:    strcpy(ptr,">?"); break;
+    case BINOP_ASSIGN: strcpy(ptr,"="); break;
+    case BINOP_ASSIGN_MODIFY:  
+      switch (otherop)
+       {
+       case BINOP_ADD:      strcpy(ptr,"+="); break;
+       case BINOP_SUB:      strcpy(ptr,"-="); break;
+       case BINOP_MUL:      strcpy(ptr,"*="); break;
+       case BINOP_DIV:      strcpy(ptr,"/="); break;
+       case BINOP_REM:      strcpy(ptr,"%="); break;
+       case BINOP_LOGAND:   strcpy(ptr,"&="); break;
+       case BINOP_LOGIOR:   strcpy(ptr,"|="); break;
+       case BINOP_LOGXOR:   strcpy(ptr,"^="); break;
+       default:
+         error ("Invalid binary operation specified.");
+       }
+      break;
+    case BINOP_SUBSCRIPT: strcpy(ptr,"[]"); break;
+    case BINOP_EQUAL:    strcpy(ptr,"=="); break;
+    case BINOP_NOTEQUAL:  strcpy(ptr,"!="); break;
+    case BINOP_LESS:      strcpy(ptr,"<"); break;
+    case BINOP_GTR:       strcpy(ptr,">"); break;
+    case BINOP_GEQ:       strcpy(ptr,">="); break;
+    case BINOP_LEQ:       strcpy(ptr,"<="); break;
+    default:
+      error ("Invalid binary operation specified.");
+    }
+  argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure");
+  if (argvec[0])
+    {
+      if (static_memfuncp)
+       {
+         argvec[1] = argvec[0];
+         argvec++;
+       }
+      return target_call_function (argvec[0], 2 - static_memfuncp, argvec + 1);
+    }
+  error ("member function %s not found", tstr);
+#ifdef lint
+  return target_call_function (argvec[0], 2 - static_memfuncp, argvec + 1);
+#endif
+}
+
+/* We know that arg1 is a structure, so try to find a unary user
+   defined operator that matches the operator in question.  
+   Create an argument vector that calls arg1.operator @ (arg1)
+   and return that value (where '@' is (almost) any unary operator which
+   is legal for GNU C++).  */
+
+value
+value_x_unop (arg1, op)
+     value arg1;
+     enum exp_opcode op;
+{
+  value * argvec;
+  char *ptr;
+  char tstr[13];
+  int static_memfuncp;
+
+  COERCE_ENUM (arg1);
+
+  /* now we know that what we have to do is construct our
+     arg vector and find the right function to call it with.  */
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
+    error ("Can't do that unary op on that type");  /* FIXME be explicit */
+
+  argvec = (value *) alloca (sizeof (value) * 3);
+  argvec[1] = value_addr (arg1);
+  argvec[2] = 0;
+
+  /* make the right function name up */  
+  strcpy(tstr,"operator__");
+  ptr = tstr+8;
+  switch (op)
+    {
+    case UNOP_PREINCREMENT:    strcpy(ptr,"++"); break;
+    case UNOP_PREDECREMENT:    strcpy(ptr,"++"); break;
+    case UNOP_POSTINCREMENT:   strcpy(ptr,"++"); break;
+    case UNOP_POSTDECREMENT:   strcpy(ptr,"++"); break;
+    case UNOP_ZEROP:   strcpy(ptr,"!"); break;
+    case UNOP_LOGNOT:  strcpy(ptr,"~"); break;
+    case UNOP_NEG:     strcpy(ptr,"-"); break;
+    default:
+      error ("Invalid binary operation specified.");
+    }
+  argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure");
+  if (argvec[0])
+    {
+      if (static_memfuncp)
+       {
+         argvec[1] = argvec[0];
+         argvec++;
+       }
+      return target_call_function (argvec[0], 1 - static_memfuncp, argvec + 1);
+    }
+  error ("member function %s not found", tstr);
+  return 0;  /* For lint -- never reached */
+}
+\f
+/* Perform a binary operation on two integers or two floats.
+   Does not support addition and subtraction on pointers;
+   use value_add or value_sub if you want to handle those possibilities.  */
+
+value
+value_binop (arg1, arg2, op)
+     value arg1, arg2;
+     int op;
+{
+  register value val;
+
+  COERCE_ENUM (arg1);
+  COERCE_ENUM (arg2);
+
+  if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT
+       &&
+       TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
+      ||
+      (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT
+       &&
+       TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT))
+    error ("Argument to arithmetic operation not a number.");
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT
+      ||
+      TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT)
+    {
+      double v1, v2, v;
+      v1 = value_as_double (arg1);
+      v2 = value_as_double (arg2);
+      switch (op)
+       {
+       case BINOP_ADD:
+         v = v1 + v2;
+         break;
+
+       case BINOP_SUB:
+         v = v1 - v2;
+         break;
+
+       case BINOP_MUL:
+         v = v1 * v2;
+         break;
+
+       case BINOP_DIV:
+         v = v1 / v2;
+         break;
+
+       default:
+         error ("Integer-only operation on floating point number.");
+       }
+
+      val = allocate_value (builtin_type_double);
+      SWAP_TARGET_AND_HOST (&v, sizeof (v));
+      *(double *) VALUE_CONTENTS_RAW (val) = v;
+    }
+  else
+    /* Integral operations here.  */
+    {
+      /* Should we promote to unsigned longest?  */
+      if ((TYPE_UNSIGNED (VALUE_TYPE (arg1))
+          || TYPE_UNSIGNED (VALUE_TYPE (arg2)))
+         && (TYPE_LENGTH (VALUE_TYPE (arg1)) >= sizeof (unsigned LONGEST)
+             || TYPE_LENGTH (VALUE_TYPE (arg1)) >= sizeof (unsigned LONGEST)))
+       {
+         unsigned LONGEST v1, v2, v;
+         v1 = (unsigned LONGEST) value_as_long (arg1);
+         v2 = (unsigned LONGEST) value_as_long (arg2);
+         
+         switch (op)
+           {
+           case BINOP_ADD:
+             v = v1 + v2;
+             break;
+             
+           case BINOP_SUB:
+             v = v1 - v2;
+             break;
+             
+           case BINOP_MUL:
+             v = v1 * v2;
+             break;
+             
+           case BINOP_DIV:
+             v = v1 / v2;
+             break;
+             
+           case BINOP_REM:
+             v = v1 % v2;
+             break;
+             
+           case BINOP_LSH:
+             v = v1 << v2;
+             break;
+             
+           case BINOP_RSH:
+             v = v1 >> v2;
+             break;
+             
+           case BINOP_LOGAND:
+             v = v1 & v2;
+             break;
+             
+           case BINOP_LOGIOR:
+             v = v1 | v2;
+             break;
+             
+           case BINOP_LOGXOR:
+             v = v1 ^ v2;
+             break;
+             
+           case BINOP_AND:
+             v = v1 && v2;
+             break;
+             
+           case BINOP_OR:
+             v = v1 || v2;
+             break;
+             
+           case BINOP_MIN:
+             v = v1 < v2 ? v1 : v2;
+             break;
+             
+           case BINOP_MAX:
+             v = v1 > v2 ? v1 : v2;
+             break;
+             
+           default:
+             error ("Invalid binary operation on numbers.");
+           }
+
+         val = allocate_value (BUILTIN_TYPE_UNSIGNED_LONGEST);
+         SWAP_TARGET_AND_HOST (&v, sizeof (v));
+         *(unsigned LONGEST *) VALUE_CONTENTS_RAW (val) = v;
+       }
+      else
+       {
+         LONGEST v1, v2, v;
+         v1 = value_as_long (arg1);
+         v2 = value_as_long (arg2);
+         
+         switch (op)
+           {
+           case BINOP_ADD:
+             v = v1 + v2;
+             break;
+             
+           case BINOP_SUB:
+             v = v1 - v2;
+             break;
+             
+           case BINOP_MUL:
+             v = v1 * v2;
+             break;
+             
+           case BINOP_DIV:
+             v = v1 / v2;
+             break;
+             
+           case BINOP_REM:
+             v = v1 % v2;
+             break;
+             
+           case BINOP_LSH:
+             v = v1 << v2;
+             break;
+             
+           case BINOP_RSH:
+             v = v1 >> v2;
+             break;
+             
+           case BINOP_LOGAND:
+             v = v1 & v2;
+             break;
+             
+           case BINOP_LOGIOR:
+             v = v1 | v2;
+             break;
+             
+           case BINOP_LOGXOR:
+             v = v1 ^ v2;
+             break;
+             
+           case BINOP_AND:
+             v = v1 && v2;
+             break;
+             
+           case BINOP_OR:
+             v = v1 || v2;
+             break;
+             
+           case BINOP_MIN:
+             v = v1 < v2 ? v1 : v2;
+             break;
+             
+           case BINOP_MAX:
+             v = v1 > v2 ? v1 : v2;
+             break;
+             
+           default:
+             error ("Invalid binary operation on numbers.");
+           }
+         
+         val = allocate_value (BUILTIN_TYPE_LONGEST);
+         SWAP_TARGET_AND_HOST (&v, sizeof (v));
+         *(LONGEST *) VALUE_CONTENTS_RAW (val) = v;
+       }
+    }
+
+  return val;
+}
+\f
+/* Simulate the C operator ! -- return 1 if ARG1 contains zeros.  */
+
+int
+value_zerop (arg1)
+     value arg1;
+{
+  register int len;
+  register char *p;
+
+  COERCE_ARRAY (arg1);
+
+  len = TYPE_LENGTH (VALUE_TYPE (arg1));
+  p = VALUE_CONTENTS (arg1);
+
+  while (--len >= 0)
+    {
+      if (*p++)
+       break;
+    }
+
+  return len < 0;
+}
+
+/* Simulate the C operator == by returning a 1
+   iff ARG1 and ARG2 have equal contents.  */
+
+int
+value_equal (arg1, arg2)
+     register value arg1, arg2;
+
+{
+  register int len;
+  register char *p1, *p2;
+  enum type_code code1;
+  enum type_code code2;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  code1 = TYPE_CODE (VALUE_TYPE (arg1));
+  code2 = TYPE_CODE (VALUE_TYPE (arg2));
+
+  if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+    return value_as_long (arg1) == value_as_long (arg2);
+  else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+          && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+    return value_as_double (arg1) == value_as_double (arg2);
+  else if ((code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
+          || (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT))
+    return (char *) value_as_long (arg1) == (char *) value_as_long (arg2);
+  else if (code1 == code2
+          && ((len = TYPE_LENGTH (VALUE_TYPE (arg1)))
+              == TYPE_LENGTH (VALUE_TYPE (arg2))))
+    {
+      p1 = VALUE_CONTENTS (arg1);
+      p2 = VALUE_CONTENTS (arg2);
+      while (--len >= 0)
+       {
+         if (*p1++ != *p2++)
+           break;
+       }
+      return len < 0;
+    }
+  else
+    {
+      error ("Invalid type combination in equality test.");
+      return 0;  /* For lint -- never reached */
+    }
+}
+
+/* Simulate the C operator < by returning 1
+   iff ARG1's contents are less than ARG2's.  */
+
+int
+value_less (arg1, arg2)
+     register value arg1, arg2;
+{
+  register enum type_code code1;
+  register enum type_code code2;
+
+  COERCE_ARRAY (arg1);
+  COERCE_ARRAY (arg2);
+
+  code1 = TYPE_CODE (VALUE_TYPE (arg1));
+  code2 = TYPE_CODE (VALUE_TYPE (arg2));
+
+  if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+    {
+      if (TYPE_UNSIGNED (VALUE_TYPE (arg1))
+       || TYPE_UNSIGNED (VALUE_TYPE (arg2)))
+       return (unsigned)value_as_long (arg1) < (unsigned)value_as_long (arg2);
+      else
+       return value_as_long (arg1) < value_as_long (arg2);
+    }
+  else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+          && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+    return value_as_double (arg1) < value_as_double (arg2);
+  else if ((code1 == TYPE_CODE_PTR || code1 == TYPE_CODE_INT)
+          && (code2 == TYPE_CODE_PTR || code2 == TYPE_CODE_INT))
+    {
+      /* FIXME, this assumes that host and target char *'s are the same! */
+      return (char *) value_as_long (arg1) < (char *) value_as_long (arg2);
+    }
+  else
+    {
+      error ("Invalid type combination in ordering comparison.");
+      return 0;
+    }
+}
+\f
+/* The unary operators - and ~.  Both free the argument ARG1.  */
+
+value
+value_neg (arg1)
+     register value arg1;
+{
+  register struct type *type;
+
+  COERCE_ENUM (arg1);
+
+  type = VALUE_TYPE (arg1);
+
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return value_from_double (type, - value_as_double (arg1));
+  else if (TYPE_CODE (type) == TYPE_CODE_INT)
+    return value_from_long (type, - value_as_long (arg1));
+  else {
+    error ("Argument to negate operation not a number.");
+    return 0;  /* For lint -- never reached */
+  }
+}
+
+value
+value_lognot (arg1)
+     register value arg1;
+{
+  COERCE_ENUM (arg1);
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
+    error ("Argument to complement operation not an integer.");
+
+  return value_from_long (VALUE_TYPE (arg1), ~ value_as_long (arg1));
+}
+\f
diff --git a/gdb/valops.c b/gdb/valops.c
new file mode 100644 (file)
index 0000000..8031471
--- /dev/null
@@ -0,0 +1,1478 @@
+/* Perform non-arithmetic operations on values, for GDB.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+
+#include <errno.h>
+
+/* Local functions.  */
+static value search_struct_field ();
+\f
+/* Cast value ARG2 to type TYPE and return as a value.
+   More general than a C cast: accepts any two types of the same length,
+   and if ARG2 is an lvalue it can be cast into anything at all.  */
+/* In C++, casts may change pointer representations.  */
+
+value
+value_cast (type, arg2)
+     struct type *type;
+     register value arg2;
+{
+  register enum type_code code1;
+  register enum type_code code2;
+  register int scalar;
+
+  /* Coerce arrays but not enums.  Enums will work as-is
+     and coercing them would cause an infinite recursion.  */
+  if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_ENUM)
+    COERCE_ARRAY (arg2);
+
+  code1 = TYPE_CODE (type);
+  code2 = TYPE_CODE (VALUE_TYPE (arg2));
+  scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
+           || code2 == TYPE_CODE_ENUM);
+
+  if (code1 == TYPE_CODE_FLT && scalar)
+    return value_from_double (type, value_as_double (arg2));
+  else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM)
+          && (scalar || code2 == TYPE_CODE_PTR))
+    return value_from_long (type, value_as_long (arg2));
+  else if (TYPE_LENGTH (type) == TYPE_LENGTH (VALUE_TYPE (arg2)))
+    {
+      if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
+       {
+         /* Look in the type of the source to see if it contains the
+            type of the target as a superclass.  If so, we'll need to
+            offset the pointer rather than just change its type.  */
+         struct type *t1 = TYPE_TARGET_TYPE (type);
+         struct type *t2 = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
+         if (TYPE_CODE (t1) == TYPE_CODE_STRUCT
+             && TYPE_CODE (t2) == TYPE_CODE_STRUCT
+             && TYPE_NAME (t1) != 0) /* if name unknown, can't have supercl */
+           {
+             value v = search_struct_field (type_name_no_tag (t1),
+                                            value_ind (arg2), 0, t2);
+             if (v)
+               {
+                 v = value_addr (v);
+                 VALUE_TYPE (v) = type;
+                 return v;
+               }
+           }
+         /* No superclass found, just fall through to change ptr type.  */
+       }
+      VALUE_TYPE (arg2) = type;
+      return arg2;
+    }
+  else if (VALUE_LVAL (arg2) == lval_memory)
+    {
+      return value_at_lazy (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
+    }
+  else
+    {
+      error ("Invalid cast.");
+      return 0;
+    }
+}
+
+/* Create a value of type TYPE that is zero, and return it.  */
+
+value
+value_zero (type, lv)
+     struct type *type;
+     enum lval_type lv;
+{
+  register value val = allocate_value (type);
+
+  bzero (VALUE_CONTENTS (val), TYPE_LENGTH (type));
+  VALUE_LVAL (val) = lv;
+
+  return val;
+}
+
+/* Return a value with type TYPE located at ADDR.  
+
+   Call value_at only if the data needs to be fetched immediately;
+   if we can be 'lazy' and defer the fetch, perhaps indefinately, call
+   value_at_lazy instead.  value_at_lazy simply records the address of
+   the data and sets the lazy-evaluation-required flag.  The lazy flag 
+   is tested in the VALUE_CONTENTS macro, which is used if and when 
+   the contents are actually required.  */
+
+value
+value_at (type, addr)
+     struct type *type;
+     CORE_ADDR addr;
+{
+  register value val = allocate_value (type);
+
+  read_memory (addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (type));
+
+  VALUE_LVAL (val) = lval_memory;
+  VALUE_ADDRESS (val) = addr;
+
+  return val;
+}
+
+/* Return a lazy value with type TYPE located at ADDR (cf. value_at).  */
+
+value
+value_at_lazy (type, addr)
+     struct type *type;
+     CORE_ADDR addr;
+{
+  register value val = allocate_value (type);
+
+  VALUE_LVAL (val) = lval_memory;
+  VALUE_ADDRESS (val) = addr;
+  VALUE_LAZY (val) = 1;
+
+  return val;
+}
+
+/* Called only from the VALUE_CONTENTS macro, if the current data for
+   a variable needs to be loaded into VALUE_CONTENTS(VAL).  Fetches the
+   data from the user's process, and clears the lazy flag to indicate
+   that the data in the buffer is valid.
+
+   This function returns a value because it is used in the VALUE_CONTENTS
+   macro as part of an expression, where a void would not work.  The
+   value is ignored.  */
+
+int
+value_fetch_lazy (val)
+     register value val;
+{
+  CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val);
+
+  read_memory (addr, VALUE_CONTENTS_RAW (val), 
+              TYPE_LENGTH (VALUE_TYPE (val)));
+  VALUE_LAZY (val) = 0;
+  return 0;
+}
+
+
+/* Store the contents of FROMVAL into the location of TOVAL.
+   Return a new value with the location of TOVAL and contents of FROMVAL.  */
+
+value
+value_assign (toval, fromval)
+     register value toval, fromval;
+{
+  register struct type *type = VALUE_TYPE (toval);
+  register value val;
+  char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+  int use_buffer = 0;
+
+  COERCE_ARRAY (fromval);
+
+  if (VALUE_LVAL (toval) != lval_internalvar)
+    fromval = value_cast (type, fromval);
+
+  /* If TOVAL is a special machine register requiring conversion
+     of program values to a special raw format,
+     convert FROMVAL's contents now, with result in `raw_buffer',
+     and set USE_BUFFER to the number of bytes to write.  */
+
+  if (VALUE_REGNO (toval) >= 0
+      && REGISTER_CONVERTIBLE (VALUE_REGNO (toval)))
+    {
+      int regno = VALUE_REGNO (toval);
+      if (VALUE_TYPE (fromval) != REGISTER_VIRTUAL_TYPE (regno))
+       fromval = value_cast (REGISTER_VIRTUAL_TYPE (regno), fromval);
+      bcopy (VALUE_CONTENTS (fromval), virtual_buffer,
+            REGISTER_VIRTUAL_SIZE (regno));
+      target_convert_from_virtual (regno, virtual_buffer, raw_buffer);
+      use_buffer = REGISTER_RAW_SIZE (regno);
+    }
+
+  switch (VALUE_LVAL (toval))
+    {
+    case lval_internalvar:
+      set_internalvar (VALUE_INTERNALVAR (toval), fromval);
+      break;
+
+    case lval_internalvar_component:
+      set_internalvar_component (VALUE_INTERNALVAR (toval),
+                                VALUE_OFFSET (toval),
+                                VALUE_BITPOS (toval),
+                                VALUE_BITSIZE (toval),
+                                fromval);
+      break;
+
+    case lval_memory:
+      if (VALUE_BITSIZE (toval))
+       {
+         int v;                /* FIXME, this won't work for large bitfields */
+         read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                      &v, sizeof v);
+         modify_field (&v, (int) value_as_long (fromval),
+                       VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+         write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                       (char *)&v, sizeof v);
+       }
+      else if (use_buffer)
+       write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                     raw_buffer, use_buffer);
+      else
+       write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                     VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+      break;
+
+    case lval_register:
+      if (VALUE_BITSIZE (toval))
+       {
+         int v;
+
+         read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                              &v, sizeof v);
+         modify_field (&v, (int) value_as_long (fromval),
+                       VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+         write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                               &v, sizeof v);
+       }
+      else if (use_buffer)
+       write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                             raw_buffer, use_buffer);
+      else
+       write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+                             VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+      break;
+
+    case lval_reg_frame_relative:
+      {
+       /* value is stored in a series of registers in the frame
+          specified by the structure.  Copy that value out, modify
+          it, and copy it back in.  */
+       int amount_to_copy = (VALUE_BITSIZE (toval) ? 1 : TYPE_LENGTH (type));
+       int reg_size = REGISTER_RAW_SIZE (VALUE_FRAME_REGNUM (toval));
+       int byte_offset = VALUE_OFFSET (toval) % reg_size;
+       int reg_offset = VALUE_OFFSET (toval) / reg_size;
+       int amount_copied;
+       char *buffer = (char *) alloca (amount_to_copy);
+       int regno;
+       FRAME frame;
+
+       /* Figure out which frame this is in currently.  */
+       for (frame = get_current_frame ();
+            frame && FRAME_FP (frame) != VALUE_FRAME (toval);
+            frame = get_prev_frame (frame))
+         ;
+
+       if (!frame)
+         error ("Value being assigned to is no longer active.");
+
+       amount_to_copy += (reg_size - amount_to_copy % reg_size);
+
+       /* Copy it out.  */
+       for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
+             amount_copied = 0);
+            amount_copied < amount_to_copy;
+            amount_copied += reg_size, regno++)
+         {
+           get_saved_register (buffer + amount_copied,
+                               (int *)NULL, (CORE_ADDR)NULL,
+                               frame, regno, (enum lval_type *)NULL);
+         }
+
+       /* Modify what needs to be modified.  */
+       if (VALUE_BITSIZE (toval))
+         modify_field (buffer + byte_offset,
+                       (int) value_as_long (fromval),
+                       VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+       else if (use_buffer)
+         bcopy (raw_buffer, buffer + byte_offset, use_buffer);
+       else
+         bcopy (VALUE_CONTENTS (fromval), buffer + byte_offset,
+                TYPE_LENGTH (type));
+
+       /* Copy it back.  */
+       for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
+             amount_copied = 0);
+            amount_copied < amount_to_copy;
+            amount_copied += reg_size, regno++)
+         {
+           enum lval_type lval;
+           CORE_ADDR addr;
+           int optim;
+
+           /* Just find out where to put it.  */
+           get_saved_register ((char *)NULL,
+                               &optim, &addr, frame, regno, &lval);
+           
+           if (optim)
+             error ("Attempt to assign to a value that was optimized out.");
+           if (lval == lval_memory)
+             write_memory (addr, buffer + amount_copied, reg_size);
+           else if (lval == lval_register)
+             write_register_bytes (addr, buffer + amount_copied, reg_size);
+           else
+             error ("Attempt to assign to an unmodifiable value.");
+         }
+      }
+      break;
+       
+
+    default:
+      error ("Left side of = operation is not an lvalue.");
+    }
+
+  /* Return a value just like TOVAL except with the contents of FROMVAL
+     (except in the case of the type if TOVAL is an internalvar).  */
+
+  if (VALUE_LVAL (toval) == lval_internalvar
+      || VALUE_LVAL (toval) == lval_internalvar_component)
+    {
+      type = VALUE_TYPE (fromval);
+    }
+
+  val = allocate_value (type);
+  bcopy (toval, val, VALUE_CONTENTS_RAW (val) - (char *) val);
+  bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS_RAW (val), TYPE_LENGTH (type));
+  VALUE_TYPE (val) = type;
+  
+  return val;
+}
+
+/* Extend a value VAL to COUNT repetitions of its type.  */
+
+value
+value_repeat (arg1, count)
+     value arg1;
+     int count;
+{
+  register value val;
+
+  if (VALUE_LVAL (arg1) != lval_memory)
+    error ("Only values in memory can be extended with '@'.");
+  if (count < 1)
+    error ("Invalid number %d of repetitions.", count);
+
+  val = allocate_repeat_value (VALUE_TYPE (arg1), count);
+
+  read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),
+              VALUE_CONTENTS_RAW (val),
+              TYPE_LENGTH (VALUE_TYPE (val)) * count);
+  VALUE_LVAL (val) = lval_memory;
+  VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);
+
+  return val;
+}
+
+value
+value_of_variable (var)
+     struct symbol *var;
+{
+  value val;
+
+  val = read_var_value (var, (FRAME) 0);
+  if (val == 0)
+    error ("Address of symbol \"%s\" is unknown.", SYMBOL_NAME (var));
+  return val;
+}
+
+/* Given a value which is an array, return a value which is
+   a pointer to its first element.  */
+
+value
+value_coerce_array (arg1)
+     value arg1;
+{
+  register struct type *type;
+  register value val;
+
+  if (VALUE_LVAL (arg1) != lval_memory)
+    error ("Attempt to take address of value not located in memory.");
+
+  /* Get type of elements.  */
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY)
+    type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1));
+  else
+    /* A phony array made by value_repeat.
+       Its type is the type of the elements, not an array type.  */
+    type = VALUE_TYPE (arg1);
+
+  /* Get the type of the result.  */
+  type = lookup_pointer_type (type);
+  val = value_from_long (builtin_type_long,
+                      (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+  VALUE_TYPE (val) = type;
+  return val;
+}
+
+/* Given a value which is a function, return a value which is a pointer
+   to it.  */
+
+value
+value_coerce_function (arg1)
+     value arg1;
+{
+  register struct type *type;
+  register value val;
+
+  if (VALUE_LVAL (arg1) != lval_memory)
+    error ("Attempt to take address of value not located in memory.");
+
+  /* Get the type of the result.  */
+  type = lookup_pointer_type (VALUE_TYPE (arg1));
+  val = value_from_long (builtin_type_long,
+               (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+  VALUE_TYPE (val) = type;
+  return val;
+}  
+
+/* Return a pointer value for the object for which ARG1 is the contents.  */
+
+value
+value_addr (arg1)
+     value arg1;
+{
+  register struct type *type;
+  register value val;
+
+  COERCE_REF(arg1);
+  /* Taking the address of an array is really a no-op
+     once the array is coerced to a pointer to its first element.  */
+  if (VALUE_REPEATED (arg1)
+      || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY)
+    return value_coerce_array (arg1);
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FUNC)
+    return value_coerce_function (arg1);
+
+  if (VALUE_LVAL (arg1) != lval_memory)
+    error ("Attempt to take address of value not located in memory.");
+
+  /* Get the type of the result.  */
+  type = lookup_pointer_type (VALUE_TYPE (arg1));
+  val = value_from_long (builtin_type_long,
+               (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+  VALUE_TYPE (val) = type;
+  return val;
+}
+
+/* Given a value of a pointer type, apply the C unary * operator to it.  */
+
+value
+value_ind (arg1)
+     value arg1;
+{
+  COERCE_ARRAY (arg1);
+
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_MEMBER)
+    error ("not implemented: member types in value_ind");
+
+  /* Allow * on an integer so we can cast it to whatever we want.
+     This returns an int, which seems like the most C-like thing
+     to do.  "long long" variables are rare enough that
+     BUILTIN_TYPE_LONGEST would seem to be a mistake.  */
+  if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
+    return value_at (builtin_type_int,
+                    (CORE_ADDR) value_as_long (arg1));
+  else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
+    return value_at_lazy (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+                    (CORE_ADDR) value_as_long (arg1));
+  error ("Attempt to take contents of a non-pointer value.");
+  return 0;  /* For lint -- never reached */
+}
+\f
+/* Pushing small parts of stack frames.  */
+
+/* Push one word (the size of object that a register holds).  */
+
+CORE_ADDR
+push_word (sp, buffer)
+     CORE_ADDR sp;
+     REGISTER_TYPE buffer;
+{
+  register int len = sizeof (REGISTER_TYPE);
+
+#if 1 INNER_THAN 2
+  sp -= len;
+  write_memory (sp, (char *)&buffer, len);
+#else /* stack grows upward */
+  write_memory (sp, (char *)&buffer, len);
+  sp += len;
+#endif /* stack grows upward */
+
+  return sp;
+}
+
+/* Push LEN bytes with data at BUFFER.  */
+
+CORE_ADDR
+push_bytes (sp, buffer, len)
+     CORE_ADDR sp;
+     char *buffer;
+     int len;
+{
+#if 1 INNER_THAN 2
+  sp -= len;
+  write_memory (sp, buffer, len);
+#else /* stack grows upward */
+  write_memory (sp, buffer, len);
+  sp += len;
+#endif /* stack grows upward */
+
+  return sp;
+}
+
+/* Push onto the stack the specified value VALUE.  */
+
+CORE_ADDR
+value_push (sp, arg)
+     register CORE_ADDR sp;
+     value arg;
+{
+  register int len = TYPE_LENGTH (VALUE_TYPE (arg));
+
+#if 1 INNER_THAN 2
+  sp -= len;
+  write_memory (sp, VALUE_CONTENTS (arg), len);
+#else /* stack grows upward */
+  write_memory (sp, VALUE_CONTENTS (arg), len);
+  sp += len;
+#endif /* stack grows upward */
+
+  return sp;
+}
+
+/* Perform the standard coercions that are specified
+   for arguments to be passed to C functions.  */
+
+value
+value_arg_coerce (arg)
+     value arg;
+{
+  register struct type *type;
+
+  COERCE_ENUM (arg);
+
+  type = VALUE_TYPE (arg);
+
+  if (TYPE_CODE (type) == TYPE_CODE_INT
+      && TYPE_LENGTH (type) < sizeof (int))
+    return value_cast (builtin_type_int, arg);
+
+  if (type == builtin_type_float)
+    return value_cast (builtin_type_double, arg);
+
+  return arg;
+}
+
+/* Push the value ARG, first coercing it as an argument
+   to a C function.  */
+
+CORE_ADDR
+value_arg_push (sp, arg)
+     register CORE_ADDR sp;
+     value arg;
+{
+  return value_push (sp, value_arg_coerce (arg));
+}
+
+/* Determine a function's address and its return type from its value. 
+   Calls error() if the function is not valid for calling.  */
+
+CORE_ADDR
+find_function_addr (function, retval_type)
+     value function;
+     struct type **retval_type;
+{
+  register struct type *ftype = VALUE_TYPE (function);
+  register enum type_code code = TYPE_CODE (ftype);
+  struct type *value_type;
+  CORE_ADDR funaddr;
+
+  /* If it's a member function, just look at the function
+     part of it.  */
+
+  /* Determine address to call.  */
+  if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
+    {
+      funaddr = VALUE_ADDRESS (function);
+      value_type = TYPE_TARGET_TYPE (ftype);
+    }
+  else if (code == TYPE_CODE_PTR)
+    {
+      funaddr = value_as_long (function);
+      if (TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_FUNC
+         || TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_METHOD)
+       value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype));
+      else
+       value_type = builtin_type_int;
+    }
+  else if (code == TYPE_CODE_INT)
+    {
+      /* Handle the case of functions lacking debugging info.
+        Their values are characters since their addresses are char */
+      if (TYPE_LENGTH (ftype) == 1)
+       funaddr = value_as_long (value_addr (function));
+      else
+       /* Handle integer used as address of a function.  */
+       funaddr = value_as_long (function);
+
+      value_type = builtin_type_int;
+    }
+  else
+    error ("Invalid data type for function to be called.");
+
+  *retval_type = value_type;
+  return funaddr;
+}
+
+#if defined (CALL_DUMMY)
+/* All this stuff with a dummy frame may seem unnecessarily complicated
+   (why not just save registers in GDB?).  The purpose of pushing a dummy
+   frame which looks just like a real frame is so that if you call a
+   function and then hit a breakpoint (get a signal, etc), "backtrace"
+   will look right.  Whether the backtrace needs to actually show the
+   stack at the time the inferior function was called is debatable, but
+   it certainly needs to not display garbage.  So if you are contemplating
+   making dummy frames be different from normal frames, consider that.  */
+
+/* Perform a function call in the inferior.
+   ARGS is a vector of values of arguments (NARGS of them).
+   FUNCTION is a value, the function to be called.
+   Returns a value representing what the function returned.
+   May fail to return, if a breakpoint or signal is hit
+   during the execution of the function.  */
+
+value
+call_function_by_hand (function, nargs, args)
+     value function;
+     int nargs;
+     value *args;
+{
+  register CORE_ADDR sp;
+  register int i;
+  CORE_ADDR start_sp;
+  static REGISTER_TYPE dummy[] = CALL_DUMMY;
+  REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
+  CORE_ADDR old_sp;
+  struct type *value_type;
+  unsigned char struct_return;
+  CORE_ADDR struct_addr;
+  struct inferior_status inf_status;
+  struct cleanup *old_chain;
+  CORE_ADDR funaddr;
+  int using_gcc;
+
+  save_inferior_status (&inf_status, 1);
+  old_chain = make_cleanup (restore_inferior_status, &inf_status);
+
+  /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
+     (and POP_FRAME for restoring them).  (At least on most machines)
+     they are saved on the stack in the inferior.  */
+  PUSH_DUMMY_FRAME;
+
+  old_sp = sp = read_register (SP_REGNUM);
+
+#if 1 INNER_THAN 2             /* Stack grows down */
+  sp -= sizeof dummy;
+  start_sp = sp;
+#else                          /* Stack grows up */
+  start_sp = sp;
+  sp += sizeof dummy;
+#endif
+
+  funaddr = find_function_addr (function, &value_type);
+
+  {
+    struct block *b = block_for_pc (funaddr);
+    /* If compiled without -g, assume GCC.  */
+    using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
+  }
+
+  /* Are we returning a value using a structure return or a normal
+     value return? */
+
+  struct_return = using_struct_return (function, funaddr, value_type,
+                                      using_gcc);
+
+  /* Create a call sequence customized for this function
+     and the number of arguments for it.  */
+  bcopy (dummy, dummy1, sizeof dummy);
+  FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+                 value_type, using_gcc);
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+  write_memory (start_sp, (char *)dummy1, sizeof dummy);
+
+#else /* Not on stack.  */
+#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
+  /* Convex Unix prohibits executing in the stack segment. */
+  /* Hope there is empty room at the top of the text segment. */
+  {
+    static checked = 0;
+    if (!checked)
+      for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
+       if (read_memory_integer (start_sp, 1) != 0)
+         error ("text segment full -- no place to put call");
+    checked = 1;
+    sp = old_sp;
+    start_sp = text_end - sizeof dummy;
+    write_memory (start_sp, (char *)dummy1, sizeof dummy);
+  }
+#else /* After text_end.  */
+  {
+    int errcode;
+    sp = old_sp;
+    start_sp = text_end;
+    errcode = target_write_memory (start_sp, (char *)dummy1, sizeof dummy);
+    if (errcode != 0)
+      error ("Cannot write text segment -- call_function failed");
+  }
+#endif /* After text_end.  */
+#endif /* Not on stack.  */
+
+#ifdef lint
+  sp = old_sp;         /* It really is used, for some ifdef's... */
+#endif
+
+#ifdef STACK_ALIGN
+  /* If stack grows down, we must leave a hole at the top. */
+  {
+    int len = 0;
+
+    /* Reserve space for the return structure to be written on the
+       stack, if necessary */
+
+    if (struct_return)
+      len += TYPE_LENGTH (value_type);
+    
+    for (i = nargs - 1; i >= 0; i--)
+      len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
+#ifdef CALL_DUMMY_STACK_ADJUST
+    len += CALL_DUMMY_STACK_ADJUST;
+#endif
+#if 1 INNER_THAN 2
+    sp -= STACK_ALIGN (len) - len;
+#else
+    sp += STACK_ALIGN (len) - len;
+#endif
+  }
+#endif /* STACK_ALIGN */
+
+    /* Reserve space for the return structure to be written on the
+       stack, if necessary */
+
+    if (struct_return)
+      {
+#if 1 INNER_THAN 2
+       sp -= TYPE_LENGTH (value_type);
+       struct_addr = sp;
+#else
+       struct_addr = sp;
+       sp += TYPE_LENGTH (value_type);
+#endif
+      }
+
+#if defined (REG_STRUCT_HAS_ADDR)
+  {
+    /* This is a machine like the sparc, where we need to pass a pointer
+       to the structure, not the structure itself.  */
+    if (REG_STRUCT_HAS_ADDR (using_gcc))
+      for (i = nargs - 1; i >= 0; i--)
+       if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
+         {
+           CORE_ADDR addr;
+#if !(1 INNER_THAN 2)
+           /* The stack grows up, so the address of the thing we push
+              is the stack pointer before we push it.  */
+           addr = sp;
+#endif
+           /* Push the structure.  */
+           sp = value_push (sp, args[i]);
+#if 1 INNER_THAN 2
+           /* The stack grows down, so the address of the thing we push
+              is the stack pointer after we push it.  */
+           addr = sp;
+#endif
+           /* The value we're going to pass is the address of the thing
+              we just pushed.  */
+           args[i] = value_from_long (builtin_type_long, (LONGEST) addr);
+         }
+  }
+#endif /* REG_STRUCT_HAS_ADDR.  */
+
+#ifdef PUSH_ARGUMENTS
+  PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
+#else /* !PUSH_ARGUMENTS */
+  for (i = nargs - 1; i >= 0; i--)
+    sp = value_arg_push (sp, args[i]);
+#endif /* !PUSH_ARGUMENTS */
+
+#ifdef CALL_DUMMY_STACK_ADJUST
+#if 1 INNER_THAN 2
+  sp -= CALL_DUMMY_STACK_ADJUST;
+#else
+  sp += CALL_DUMMY_STACK_ADJUST;
+#endif
+#endif /* CALL_DUMMY_STACK_ADJUST */
+
+  /* Store the address at which the structure is supposed to be
+     written.  Note that this (and the code which reserved the space
+     above) assumes that gcc was used to compile this function.  Since
+     it doesn't cost us anything but space and if the function is pcc
+     it will ignore this value, we will make that assumption.
+
+     Also note that on some machines (like the sparc) pcc uses a 
+     convention like gcc's.  */
+
+  if (struct_return)
+    STORE_STRUCT_RETURN (struct_addr, sp);
+
+  /* Write the stack pointer.  This is here because the statements above
+     might fool with it.  On SPARC, this write also stores the register
+     window into the right place in the new stack frame, which otherwise
+     wouldn't happen.  (See write_inferior_registers in sparc-xdep.c.)  */
+  write_register (SP_REGNUM, sp);
+
+  /* Figure out the value returned by the function.  */
+  {
+    char retbuf[REGISTER_BYTES];
+
+    /* Execute the stack dummy routine, calling FUNCTION.
+       When it is done, discard the empty frame
+       after storing the contents of all regs into retbuf.  */
+    run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
+
+    do_cleanups (old_chain);
+
+    return value_being_returned (value_type, retbuf, struct_return);
+  }
+}
+#else /* no CALL_DUMMY.  */
+value
+call_function_by_hand (function, nargs, args)
+     value function;
+     int nargs;
+     value *args;
+{
+  error ("Cannot invoke functions on this machine.");
+}
+#endif /* no CALL_DUMMY.  */
+\f
+/* Create a value for a string constant:
+   Call the function malloc in the inferior to get space for it,
+   then copy the data into that space
+   and then return the address with type char *.
+   PTR points to the string constant data; LEN is number of characters.  */
+
+value
+value_string (ptr, len)
+     char *ptr;
+     int len;
+{
+  register value val;
+  register struct symbol *sym;
+  value blocklen;
+  register char *copy = (char *) alloca (len + 1);
+  char *i = ptr;
+  register char *o = copy, *ibeg = ptr;
+  register int c;
+
+  /* Copy the string into COPY, processing escapes.
+     We could not conveniently process them in expread
+     because the string there wants to be a substring of the input.  */
+
+  while (i - ibeg < len)
+    {
+      c = *i++;
+      if (c == '\\')
+       {
+         c = parse_escape (&i);
+         if (c == -1)
+           continue;
+       }
+      *o++ = c;
+    }
+  *o = 0;
+
+  /* Get the length of the string after escapes are processed.  */
+
+  len = o - copy;
+
+  /* Find the address of malloc in the inferior.  */
+
+  sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE, 0, NULL);
+  if (sym != 0)
+    {
+      if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+       error ("\"malloc\" exists in this program but is not a function.");
+      val = value_of_variable (sym);
+    }
+  else
+    {
+      register int j;
+      for (j = 0; j < misc_function_count; j++)
+       if (!strcmp (misc_function_vector[j].name, "malloc"))
+         break;
+      if (j < misc_function_count)
+       val = value_from_long (builtin_type_long,
+                            (LONGEST) misc_function_vector[j].address);
+      else
+       error ("String constants require the program to have a function \"malloc\".");
+    }
+
+  blocklen = value_from_long (builtin_type_int, (LONGEST) (len + 1));
+  val = target_call_function (val, 1, &blocklen);
+  if (value_zerop (val))
+    error ("No memory available for string constant.");
+  write_memory ((CORE_ADDR) value_as_long (val), copy, len + 1);
+  VALUE_TYPE (val) = lookup_pointer_type (builtin_type_char);
+  return val;
+}
+\f
+/* Helper function used by value_struct_elt to recurse through baseclasses.
+   Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes,
+   and treat the result as having type TYPE.
+   If found, return value, else return NULL. */
+
+static value
+search_struct_field (name, arg1, offset, type)
+     char *name;
+     register value arg1;
+     int offset;
+     register struct type *type;
+{
+  int i;
+
+  check_stub_type (type);
+
+  for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+    {
+      char *t_field_name = TYPE_FIELD_NAME (type, i);
+      if (t_field_name && !strcmp (t_field_name, name))
+         return TYPE_FIELD_STATIC (type, i)
+             ? value_static_field (type, name, i)
+             : value_primitive_field (arg1, offset, i, type);
+    }
+
+  for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+    {
+      value v;
+      /* If we are looking for baseclasses, this is what we get when we
+        hit them.  */
+      int found_baseclass = !strcmp (name, TYPE_BASECLASS_NAME (type, i));
+
+      if (BASETYPE_VIA_VIRTUAL (type, i))
+       {
+         value v2;
+         baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset, &v2);
+         if (v2 == 0)
+           error ("virtual baseclass botch");
+         if (found_baseclass)
+           return v2;
+         v = search_struct_field (name, v2, 0, TYPE_BASECLASS (type, i));
+         if (v) return v;
+         else continue;
+       }
+      if (found_baseclass)
+       v = value_primitive_field (arg1, offset, i, type);
+      else
+       v = search_struct_field (name, arg1,
+                                offset + TYPE_BASECLASS_BITPOS (type, i) / 8,
+                                TYPE_BASECLASS (type, i));
+      if (v) return v;
+    }
+  return NULL;
+}
+
+/* Helper function used by value_struct_elt to recurse through baseclasses.
+   Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes,
+   and treat the result as having type TYPE.
+   If found, return value, else return NULL. */
+
+static value
+search_struct_method (name, arg1, args, offset, static_memfuncp, type)
+     char *name;
+     register value arg1, *args;
+     int offset, *static_memfuncp;
+     register struct type *type;
+{
+  int i;
+
+  check_stub_type (type);
+  for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
+    {
+      char *t_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
+      if (t_field_name && !strcmp (t_field_name, name))
+       {
+         int j;
+         struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+
+         for (j = TYPE_FN_FIELDLIST_LENGTH (type, i) - 1; j >= 0; --j)
+           {
+             if (TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) & TYPE_FLAG_STUB)
+               check_stub_method (type, i, j);
+             if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
+                           TYPE_FN_FIELD_ARGS (f, j), args))
+               {
+                 if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+                   return (value)value_virtual_fn_field (arg1, f, j);
+                 if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
+                   *static_memfuncp = 1;
+                 return (value)value_fn_field (arg1, i, j);
+               }
+           }
+       }
+    }
+
+  for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+    {
+      value v;
+
+      if (BASETYPE_VIA_VIRTUAL (type, i))
+       {
+         value v2;
+         baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset, &v2);
+         if (v2 == 0)
+           error ("virtual baseclass botch");
+         v = search_struct_method (name, v2, args, 0,
+                                   static_memfuncp, TYPE_BASECLASS (type, i));
+         if (v) return v;
+         else continue;
+       }
+
+      v = search_struct_method (name, arg1, args,
+                               TYPE_BASECLASS_BITPOS (type, i) / 8,
+                               static_memfuncp, TYPE_BASECLASS (type, i));
+      if (v) return v;
+    }
+  return NULL;
+}
+
+/* Given *ARGP, a value of type (pointer to a)* structure/union,
+   extract the component named NAME from the ultimate target structure/union
+   and return it as a value with its appropriate type.
+   ERR is used in the error message if *ARGP's type is wrong.
+
+   C++: ARGS is a list of argument types to aid in the selection of
+   an appropriate method. Also, handle derived types.
+
+   STATIC_MEMFUNCP, if non-NULL, points to a caller-supplied location
+   where the truthvalue of whether the function that was resolved was
+   a static member function or not is stored.
+
+   ERR is an error message to be printed in case the field is not found.  */
+
+value
+value_struct_elt (argp, args, name, static_memfuncp, err)
+     register value *argp, *args;
+     char *name;
+     int *static_memfuncp;
+     char *err;
+{
+  register struct type *t;
+  int found = 0;       /* FIXME, half the time this doesn't get set */
+  value arg1_as_ptr = *argp;   /* FIXME, set but not used! */
+  value v;
+
+  COERCE_ARRAY (*argp);
+
+  t = VALUE_TYPE (*argp);
+
+  /* Follow pointers until we get to a non-pointer.  */
+
+  while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+    {
+      arg1_as_ptr = *argp;
+      *argp = value_ind (*argp);
+      COERCE_ARRAY (*argp);
+      t = VALUE_TYPE (*argp);
+    }
+
+  if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+    error ("not implemented: member type in value_struct_elt");
+
+  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+      && TYPE_CODE (t) != TYPE_CODE_UNION)
+    error ("Attempt to extract a component of a value that is not a %s.", err);
+
+  /* Assume it's not, unless we see that it is.  */
+  if (static_memfuncp)
+    *static_memfuncp =0;
+
+  if (!args)
+    {
+      /* if there are no arguments ...do this...  */
+
+      /* Try as a variable first, because if we succeed, there
+        is less work to be done.  */
+      v = search_struct_field (name, *argp, 0, t);
+      if (v)
+       return v;
+
+      /* C++: If it was not found as a data field, then try to
+         return it as a pointer to a method.  */
+
+      if (destructor_name_p (name, t))
+       error ("Cannot get value of destructor");
+
+      v = search_struct_method (name, *argp, args, 0, static_memfuncp, t);
+
+      if (v == 0)
+       {
+         if (TYPE_NFN_FIELDS (t))
+           error ("There is no member or method named %s.", name);
+         else
+           error ("There is no member named %s.", name);
+       }
+      return v;
+    }
+
+  if (destructor_name_p (name, t))
+    {
+      if (!args[1])
+       {
+         /* destructors are a special case.  */
+         return (value)value_fn_field (*argp, 0,
+                                       TYPE_FN_FIELDLIST_LENGTH (t, 0));
+       }
+      else
+       {
+         error ("destructor should not have any argument");
+       }
+    }
+  else
+    v = search_struct_method (name, *argp, args, 0, static_memfuncp, t);
+
+  if (v == 0)
+    {
+      /* See if user tried to invoke data as function.  If so,
+        hand it back.  If it's not callable (i.e., a pointer to function),
+        gdb should give an error.  */
+      v = search_struct_field (name, *argp, 0, t);
+    }
+
+  if (!v)
+    error ("Structure has no component named %s.", name);
+  return v;
+}
+
+/* C++: return 1 is NAME is a legitimate name for the destructor
+   of type TYPE.  If TYPE does not have a destructor, or
+   if NAME is inappropriate for TYPE, an error is signaled.  */
+int
+destructor_name_p (name, type)
+     char *name;
+     struct type *type;
+{
+  /* destructors are a special case.  */
+
+  if (name[0] == '~')
+    {
+      char *dname = type_name_no_tag (type);
+
+      if (! TYPE_HAS_DESTRUCTOR (type))
+       error ("type `%s' does not have destructor defined", dname);
+      if (strcmp (dname, name+1))
+       error ("name of destructor must equal name of class");
+      else
+       return 1;
+    }
+  return 0;
+}
+
+/* Helper function for check_field: Given TYPE, a structure/union,
+   return 1 if the component named NAME from the ultimate
+   target structure/union is defined, otherwise, return 0. */
+
+static int
+check_field_in (type, name)
+     register struct type *type;
+     char *name;
+{
+  register int i;
+
+  for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+    {
+      char *t_field_name = TYPE_FIELD_NAME (type, i);
+      if (t_field_name && !strcmp (t_field_name, name))
+       return 1;
+    }
+
+  /* C++: If it was not found as a data field, then try to
+     return it as a pointer to a method.  */
+
+  /* Destructors are a special case.  */
+  if (destructor_name_p (name, type))
+    return 1;
+
+  for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+    {
+      if (!strcmp (TYPE_FN_FIELDLIST_NAME (type, i), name))
+       return 1;
+    }
+
+  for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+    if (check_field_in (TYPE_BASECLASS (type, i), name))
+      return 1;
+      
+  return 0;
+}
+
+
+/* C++: Given ARG1, a value of type (pointer to a)* structure/union,
+   return 1 if the component named NAME from the ultimate
+   target structure/union is defined, otherwise, return 0.  */
+
+int
+check_field (arg1, name)
+     register value arg1;
+     char *name;
+{
+  register struct type *t;
+
+  COERCE_ARRAY (arg1);
+
+  t = VALUE_TYPE (arg1);
+
+  /* Follow pointers until we get to a non-pointer.  */
+
+  while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+    t = TYPE_TARGET_TYPE (t);
+
+  if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+    error ("not implemented: member type in check_field");
+
+  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+      && TYPE_CODE (t) != TYPE_CODE_UNION)
+    error ("Internal error: `this' is not an aggregate");
+
+  return check_field_in (t, name);
+}
+
+/* C++: Given an aggregate type DOMAIN, and a member name NAME,
+   return the address of this member as a pointer to member
+   type.  If INTYPE is non-null, then it will be the type
+   of the member we are looking for.  This will help us resolve
+   pointers to member functions.  */
+
+value
+value_struct_elt_for_address (domain, intype, name)
+     struct type *domain, *intype;
+     char *name;
+{
+  register struct type *t = domain;
+  register int i;
+  value v;
+
+  struct type *baseclass;
+
+  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+      && TYPE_CODE (t) != TYPE_CODE_UNION)
+    error ("Internal error: non-aggregate type to value_struct_elt_for_address");
+
+  baseclass = t;
+
+  while (t)
+    {
+      for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
+       {
+         char *t_field_name = TYPE_FIELD_NAME (t, i);
+         if (t_field_name && !strcmp (t_field_name, name))
+           {
+             if (TYPE_FIELD_STATIC (t, i))
+               {
+                 char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (t, i);
+                 struct symbol *sym =
+                     lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+                 if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name);
+                 v = value_from_long(builtin_type_long,
+                                     (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+                 VALUE_TYPE(v) = lookup_pointer_type (TYPE_FIELD_TYPE (t, i));
+                 return v;
+               }
+             if (TYPE_FIELD_PACKED (t, i))
+               error ("pointers to bitfield members not allowed");
+
+             v = value_from_long (builtin_type_int,
+                                  (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
+             VALUE_TYPE (v)
+               = lookup_pointer_type (lookup_member_type (TYPE_FIELD_TYPE (t, i), baseclass));
+             return v;
+           }
+       }
+
+      if (TYPE_N_BASECLASSES (t) == 0)
+       break;
+
+      t = TYPE_BASECLASS (t, 0);
+    }
+
+  /* C++: If it was not found as a data field, then try to
+     return it as a pointer to a method.  */
+  t = baseclass;
+
+  /* Destructors are a special case.  */
+  if (destructor_name_p (name, t))
+    {
+      error ("pointers to destructors not implemented yet");
+    }
+
+  /* Perform all necessary dereferencing.  */
+  while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR)
+    intype = TYPE_TARGET_TYPE (intype);
+
+  while (t)
+    {
+      for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
+       {
+         if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
+           {
+             int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
+             struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
+
+             if (intype == 0 && j > 1)
+               error ("non-unique member `%s' requires type instantiation", name);
+             if (intype)
+               {
+                 while (j--)
+                   if (TYPE_FN_FIELD_TYPE (f, j) == intype)
+                     break;
+                 if (j < 0)
+                   error ("no member function matches that type instantiation");
+               }
+             else
+               j = 0;
+
+             if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+               {
+                 v = value_from_long (builtin_type_long,
+                                      (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+               }
+             else
+               {
+                 struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
+                                                   0, VAR_NAMESPACE, 0, NULL);
+                 v = locate_var_value (s, 0);
+               }
+             VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), baseclass));
+             return v;
+           }
+       }
+
+      if (TYPE_N_BASECLASSES (t) == 0)
+       break;
+
+      t = TYPE_BASECLASS (t, 0);
+    }
+  return 0;
+}
+
+/* Compare two argument lists and return the position in which they differ,
+   or zero if equal.
+
+   STATICP is nonzero if the T1 argument list came from a
+   static member function.
+
+   For non-static member functions, we ignore the first argument,
+   which is the type of the instance variable.  This is because we want
+   to handle calls with objects from derived classes.  This is not
+   entirely correct: we should actually check to make sure that a
+   requested operation is type secure, shouldn't we?  FIXME.  */
+
+int
+typecmp (staticp, t1, t2)
+     int staticp;
+     struct type *t1[];
+     value t2[];
+{
+  int i;
+
+  if (staticp && t1 == 0)
+    return t2[1] != 0;
+  if (t1 == 0)
+    return 1;
+  if (t1[0]->code == TYPE_CODE_VOID) return 0;
+  if (t1[!staticp] == 0) return 0;
+  for (i = !staticp; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++)
+    {
+      if (! t2[i]
+         || t1[i]->code != t2[i]->type->code
+/* Too pessimistic:  || t1[i]->target_type != t2[i]->type->target_type */
+ )
+       return i+1;
+    }
+  if (!t1[i]) return 0;
+  return t2[i] ? i+1 : 0;
+}
+
+/* C++: return the value of the class instance variable, if one exists.
+   Flag COMPLAIN signals an error if the request is made in an
+   inappropriate context.  */
+value
+value_of_this (complain)
+     int complain;
+{
+  extern FRAME selected_frame;
+  struct symbol *func, *sym;
+  struct block *b;
+  int i;
+  static const char funny_this[] = "this";
+  value this;
+
+  if (selected_frame == 0)
+    if (complain)
+      error ("no frame selected");
+    else return 0;
+
+  func = get_frame_function (selected_frame);
+  if (!func)
+    {
+      if (complain)
+       error ("no `this' in nameless context");
+      else return 0;
+    }
+
+  b = SYMBOL_BLOCK_VALUE (func);
+  i = BLOCK_NSYMS (b);
+  if (i <= 0)
+    if (complain)
+      error ("no args, no `this'");
+    else return 0;
+
+  /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER
+     symbol instead of the LOC_ARG one (if both exist).  */
+  sym = lookup_block_symbol (b, funny_this, VAR_NAMESPACE);
+  if (sym == NULL)
+    {
+      if (complain)
+       error ("current stack frame not in method");
+      else
+       return NULL;
+    }
+
+  this = read_var_value (sym, selected_frame);
+  if (this == 0 && complain)
+    error ("`this' argument at unknown address");
+  return this;
+}
diff --git a/gdb/valprint.c b/gdb/valprint.c
new file mode 100644 (file)
index 0000000..9a3ab90
--- /dev/null
@@ -0,0 +1,1915 @@
+/* Print values for GNU debugger gdb.
+   Copyright (C) 1986, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "obstack.h"
+
+#include <errno.h>
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+extern void print_scalar_formatted();  /* printcmd.c */
+extern void print_address_demangle();  /* printcmd.c */
+extern int demangle;   /* whether to print C++ syms raw or source-form */
+
+/* Maximum number of chars to print for a string pointer value
+   or vector contents, or UINT_MAX for no limit.  */
+
+static unsigned int print_max;
+
+static void type_print_varspec_suffix ();
+static void type_print_varspec_prefix ();
+static void type_print_base ();
+static void type_print_method_args ();
+
+/* Default input and output radixes, and output format letter.  */
+
+unsigned input_radix = 10;
+unsigned output_radix = 10;
+int output_format = 0;
+
+
+char **unsigned_type_table;
+char **signed_type_table;
+char **float_type_table;
+
+
+/* Print repeat counts if there are more than this
+   many repetitions of an element in an array.  */
+#define        REPEAT_COUNT_THRESHOLD  10
+\f
+/* Print the character string STRING, printing at most LENGTH characters.
+   Printing stops early if the number hits print_max; repeat counts
+   are printed as appropriate.  Print ellipses at the end if we
+   had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.  */
+
+void
+print_string (stream, string, length, force_ellipses)
+     FILE *stream;
+     char *string;
+     unsigned int length;
+     int force_ellipses;
+{
+  register unsigned int i;
+  unsigned int things_printed = 0;
+  int in_quotes = 0;
+  int need_comma = 0;
+  extern int inspect_it;
+
+  if (length == 0)
+    {
+      fputs_filtered ("\"\"", stdout);
+      return;
+    }
+
+  for (i = 0; i < length && things_printed < print_max; ++i)
+    {
+      /* Position of the character we are examining
+        to see whether it is repeated.  */
+      unsigned int rep1;
+      /* Number of repetitions we have detected so far.  */
+      unsigned int reps;
+
+      QUIT;
+
+      if (need_comma)
+       {
+         fputs_filtered (", ", stream);
+         need_comma = 0;
+       }
+
+      rep1 = i + 1;
+      reps = 1;
+      while (rep1 < length && string[rep1] == string[i])
+       {
+         ++rep1;
+         ++reps;
+       }
+
+      if (reps > REPEAT_COUNT_THRESHOLD)
+       {
+         if (in_quotes)
+           {
+             if (inspect_it)
+               fputs_filtered ("\\\", ", stream);
+             else
+               fputs_filtered ("\", ", stream);
+             in_quotes = 0;
+           }
+         fputs_filtered ("'", stream);
+         printchar (string[i], stream, '\'');
+         fprintf_filtered (stream, "' <repeats %u times>", reps);
+         i = rep1 - 1;
+         things_printed += REPEAT_COUNT_THRESHOLD;
+         need_comma = 1;
+       }
+      else
+       {
+         if (!in_quotes)
+           {
+             if (inspect_it)
+               fputs_filtered ("\\\"", stream);
+             else
+               fputs_filtered ("\"", stream);
+             in_quotes = 1;
+           }
+         printchar (string[i], stream, '"');
+         ++things_printed;
+       }
+    }
+
+  /* Terminate the quotes if necessary.  */
+  if (in_quotes)
+    {
+      if (inspect_it)
+       fputs_filtered ("\\\"", stream);
+      else
+       fputs_filtered ("\"", stream);
+    }
+
+  if (force_ellipses || i < length)
+    fputs_filtered ("...", stream);
+}
+
+/* Print a floating point value of type TYPE, pointed to in GDB by VALADDR,
+   on STREAM.  */
+
+void
+print_floating (valaddr, type, stream)
+     char *valaddr;
+     struct type *type;
+     FILE *stream;
+{
+  double doub;
+  int inv;
+  unsigned len = TYPE_LENGTH (type);
+  
+#if defined (IEEE_FLOAT)
+
+  /* Check for NaN's.  Note that this code does not depend on us being
+     on an IEEE conforming system.  It only depends on the target
+     machine using IEEE representation.  This means (a)
+     cross-debugging works right, and (2) IEEE_FLOAT can (and should)
+     be defined for systems like the 68881, which uses IEEE
+     representation, but is not IEEE conforming.  */
+
+  {
+    long low, high;
+    /* Is the sign bit 0?  */
+    int nonnegative;
+    /* Is it is a NaN (i.e. the exponent is all ones and
+       the fraction is nonzero)?  */
+    int is_nan;
+
+    if (len == sizeof (float))
+      {
+       /* It's single precision. */
+       bcopy (valaddr, &low, sizeof (low));
+       /* target -> host.  */
+       SWAP_TARGET_AND_HOST (&low, sizeof (float));
+       nonnegative = low >= 0;
+       is_nan = ((((low >> 23) & 0xFF) == 0xFF) 
+                 && 0 != (low & 0x7FFFFF));
+       low &= 0x7fffff;
+       high = 0;
+      }
+    else
+      {
+       /* It's double precision.  Get the high and low words.  */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+         bcopy (valaddr+4, &low,  sizeof (low));
+         bcopy (valaddr+0, &high, sizeof (high));
+#else
+         bcopy (valaddr+0, &low,  sizeof (low));
+         bcopy (valaddr+4, &high, sizeof (high));
+#endif
+         SWAP_TARGET_AND_HOST (&low, sizeof (low));
+         SWAP_TARGET_AND_HOST (&high, sizeof (high));
+         nonnegative = high >= 0;
+         is_nan = (((high >> 20) & 0x7ff) == 0x7ff
+                   && ! ((((high & 0xfffff) == 0)) && (low == 0)));
+         high &= 0xfffff;
+       }
+
+    if (is_nan)
+      {
+       /* The meaning of the sign and fraction is not defined by IEEE.
+          But the user might know what they mean.  For example, they
+          (in an implementation-defined manner) distinguish between
+          signaling and quiet NaN's.  */
+       if (high)
+         fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonnegative,
+                           high, low);
+       else
+         fprintf_filtered (stream, "-NaN(0x%lx)" + nonnegative, low);
+       return;
+      }
+  }
+#endif /* IEEE_FLOAT.  */
+
+  doub = unpack_double (type, valaddr, &inv);
+  if (inv)
+    fprintf_filtered (stream, "<invalid float value>");
+  else
+    fprintf_filtered (stream, len <= sizeof(float) ? "%.6g" : "%.17g", doub);
+}
+
+/* VALADDR points to an integer of LEN bytes.  Print it in hex on stream.  */
+static void
+print_hex_chars (stream, valaddr, len)
+     FILE *stream;
+     unsigned char *valaddr;
+     unsigned len;
+{
+  unsigned char *p;
+  
+  fprintf_filtered (stream, "0x");
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+  for (p = valaddr;
+       p < valaddr + len;
+       p++)
+#else /* Little endian.  */
+  for (p = valaddr + len - 1;
+       p >= valaddr;
+       p--)
+#endif
+    {
+      fprintf_filtered (stream, "%02x", *p);
+    }
+}
+\f
+/* Print the value VAL in C-ish syntax on stream STREAM.
+   FORMAT is a format-letter, or 0 for print in natural format of data type.
+   If the object printed is a string pointer, returns
+   the number of string bytes printed.  */
+
+int
+value_print (val, stream, format, pretty)
+     value val;
+     FILE *stream;
+     char format;
+     enum val_prettyprint pretty;
+{
+  register unsigned int i, n, typelen;
+
+  if (val == 0)
+    {
+      printf_filtered ("<address of value unknown>");
+      return 0;
+    }
+  if (VALUE_OPTIMIZED_OUT (val))
+    {
+      printf_filtered ("<value optimized out>");
+      return 0;
+    }
+  
+  /* A "repeated" value really contains several values in a row.
+     They are made by the @ operator.
+     Print such values as if they were arrays.  */
+
+  else if (VALUE_REPEATED (val))
+    {
+      n = VALUE_REPETITIONS (val);
+      typelen = TYPE_LENGTH (VALUE_TYPE (val));
+      fprintf_filtered (stream, "{");
+      /* Print arrays of characters using string syntax.  */
+      if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT
+         && format == 0)
+       print_string (stream, VALUE_CONTENTS (val), n, 0);
+      else
+       {
+         unsigned int things_printed = 0;
+         
+         for (i = 0; i < n && things_printed < print_max; i++)
+           {
+             /* Position of the array element we are examining to see
+                whether it is repeated.  */
+             unsigned int rep1;
+             /* Number of repetitions we have detected so far.  */
+             unsigned int reps;
+
+             if (i != 0)
+               fprintf_filtered (stream, ", ");
+             wrap_here ("");
+
+             rep1 = i + 1;
+             reps = 1;
+             while (rep1 < n
+                    && !bcmp (VALUE_CONTENTS (val) + typelen * i,
+                              VALUE_CONTENTS (val) + typelen * rep1, typelen))
+               {
+                 ++reps;
+                 ++rep1;
+               }
+
+             if (reps > REPEAT_COUNT_THRESHOLD)
+               {
+                 val_print (VALUE_TYPE (val),
+                            VALUE_CONTENTS (val) + typelen * i,
+                            VALUE_ADDRESS (val) + typelen * i,
+                            stream, format, 1, 0, pretty);
+                 fprintf (stream, " <repeats %u times>", reps);
+                 i = rep1 - 1;
+                 things_printed += REPEAT_COUNT_THRESHOLD;
+               }
+             else
+               {
+                 val_print (VALUE_TYPE (val),
+                            VALUE_CONTENTS (val) + typelen * i,
+                            VALUE_ADDRESS (val) + typelen * i,
+                            stream, format, 1, 0, pretty);
+                 things_printed++;
+               }
+           }
+         if (i < n)
+           fprintf_filtered (stream, "...");
+       }
+      fprintf_filtered (stream, "}");
+      return n * typelen;
+    }
+  else
+    {
+      /* If it is a pointer, indicate what it points to.
+
+        Print type also if it is a reference.
+
+         C++: if it is a member pointer, we will take care
+        of that when we print it.  */
+      if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR
+         || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF)
+       {
+         /* Hack:  remove (char *) for char strings.  Their
+            type is indicated by the quoted string anyway. */
+          if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR
+           && TYPE_LENGTH   (TYPE_TARGET_TYPE (VALUE_TYPE (val)))
+                        == sizeof(char)
+           && TYPE_CODE     (TYPE_TARGET_TYPE (VALUE_TYPE (val)))
+                        == TYPE_CODE_INT
+           && !TYPE_UNSIGNED (TYPE_TARGET_TYPE (VALUE_TYPE (val))))
+           {
+               /* Print nothing */
+           }
+         else
+           {
+             fprintf_filtered (stream, "(");
+             type_print (VALUE_TYPE (val), "", stream, -1);
+             fprintf_filtered (stream, ") ");
+           }
+       }
+      return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+                       VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
+    }
+}
+
+/* Return truth value for assertion that TYPE is of the type
+   "pointer to virtual function".  */
+static int
+is_vtbl_ptr_type(type)
+     struct type *type;
+{
+  char *typename = TYPE_NAME(type);
+  static const char vtbl_ptr_name[] =
+    { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e' };
+
+  return (typename != NULL && !strcmp(typename, vtbl_ptr_name));
+}
+
+/* Return truth value for the assertion that TYPE is of the type
+   "pointer to virtual function table".  */
+static int
+is_vtbl_member(type)
+     struct type *type;
+{
+  if (TYPE_CODE (type) == TYPE_CODE_PTR
+      && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY
+      && TYPE_CODE (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type))) == TYPE_CODE_STRUCT)
+    /* Virtual functions tables are full of pointers to virtual functions.  */
+    return is_vtbl_ptr_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)));
+  return 0;
+}
+\f
+/* Define a mess of print controls.  */
+
+int prettyprint;       /* Controls pretty printing of structures */
+int vtblprint;         /* Controls printing of vtbl's */
+int unionprint;                /* Controls printing of nested unions.  */
+int arrayprint;                /* Controls pretty printing of arrays.  */
+int addressprint;      /* Controls pretty printing of addresses.  */
+
+struct obstack dont_print_obstack;
+
+static void cplus_val_print ();
+
+/* Mutually recursive subroutines of cplus_val_print and val_print to print out
+   a structure's fields: val_print_fields and cplus_val_print.
+
+   TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the
+   same meanings as in cplus_val_print and val_print.
+
+   DONT_PRINT is an array of baseclass types that we
+   should not print, or zero if called from top level.  */
+static void
+val_print_fields (type, valaddr, stream, format, recurse, pretty, dont_print)
+     struct type *type;
+     char *valaddr;
+     FILE *stream;
+     char format;
+     int recurse;
+     enum val_prettyprint pretty;
+     struct type **dont_print;
+{
+  int i, len, n_baseclasses;
+
+  fprintf_filtered (stream, "{");
+  len = TYPE_NFIELDS (type);
+  n_baseclasses = TYPE_N_BASECLASSES (type);
+
+  /* Print out baseclasses such that we don't print
+     duplicates of virtual baseclasses.  */
+  if (n_baseclasses > 0)
+    cplus_val_print (type, valaddr, stream, format, recurse+1, pretty, dont_print);
+
+  if (!len && n_baseclasses == 1)
+    fprintf_filtered (stream, "<No data fields>");
+  else
+    {
+      extern int inspect_it;
+      int fields_seen = 0;
+
+      for (i = n_baseclasses; i < len; i++)
+       {
+         /* Check if static field */
+         if (TYPE_FIELD_STATIC (type, i))
+           continue;
+         if (fields_seen)
+           fprintf_filtered (stream, ", ");
+         else if (n_baseclasses > 0)
+           {
+             fprintf_filtered (stream, "\n");
+             print_spaces_filtered (2 + 2 * recurse, stream);
+             fputs_filtered ("members of ", stream);
+             fputs_filtered (type_name_no_tag (type), stream);
+             fputs_filtered (": ", stream);
+           }
+         fields_seen = 1;
+
+         if (pretty)
+           {
+             fprintf_filtered (stream, "\n");
+             print_spaces_filtered (2 + 2 * recurse, stream);
+           }
+         else 
+           {
+             wrap_here (n_spaces (2 + 2 * recurse));
+           }
+         if (inspect_it)
+           {
+             if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR)
+               fputs_filtered ("\"( ptr \"", stream);
+             else
+               fputs_filtered ("\"( nodef \"", stream);
+             fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+             fputs_filtered ("\" \"", stream);
+             fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+             fputs_filtered ("\") \"", stream);
+           }
+         else
+           {
+             fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+             fputs_filtered (" = ", stream);
+           }
+         if (TYPE_FIELD_PACKED (type, i))
+           {
+             LONGEST val;
+             char *valp = (char *) & val;
+
+             val = unpack_field_as_long (type, valaddr, i);
+
+             /* Since we have moved the bitfield into a long,
+                if it is declared with a smaller type, we need to
+                offset its address *in gdb* to match the type we
+                are passing to val_print.  */
+#if HOST_BYTE_ORDER == BIG_ENDIAN
+             valp += sizeof val - TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
+#endif
+             val_print (TYPE_FIELD_TYPE (type, i), valp, 0,
+                        stream, format, 0, recurse + 1, pretty);
+           }
+         else
+           {
+             val_print (TYPE_FIELD_TYPE (type, i), 
+                        valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
+                        0, stream, format, 0, recurse + 1, pretty);
+           }
+       }
+      if (pretty)
+       {
+         fprintf_filtered (stream, "\n");
+         print_spaces_filtered (2 * recurse, stream);
+       }
+    }
+  fprintf_filtered (stream, "}");
+}
+
+/* Special val_print routine to avoid printing multiple copies of virtual
+   baseclasses.  */
+
+static void
+cplus_val_print (type, valaddr, stream, format, recurse, pretty, dont_print)
+     struct type *type;
+     char *valaddr;
+     FILE *stream;
+     char format;
+     int recurse;
+     enum val_prettyprint pretty;
+     struct type **dont_print;
+{
+  struct obstack tmp_obstack;
+  struct type **last_dont_print
+    = (struct type **)obstack_next_free (&dont_print_obstack);
+  int i, n_baseclasses = TYPE_N_BASECLASSES (type);
+
+  if (dont_print == 0)
+    {
+      /* If we're at top level, carve out a completely fresh
+        chunk of the obstack and use that until this particular
+        invocation returns.  */
+      tmp_obstack = dont_print_obstack;
+      /* Bump up the high-water mark.  Now alpha is omega.  */
+      obstack_finish (&dont_print_obstack);
+    }
+
+  for (i = 0; i < n_baseclasses; i++)
+    {
+      char *baddr;
+
+      if (BASETYPE_VIA_VIRTUAL (type, i))
+       {
+         struct type **first_dont_print
+           = (struct type **)obstack_base (&dont_print_obstack);
+
+         int j = (struct type **)obstack_next_free (&dont_print_obstack)
+           - first_dont_print;
+
+         while (--j >= 0)
+           if (TYPE_BASECLASS (type, i) == first_dont_print[j])
+             goto flush_it;
+
+         obstack_ptr_grow (&dont_print_obstack, TYPE_BASECLASS (type, i));
+       }
+
+      baddr = baseclass_addr (type, i, valaddr, 0);
+      if (baddr == 0)
+       error ("could not find virtual baseclass `%s'\n",
+              type_name_no_tag (TYPE_BASECLASS (type, i)));
+
+      fprintf_filtered (stream, "\n");
+      if (pretty)
+       print_spaces_filtered (2 + 2 * recurse, stream);
+      fputs_filtered ("<", stream);
+      fputs_filtered (type_name_no_tag (TYPE_BASECLASS (type, i)), stream);
+      fputs_filtered ("> = ", stream);
+      val_print_fields (TYPE_BASECLASS (type, i), baddr, stream, format,
+                       recurse, pretty,
+                       (struct type **)obstack_base (&dont_print_obstack));
+    flush_it:
+      ;
+    }
+
+  if (dont_print == 0)
+    {
+      /* Free the space used to deal with the printing
+        of this type from top level.  */
+      obstack_free (&dont_print_obstack, last_dont_print);
+      /* Reset watermark so that we can continue protecting
+        ourselves from whatever we were protecting ourselves.  */
+      dont_print_obstack = tmp_obstack;
+    }
+}
+
+/* Print data of type TYPE located at VALADDR (within GDB),
+   which came from the inferior at address ADDRESS,
+   onto stdio stream STREAM according to FORMAT
+   (a letter or 0 for natural format).  The data at VALADDR
+   is in target byte order.
+
+   If the data are a string pointer, returns the number of
+   sting characters printed.
+
+   if DEREF_REF is nonzero, then dereference references,
+   otherwise just print them like pointers.
+
+   The PRETTY parameter controls prettyprinting.  */
+
+int
+val_print (type, valaddr, address, stream, format,
+          deref_ref, recurse, pretty)
+     struct type *type;
+     char *valaddr;
+     CORE_ADDR address;
+     FILE *stream;
+     char format;
+     int deref_ref;
+     int recurse;
+     enum val_prettyprint pretty;
+{
+  register unsigned int i;
+  unsigned len;
+  struct type *elttype;
+  unsigned eltlen;
+  LONGEST val;
+  unsigned char c;
+
+  if (pretty == Val_pretty_default)
+    {
+      pretty = prettyprint ? Val_prettyprint : Val_no_prettyprint;
+    }
+  
+  QUIT;
+
+  check_stub_type (type);
+  
+  if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+    {
+      fprintf_filtered (stream, "<unknown struct>");
+      fflush (stream);
+      return 0;
+    }
+  
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_ARRAY:
+      if (TYPE_LENGTH (type) >= 0
+         && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+       {
+         elttype = TYPE_TARGET_TYPE (type);
+         eltlen = TYPE_LENGTH (elttype);
+         len = TYPE_LENGTH (type) / eltlen;
+         if (arrayprint)
+           print_spaces_filtered (2 + 2 * recurse, stream);
+         fprintf_filtered (stream, "{");
+         /* For an array of chars, print with string syntax.  */
+         if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
+             && (format == 0 || format == 's') )
+           print_string (stream, valaddr, len, 0);
+         else
+           {
+             unsigned int things_printed = 0;
+             
+             for (i = 0; i < len && things_printed < print_max; i++)
+               {
+                 /* Position of the array element we are examining to see
+                    whether it is repeated.  */
+                 unsigned int rep1;
+                 /* Number of repetitions we have detected so far.  */
+                 unsigned int reps;
+                 
+                 if (i != 0)
+                   if (arrayprint)
+                     {
+                       fprintf_filtered (stream, ",\n");
+                       print_spaces_filtered (2 + 2 * recurse, stream);
+                     }
+                   else
+                     fprintf_filtered (stream, ", ");
+                   wrap_here (n_spaces (2 + 2 * recurse));
+                 
+                 rep1 = i + 1;
+                 reps = 1;
+                 while (rep1 < len
+                        && !bcmp (valaddr + i * eltlen,
+                                  valaddr + rep1 * eltlen, eltlen))
+                   {
+                     ++reps;
+                     ++rep1;
+                   }
+
+                 if (reps > REPEAT_COUNT_THRESHOLD)
+                   {
+                     val_print (elttype, valaddr + i * eltlen,
+                                0, stream, format, deref_ref,
+                                recurse + 1, pretty);
+                     fprintf_filtered (stream, " <repeats %u times>", reps);
+                     i = rep1 - 1;
+                     things_printed += REPEAT_COUNT_THRESHOLD;
+                   }
+                 else
+                   {
+                     val_print (elttype, valaddr + i * eltlen,
+                                0, stream, format, deref_ref,
+                                recurse + 1, pretty);
+                     things_printed++;
+                   }
+               }
+             if (i < len)
+               fprintf_filtered (stream, "...");
+           }
+         fprintf_filtered (stream, "}");
+         break;
+       }
+      /* Array of unspecified length: treat like pointer to first elt.  */
+      valaddr = (char *) &address;
+
+    case TYPE_CODE_PTR:
+      if (format && format != 's')
+       {
+         print_scalar_formatted (valaddr, type, format, 0, stream);
+         break;
+       }
+      if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
+       {
+         struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
+         struct fn_field *f;
+         int j, len2;
+         char *kind = "";
+
+         val = unpack_long (builtin_type_int, valaddr);
+         if (val < 128)
+           {
+             len = TYPE_NFN_FIELDS (domain);
+             for (i = 0; i < len; i++)
+               {
+                 f = TYPE_FN_FIELDLIST1 (domain, i);
+                 len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+                 for (j = 0; j < len2; j++)
+                   {
+                     QUIT;
+                     if (TYPE_FN_FIELD_VOFFSET (f, j) == val)
+                       {
+                         kind = "virtual";
+                         goto common;
+                       }
+                   }
+               }
+           }
+         else
+           {
+             struct symbol *sym = find_pc_function ((CORE_ADDR) val);
+             if (sym == 0)
+               error ("invalid pointer to member function");
+             len = TYPE_NFN_FIELDS (domain);
+             for (i = 0; i < len; i++)
+               {
+                 f = TYPE_FN_FIELDLIST1 (domain, i);
+                 len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+                 for (j = 0; j < len2; j++)
+                   {
+                     QUIT;
+                     if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
+                       goto common;
+                   }
+               }
+           }
+       common:
+         if (i < len)
+           {
+             fprintf_filtered (stream, "&");
+             type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
+             fprintf (stream, kind);
+             if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+                 && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER)
+               type_print_method_args
+                 (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+                  TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream);
+             else
+               type_print_method_args
+                 (TYPE_FN_FIELD_ARGS (f, j), "",
+                  TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream);
+             break;
+           }
+         fprintf_filtered (stream, "(");
+         type_print (type, "", stream, -1);
+         fprintf_filtered (stream, ") %d", (int) val >> 3);
+       }
+      else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
+       {
+         struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
+
+         /* VAL is a byte offset into the structure type DOMAIN.
+            Find the name of the field for that offset and
+            print it.  */
+         int extra = 0;
+         int bits = 0;
+         len = TYPE_NFIELDS (domain);
+         /* @@ Make VAL into bit offset */
+         val = unpack_long (builtin_type_int, valaddr) << 3;
+         for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
+           {
+             int bitpos = TYPE_FIELD_BITPOS (domain, i);
+             QUIT;
+             if (val == bitpos)
+               break;
+             if (val < bitpos && i != 0)
+               {
+                 /* Somehow pointing into a field.  */
+                 i -= 1;
+                 extra = (val - TYPE_FIELD_BITPOS (domain, i));
+                 if (extra & 0x3)
+                   bits = 1;
+                 else
+                   extra >>= 3;
+                 break;
+               }
+           }
+         if (i < len)
+           {
+             fprintf_filtered (stream, "&");
+             type_print_base (domain, stream, 0, 0);
+             fprintf_filtered (stream, "::");
+             fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
+             if (extra)
+               fprintf_filtered (stream, " + %d bytes", extra);
+             if (bits)
+               fprintf_filtered (stream, " (offset in bits)");
+             break;
+           }
+         fprintf_filtered (stream, "%d", val >> 3);
+       }
+      else
+       {
+         CORE_ADDR addr = (CORE_ADDR) unpack_long (type, valaddr);
+         elttype = TYPE_TARGET_TYPE (type);
+
+         if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
+           {
+             /* Try to print what function it points to.  */
+             print_address_demangle (addr, stream, demangle);
+             /* Return value is irrelevant except for string pointers.  */
+             return 0;
+           }
+
+         if (addressprint && format != 's')
+           fprintf_filtered (stream, "0x%x", addr);
+
+         /* For a pointer to char or unsigned char,
+            also print the string pointed to, unless pointer is null.  */
+         i = 0;                /* Number of characters printed.  */
+         if (TYPE_LENGTH (elttype) == 1 
+             && TYPE_CODE (elttype) == TYPE_CODE_INT
+             && (format == 0 || format == 's')
+             && addr != 0
+             /* If print_max is UINT_MAX, the alloca below will fail.
+                In that case don't try to print the string.  */
+             && print_max < UINT_MAX)
+           {
+             int first_addr_err = 0;
+             int errcode = 0;
+             
+             /* Get first character.  */
+             errcode = target_read_memory (addr, (char *)&c, 1);
+             if (errcode != 0)
+               {
+                 /* First address out of bounds.  */
+                 first_addr_err = 1;
+               }
+             else
+               {
+                 /* A real string.  */
+                 char *string = (char *) alloca (print_max);
+
+                 /* If the loop ends by us hitting print_max characters,
+                    we need to have elipses at the end.  */
+                 int force_ellipses = 1;
+
+                 /* This loop always fetches print_max characters, even
+                    though print_string might want to print more or fewer
+                    (with repeated characters).  This is so that
+                    we don't spend forever fetching if we print
+                    a long string consisting of the same character
+                    repeated.  Also so we can do it all in one memory
+                    operation, which is faster.  However, this will be
+                    slower if print_max is set high, e.g. if you set
+                    print_max to 1000, not only will it take a long
+                    time to fetch short strings, but if you are near
+                    the end of the address space, it might not work.
+                    FIXME.  */
+                 QUIT;
+                 errcode = target_read_memory (addr, string, print_max);
+                 if (errcode != 0)
+                     force_ellipses = 0;
+                 else 
+                   for (i = 0; i < print_max; i++)
+                     if (string[i] == '\0')
+                       {
+                         force_ellipses = 0;
+                         break;
+                       }
+                 QUIT;
+
+                 if (addressprint)
+                   fputs_filtered (" ", stream);
+                 print_string (stream, string, i, force_ellipses);
+               }
+
+             if (errcode != 0)
+               {
+                 if (errcode == EIO)
+                   {
+                     fprintf_filtered (stream,
+                                       (" <Address 0x%x out of bounds>"
+                                        + first_addr_err),
+                                       addr + i);
+                   }
+                 else
+                   {
+                     if (errcode >= sys_nerr || errcode < 0)
+                       error ("Error reading memory address 0x%x: unknown error (%d).",
+                              addr + i, errcode);
+                     else
+                       error ("Error reading memory address 0x%x: %s.",
+                              addr + i, sys_errlist[errcode]);
+                   }
+               }
+
+             fflush (stream);
+           }
+         else /* print vtbl's nicely */
+         if (is_vtbl_member(type))
+           {
+             CORE_ADDR vt_address = (CORE_ADDR) unpack_long (type, valaddr);
+
+             int vt_index = find_pc_misc_function (vt_address);
+             if (vt_index >= 0
+                 && vt_address == misc_function_vector[vt_index].address)
+               {
+                 fputs_filtered (" <", stream);
+                 fputs_demangled (misc_function_vector[vt_index].name,
+                                  stream, 1);
+                 fputs_filtered (">", stream);
+               }
+             if (vtblprint)
+               {
+                 value val;
+
+                 val = value_at (TYPE_TARGET_TYPE (type), vt_address);
+                 val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+                            VALUE_ADDRESS (val), stream, format,
+                            deref_ref, recurse + 1, pretty);
+                 if (pretty)
+                   {
+                     fprintf_filtered (stream, "\n");
+                     print_spaces_filtered (2 + 2 * recurse, stream);
+                   }
+               }
+             }
+
+         /* Return number of characters printed, plus one for the
+            terminating null if we have "reached the end".  */
+         return i + (print_max && i != print_max);
+       }
+      break;
+
+    case TYPE_CODE_MEMBER:
+      error ("not implemented: member type in val_print");
+      break;
+
+    case TYPE_CODE_REF:
+      if (addressprint)
+        {
+         fprintf_filtered (stream, "@0x%lx",
+                           unpack_long (builtin_type_int, valaddr));
+         if (deref_ref)
+           fputs_filtered (": ", stream);
+        }
+      /* De-reference the reference.  */
+      if (deref_ref)
+       {
+         if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
+           {
+             value val = value_at (TYPE_TARGET_TYPE (type),
+                                   (CORE_ADDR) unpack_long (builtin_type_int,
+                                                            valaddr));
+             val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+                        VALUE_ADDRESS (val), stream, format,
+                        deref_ref, recurse + 1, pretty);
+           }
+         else
+           fputs_filtered ("???", stream);
+       }
+      break;
+
+    case TYPE_CODE_UNION:
+      if (recurse && !unionprint)
+       {
+         fprintf_filtered (stream, "{...}");
+         break;
+       }
+      /* Fall through.  */
+    case TYPE_CODE_STRUCT:
+      if (vtblprint && is_vtbl_ptr_type(type))
+       {
+          /* Print the unmangled name if desired.  */
+         print_address_demangle(*((int *) (valaddr +   /* FIXME bytesex */
+             TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8)),
+             stream, demangle);
+         break;
+       }
+      val_print_fields (type, valaddr, stream, format, recurse, pretty, 0);
+      break;
+
+    case TYPE_CODE_ENUM:
+      if (format)
+       {
+         print_scalar_formatted (valaddr, type, format, 0, stream);
+         break;
+       }
+      len = TYPE_NFIELDS (type);
+      val = unpack_long (builtin_type_int, valaddr);
+      for (i = 0; i < len; i++)
+       {
+         QUIT;
+         if (val == TYPE_FIELD_BITPOS (type, i))
+           break;
+       }
+      if (i < len)
+       fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+      else
+       fprintf_filtered (stream, "%d", (int) val);
+      break;
+
+    case TYPE_CODE_FUNC:
+      if (format)
+       {
+         print_scalar_formatted (valaddr, type, format, 0, stream);
+         break;
+       }
+      fprintf_filtered (stream, "{");
+      type_print (type, "", stream, -1);
+      fprintf_filtered (stream, "} ");
+      if (addressprint)
+       fprintf_filtered (stream, "0x%x", address);
+      break;
+
+    case TYPE_CODE_INT:
+      if (format || output_format)
+       {
+         print_scalar_formatted (valaddr, type,
+                                 format? format: output_format,
+                                 0, stream);
+         break;
+       }
+      if (TYPE_LENGTH (type) > sizeof (LONGEST))
+       {
+         if (TYPE_UNSIGNED (type))
+           {
+             /* First figure out whether the number in fact has zeros
+                in all its bytes more significant than least significant
+                sizeof (LONGEST) ones.  */
+             char *p;
+             /* Pointer to first (i.e. lowest address) nonzero character.  */
+             char *first_addr;
+             unsigned len = TYPE_LENGTH (type);
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+             for (p = valaddr;
+                  len > sizeof (LONGEST)
+                  && p < valaddr + TYPE_LENGTH (type);
+                  p++)
+#else /* Little endian.  */
+             first_addr = valaddr;
+             for (p = valaddr + TYPE_LENGTH (type);
+                  len > sizeof (LONGEST) && p >= valaddr;
+                  p--)
+#endif /* Little endian.  */
+               {
+                 if (*p == 0)
+                   len--;
+                 else
+                   break;
+               }
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+             first_addr = p;
+#endif
+             
+             if (len <= sizeof (LONGEST))
+               {
+                 /* We can print it in decimal.  */
+                 fprintf_filtered
+                   (stream, 
+#if defined (LONG_LONG)
+                    "%llu",
+#else
+                    "%lu",
+#endif
+                    unpack_long (BUILTIN_TYPE_LONGEST, first_addr));
+               }
+             else
+               {
+                 /* It is big, so print it in hex.  */
+                 print_hex_chars (stream, (unsigned char *)first_addr, len);
+               }
+           }
+         else
+           {
+             /* Signed.  One could assume two's complement (a reasonable
+                assumption, I think) and do better than this.  */
+             print_hex_chars (stream, (unsigned char *)valaddr,
+                              TYPE_LENGTH (type));
+           }
+         break;
+       }
+#ifdef PRINT_TYPELESS_INTEGER
+      PRINT_TYPELESS_INTEGER (stream, type, unpack_long (type, valaddr));
+#else
+#ifndef LONG_LONG
+      fprintf_filtered (stream,
+                       TYPE_UNSIGNED (type) ? "%u" : "%d",
+                       unpack_long (type, valaddr));
+#else
+      fprintf_filtered (stream,
+                       TYPE_UNSIGNED (type) ? "%llu" : "%lld",
+                       unpack_long (type, valaddr));
+#endif
+#endif
+                       
+      if (TYPE_LENGTH (type) == 1)
+       {
+         fprintf_filtered (stream, " '");
+         printchar ((unsigned char) unpack_long (type, valaddr), 
+                    stream, '\'');
+         fprintf_filtered (stream, "'");
+       }
+      break;
+
+    case TYPE_CODE_FLT:
+      if (format)
+       print_scalar_formatted (valaddr, type, format, 0, stream);
+      else
+       print_floating (valaddr, type, stream);
+      break;
+
+    case TYPE_CODE_VOID:
+      fprintf_filtered (stream, "void");
+      break;
+
+    case TYPE_CODE_UNDEF:
+      /* This happens (without TYPE_FLAG_STUB set) on systems which don't use
+        dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar"
+        and no complete type for struct foo in that file.  */
+      fprintf_filtered (stream, "<unknown struct>");
+      break;
+
+    case TYPE_CODE_ERROR:
+      fprintf_filtered (stream, "?");
+      break;
+
+    default:
+      error ("Invalid type code in symbol table.");
+    }
+  fflush (stream);
+  return 0;
+}
+\f
+/* Print a description of a type TYPE
+   in the form of a declaration of a variable named VARSTRING.
+   (VARSTRING is demangled if necessary.)
+   Output goes to STREAM (via stdio).
+   If SHOW is positive, we show the contents of the outermost level
+   of structure even if there is a type name that could be used instead.
+   If SHOW is negative, we never show the details of elements' types.  */
+
+void
+type_print (type, varstring, stream, show)
+     struct type *type;
+     char *varstring;
+     FILE *stream;
+     int show;
+{
+  type_print_1 (type, varstring, stream, show, 0);
+}
+
+/* LEVEL is the depth to indent lines by.  */
+
+void
+type_print_1 (type, varstring, stream, show, level)
+     struct type *type;
+     char *varstring;
+     FILE *stream;
+     int show;
+     int level;
+{
+  register enum type_code code;
+  type_print_base (type, stream, show, level);
+  code = TYPE_CODE (type);
+  if ((varstring && *varstring)
+      ||
+      /* Need a space if going to print stars or brackets;
+        but not if we will print just a type name.  */
+      ((show > 0 || TYPE_NAME (type) == 0)
+       &&
+       (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
+       || code == TYPE_CODE_METHOD
+       || code == TYPE_CODE_ARRAY
+       || code == TYPE_CODE_MEMBER
+       || code == TYPE_CODE_REF)))
+    fprintf_filtered (stream, " ");
+  type_print_varspec_prefix (type, stream, show, 0);
+  fputs_demangled (varstring, stream, -1);     /* Print demangled name
+                                                  without arguments */
+  type_print_varspec_suffix (type, stream, show, 0);
+}
+
+/* Print the method arguments ARGS to the file STREAM.  */
+static void
+type_print_method_args (args, prefix, varstring, staticp, stream)
+     struct type **args;
+     char *prefix, *varstring;
+     int staticp;
+     FILE *stream;
+{
+  int i;
+
+  fputs_filtered (" ", stream);
+  fputs_demangled (prefix, stream, 1);
+  fputs_demangled (varstring, stream, 1);
+  fputs_filtered (" (", stream);
+  if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID)
+    {
+      i = !staticp;            /* skip the class variable */
+      while (1)
+       {
+         type_print (args[i++], "", stream, 0);
+         if (!args[i]) 
+           {
+             fprintf_filtered (stream, " ...");
+             break;
+           }
+         else if (args[i]->code != TYPE_CODE_VOID)
+           {
+             fprintf_filtered (stream, ", ");
+           }
+         else break;
+       }
+    }
+  fprintf_filtered (stream, ")");
+}
+  
+/* If TYPE is a derived type, then print out derivation
+   information.  Print out all layers of the type heirarchy
+   until we encounter one with multiple inheritance.
+   At that point, print out that ply, and return.  */
+static void
+type_print_derivation_info (stream, type)
+     FILE *stream;
+     struct type *type;
+{
+  char *name;
+  int i, n_baseclasses = TYPE_N_BASECLASSES (type);
+  struct type *basetype = 0;
+
+  while (type && n_baseclasses > 0)
+    {
+      /* Not actually sure about this one -- Bryan. */
+      check_stub_type (type);
+      
+      fprintf_filtered (stream, ": ");
+      for (i = 0; ;)
+       {
+         basetype = TYPE_BASECLASS (type, i);
+         if (name = type_name_no_tag (basetype))
+           {
+             fprintf_filtered (stream, "%s%s ",
+                      BASETYPE_VIA_PUBLIC(type, i) ? "public" : "private",
+                      BASETYPE_VIA_VIRTUAL(type, i) ? " virtual" : "");
+             fputs_filtered (name, stream);
+           }
+         i++;
+         if (i >= n_baseclasses)
+             break;
+         fprintf_filtered (stream, ", ");
+       }
+
+      fprintf_filtered (stream, " ");
+      if (n_baseclasses != 1)
+       break;
+      n_baseclasses = TYPE_N_BASECLASSES (basetype);
+      type = basetype;
+    }
+}
+
+/* Print any asterisks or open-parentheses needed before the
+   variable name (to describe its type).
+
+   On outermost call, pass 0 for PASSED_A_PTR.
+   On outermost call, SHOW > 0 means should ignore
+   any typename for TYPE and show its details.
+   SHOW is always zero on recursive calls.  */
+
+static void
+type_print_varspec_prefix (type, stream, show, passed_a_ptr)
+     struct type *type;
+     FILE *stream;
+     int show;
+     int passed_a_ptr;
+{
+  if (type == 0)
+    return;
+
+  if (TYPE_NAME (type) && show <= 0)
+    return;
+
+  QUIT;
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_PTR:
+      type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+      fprintf_filtered (stream, "*");
+      break;
+
+    case TYPE_CODE_MEMBER:
+      if (passed_a_ptr)
+       fprintf_filtered (stream, "(");
+      type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+                                0);
+      fprintf_filtered (stream, " ");
+      type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0,
+                      passed_a_ptr);
+      fprintf_filtered (stream, "::");
+      break;
+
+    case TYPE_CODE_METHOD:
+      if (passed_a_ptr)
+       fprintf (stream, "(");
+      type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+                                0);
+      fprintf_filtered (stream, " ");
+      type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0,
+                      passed_a_ptr);
+      fprintf_filtered (stream, "::");
+      break;
+
+    case TYPE_CODE_REF:
+      type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+      fprintf_filtered (stream, "&");
+      break;
+
+    case TYPE_CODE_FUNC:
+      type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+                                0);
+      if (passed_a_ptr)
+       fprintf_filtered (stream, "(");
+      break;
+
+    case TYPE_CODE_ARRAY:
+      type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+                                0);
+      if (passed_a_ptr)
+       fprintf_filtered (stream, "(");
+
+    case TYPE_CODE_UNDEF:
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_VOID:
+    case TYPE_CODE_ERROR:
+      /* These types need no prefix.  They are listed here so that
+        gcc -Wall will reveal any types that haven't been handled.  */
+      break;
+    }
+}
+
+/* Print any array sizes, function arguments or close parentheses
+   needed after the variable name (to describe its type).
+   Args work like type_print_varspec_prefix.  */
+
+static void
+type_print_varspec_suffix (type, stream, show, passed_a_ptr)
+     struct type *type;
+     FILE *stream;
+     int show;
+     int passed_a_ptr;
+{
+  if (type == 0)
+    return;
+
+  if (TYPE_NAME (type) && show <= 0)
+    return;
+
+  QUIT;
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_ARRAY:
+      if (passed_a_ptr)
+       fprintf_filtered (stream, ")");
+      
+      fprintf_filtered (stream, "[");
+      if (TYPE_LENGTH (type) >= 0
+         && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+       fprintf_filtered (stream, "%d",
+                         (TYPE_LENGTH (type)
+                          / TYPE_LENGTH (TYPE_TARGET_TYPE (type))));
+      fprintf_filtered (stream, "]");
+      
+      type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+                                0);
+      break;
+
+    case TYPE_CODE_MEMBER:
+      if (passed_a_ptr)
+       fprintf_filtered (stream, ")");
+      type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+      break;
+
+    case TYPE_CODE_METHOD:
+      if (passed_a_ptr)
+       fprintf_filtered (stream, ")");
+      type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+      if (passed_a_ptr)
+       {
+         int i;
+         struct type **args = TYPE_ARG_TYPES (type);
+
+         fprintf_filtered (stream, "(");
+         if (args[1] == 0)
+           fprintf_filtered (stream, "...");
+         else for (i = 1; args[i] != 0 && args[i]->code != TYPE_CODE_VOID; i++)
+           {
+             type_print_1 (args[i], "", stream, -1, 0);
+             if (args[i+1] == 0)
+               fprintf_filtered (stream, "...");
+             else if (args[i+1]->code != TYPE_CODE_VOID)
+               fprintf_filtered (stream, ",");
+           }
+         fprintf_filtered (stream, ")");
+       }
+      break;
+
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_REF:
+      type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+      break;
+
+    case TYPE_CODE_FUNC:
+      type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+                                passed_a_ptr);
+      if (passed_a_ptr)
+       fprintf_filtered (stream, ")");
+      fprintf_filtered (stream, "()");
+      break;
+
+    case TYPE_CODE_UNDEF:
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_VOID:
+    case TYPE_CODE_ERROR:
+      /* These types do not need a suffix.  They are listed so that
+        gcc -Wall will report types that may not have been considered.  */
+      break;
+    }
+}
+
+/* Print the name of the type (or the ultimate pointer target,
+   function value or array element), or the description of a
+   structure or union.
+
+   SHOW nonzero means don't print this type as just its name;
+   show its real definition even if it has a name.
+   SHOW zero means print just typename or struct tag if there is one
+   SHOW negative means abbreviate structure elements.
+   SHOW is decremented for printing of structure elements.
+
+   LEVEL is the depth to indent by.
+   We increase it for some recursive calls.  */
+
+static void
+type_print_base (type, stream, show, level)
+     struct type *type;
+     FILE *stream;
+     int show;
+     int level;
+{
+  char *name;
+  register int i;
+  register int len;
+  register int lastval;
+
+  QUIT;
+
+  if (type == 0)
+    {
+      fprintf_filtered (stream, "type unknown");
+      return;
+    }
+
+  if (TYPE_NAME (type) && show <= 0)
+    {
+      fputs_filtered (TYPE_NAME (type), stream);
+      return;
+    }
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_ARRAY:
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_MEMBER:
+    case TYPE_CODE_REF:
+    case TYPE_CODE_FUNC:
+    case TYPE_CODE_METHOD:
+      type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+      break;
+
+    case TYPE_CODE_STRUCT:
+      fprintf_filtered (stream, "struct ");
+      goto struct_union;
+
+    case TYPE_CODE_UNION:
+      fprintf_filtered (stream, "union ");
+    struct_union:
+      if (name = type_name_no_tag (type))
+       {
+         fputs_filtered (name, stream);
+         fputs_filtered (" ", stream);
+       }
+      if (show < 0)
+       fprintf_filtered (stream, "{...}");
+      else
+       {
+         check_stub_type (type);
+         
+         type_print_derivation_info (stream, type);
+         
+         fprintf_filtered (stream, "{");
+         len = TYPE_NFIELDS (type);
+         if (len)
+           fprintf_filtered (stream, "\n");
+         else
+           {
+             if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+               fprintf_filtered (stream, "<incomplete type>\n");
+             else
+               fprintf_filtered (stream, "<no data fields>\n");
+           }
+
+         /* If there is a base class for this type,
+            do not print the field that it occupies.  */
+         for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+           {
+             QUIT;
+             /* Don't print out virtual function table.  */
+             if ((TYPE_FIELD_NAME (type, i))[5] == CPLUS_MARKER &&
+                 !strncmp (TYPE_FIELD_NAME (type, i), "_vptr", 5))
+               continue;
+
+             print_spaces_filtered (level + 4, stream);
+             if (TYPE_FIELD_STATIC (type, i))
+               {
+                 fprintf_filtered (stream, "static ");
+               }
+             type_print_1 (TYPE_FIELD_TYPE (type, i),
+                           TYPE_FIELD_NAME (type, i),
+                           stream, show - 1, level + 4);
+             if (!TYPE_FIELD_STATIC (type, i)
+                 && TYPE_FIELD_PACKED (type, i))
+               {
+                 /* It is a bitfield.  This code does not attempt
+                    to look at the bitpos and reconstruct filler,
+                    unnamed fields.  This would lead to misleading
+                    results if the compiler does not put out fields
+                    for such things (I don't know what it does).  */
+                 fprintf_filtered (stream, " : %d",
+                                   TYPE_FIELD_BITSIZE (type, i));
+               }
+             fprintf_filtered (stream, ";\n");
+           }
+
+         /* C++: print out the methods */
+         len = TYPE_NFN_FIELDS (type);
+         if (len) fprintf_filtered (stream, "\n");
+         for (i = 0; i < len; i++)
+           {
+             struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+             int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
+
+             for (j = 0; j < len2; j++)
+               {
+                 QUIT;
+                 print_spaces_filtered (level + 4, stream);
+                 if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+                   fprintf_filtered (stream, "virtual ");
+                 else if (TYPE_FN_FIELD_STATIC_P (f, j))
+                   fprintf_filtered (stream, "static ");
+                 type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), "", stream, 0);
+                 if (TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) & TYPE_FLAG_STUB)
+                   {
+                     /* Build something we can demangle.  */
+                     char *strchr (), *gdb_mangle_typename ();
+                     char *inner_name = gdb_mangle_typename (type);
+                     char *mangled_name
+                       = (char *)xmalloc (strlen (TYPE_FN_FIELDLIST_NAME (type, i))
+                                         + strlen (inner_name)
+                                         + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
+                                         + 1);
+                     char *demangled_name, *cplus_demangle ();
+                     strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
+                     strcat (mangled_name, inner_name);
+                     strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
+                     demangled_name = cplus_demangle (mangled_name, 1);
+                     if (demangled_name == 0)
+                       fprintf_filtered (stream, " <badly mangled name %s>",
+                           mangled_name);
+                     else 
+                       {
+                         fprintf_filtered (stream, " %s",
+                             strchr (demangled_name, ':') + 2);
+                         free (demangled_name);
+                       }
+                     free (mangled_name);
+                   }
+                 else if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+                       && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER)
+                   type_print_method_args
+                     (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+                      TYPE_FN_FIELDLIST_NAME (type, i), 0, stream);
+                 else
+                   type_print_method_args
+                     (TYPE_FN_FIELD_ARGS (f, j), "",
+                      TYPE_FN_FIELDLIST_NAME (type, i),
+                      TYPE_FN_FIELD_STATIC_P (f, j), stream);
+
+                 fprintf_filtered (stream, ";\n");
+               }
+           }
+
+         print_spaces_filtered (level, stream);
+         fprintf_filtered (stream, "}");
+       }
+      break;
+
+    case TYPE_CODE_ENUM:
+      fprintf_filtered (stream, "enum ");
+      if (name = type_name_no_tag (type))
+       {
+         fputs_filtered (name, stream);
+         fputs_filtered (" ", stream);
+       }
+      if (show < 0)
+       fprintf_filtered (stream, "{...}");
+      else
+       {
+         fprintf_filtered (stream, "{");
+         len = TYPE_NFIELDS (type);
+         lastval = 0;
+         for (i = 0; i < len; i++)
+           {
+             QUIT;
+             if (i) fprintf_filtered (stream, ", ");
+             fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+             if (lastval != TYPE_FIELD_BITPOS (type, i))
+               {
+                 fprintf_filtered (stream, " = %d", TYPE_FIELD_BITPOS (type, i));
+                 lastval = TYPE_FIELD_BITPOS (type, i);
+               }
+             lastval++;
+           }
+         fprintf_filtered (stream, "}");
+       }
+      break;
+
+    case TYPE_CODE_INT:
+      if (TYPE_LENGTH (type) > sizeof (LONGEST))
+       {
+         fprintf_filtered (stream, "<%d bit integer>",
+                           TYPE_LENGTH (type) * TARGET_CHAR_BIT);
+       }
+      else
+       {
+         if (TYPE_UNSIGNED (type))
+           name = unsigned_type_table[TYPE_LENGTH (type)];
+         else
+           name = signed_type_table[TYPE_LENGTH (type)];
+       }
+      fputs_filtered (name, stream);
+      break;
+
+    case TYPE_CODE_FLT:
+      name = float_type_table[TYPE_LENGTH (type)];
+      fputs_filtered (name, stream);
+      break;
+
+    case TYPE_CODE_VOID:
+      fprintf_filtered (stream, "void");
+      break;
+
+    case 0:
+      fprintf_filtered (stream, "struct unknown");
+      break;
+
+    case TYPE_CODE_ERROR:
+      fprintf_filtered (stream, "<unknown type>");
+      break;
+
+    default:
+      error ("Invalid type code in symbol table.");
+    }
+}
+\f
+/* Validate an input or output radix setting, and make sure the user
+   knows what they really did here.  Radix setting is confusing, e.g.
+   setting the input radix to "10" never changes it!  */
+
+static void
+set_input_radix (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  unsigned radix = *(unsigned *)c->var;
+
+  if (from_tty)
+    printf_filtered ("Input radix set to decimal %d, hex %x, octal %o\n",
+       radix, radix, radix);
+}
+
+static void
+set_output_radix (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  unsigned radix = *(unsigned *)c->var;
+
+  if (from_tty)
+    printf_filtered ("Output radix set to decimal %d, hex %x, octal %o\n",
+       radix, radix, radix);
+
+  /* FIXME, we really should be able to validate the setting BEFORE
+     it takes effect.  */
+  switch (radix)
+    {
+    case 16:
+      output_format = 'x';
+      break;
+    case 10:
+      output_format = 0;
+      break;
+    case 8:
+      output_format = 'o';             /* octal */
+      break;
+    default:
+      output_format = 0;
+      error ("Unsupported radix ``decimal %d''; using decimal output",
+             radix);
+    }
+}
+
+/* Both at once */
+static void
+set_radix (arg, from_tty, c)
+     char *arg;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  unsigned radix = *(unsigned *)c->var;
+
+  if (from_tty)
+    printf_filtered ("Radix set to decimal %d, hex %x, octal %o\n",
+       radix, radix, radix);
+
+  input_radix = radix;
+  output_radix = radix;
+
+  set_output_radix (arg, 0, c);
+}
+\f
+void
+_initialize_valprint ()
+{
+  struct cmd_list_element *c;
+
+  add_show_from_set
+    (add_set_cmd ("array-max", class_vars, var_uinteger, (char *)&print_max,
+                 "Set limit on string chars or array elements to print.\n\
+\"set array-max 0\" causes there to be no limit.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("prettyprint", class_support, var_boolean, (char *)&prettyprint,
+                 "Set prettyprinting of structures.",
+                 &setlist),
+     &showlist);
+
+  add_alias_cmd ("pp", "prettyprint", class_support, 1, &setlist);
+
+  add_show_from_set
+    (add_set_cmd ("unionprint", class_support, var_boolean, (char *)&unionprint,
+                 "Set printing of unions interior to structures.",
+                 &setlist),
+     &showlist);
+  
+  add_show_from_set
+    (add_set_cmd ("vtblprint", class_support, var_boolean, (char *)&vtblprint,
+                 "Set printing of C++ virtual function tables.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("arrayprint", class_support, var_boolean, (char *)&arrayprint,
+                 "Set prettyprinting of arrays.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("addressprint", class_support, var_boolean, (char *)&addressprint,
+                 "Set printing of addresses.",
+                 &setlist),
+     &showlist);
+
+#if 0
+  /* The "show radix" cmd isn't good enough to show two separate values.
+     The rest of the code works, but the show part is confusing, so don't
+     let them be set separately 'til we work out "show".  */
+  c = add_set_cmd ("input-radix", class_support, var_uinteger,
+                  (char *)&input_radix,
+                 "Set default input radix for entering numbers.",
+                 &setlist);
+  add_show_from_set (c, &showlist);
+  c->function = set_input_radix;
+
+  c = add_set_cmd ("output-radix", class_support, var_uinteger,
+                  (char *)&output_radix,
+                 "Set default output radix for printing of values.",
+                 &setlist);
+  add_show_from_set (c, &showlist);
+  c->function = set_output_radix;
+#endif 
+
+  c = add_set_cmd ("radix", class_support, var_uinteger,
+                  (char *)&output_radix,
+                 "Set default input and output number radix.",
+                 &setlist);
+  add_show_from_set (c, &showlist);
+  c->function = set_radix;
+
+  /* Give people the defaults which they are used to.  */
+  prettyprint = 0;
+  unionprint = 1;
+  vtblprint = 0;
+  arrayprint = 0;
+  addressprint = 1;
+
+  print_max = 200;
+
+  unsigned_type_table
+    = (char **) xmalloc ((1 + sizeof (unsigned LONGEST)) * sizeof (char *));
+  bzero (unsigned_type_table, (1 + sizeof (unsigned LONGEST)));
+  unsigned_type_table[sizeof (unsigned char)] = "unsigned char";
+  unsigned_type_table[sizeof (unsigned short)] = "unsigned short";
+  unsigned_type_table[sizeof (unsigned long)] = "unsigned long";
+  unsigned_type_table[sizeof (unsigned int)] = "unsigned int";
+#ifdef LONG_LONG
+  unsigned_type_table[sizeof (unsigned long long)] = "unsigned long long";
+#endif
+
+  signed_type_table
+    = (char **) xmalloc ((1 + sizeof (LONGEST)) * sizeof (char *));
+  bzero (signed_type_table, (1 + sizeof (LONGEST)));
+  signed_type_table[sizeof (char)] = "char";
+  signed_type_table[sizeof (short)] = "short";
+  signed_type_table[sizeof (long)] = "long";
+  signed_type_table[sizeof (int)] = "int";
+#ifdef LONG_LONG
+  signed_type_table[sizeof (long long)] = "long long";
+#endif
+
+  float_type_table
+    = (char **) xmalloc ((1 + sizeof (double)) * sizeof (char *));
+  bzero (float_type_table, (1 + sizeof (double)));
+  float_type_table[sizeof (float)] = "float";
+  float_type_table[sizeof (double)] = "double";
+  obstack_begin (&dont_print_obstack, 32 * sizeof (struct type *));
+}
diff --git a/gdb/value.h b/gdb/value.h
new file mode 100644 (file)
index 0000000..e4ac101
--- /dev/null
@@ -0,0 +1,289 @@
+/* Definitions for values of C expressions, for GDB.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (VALUE_H)
+#define VALUE_H 1
+/*
+ * The structure which defines the type of a value.  It should never
+ * be possible for a program lval value to survive over a call to the inferior
+ * (ie to be put into the history list or an internal variable).
+ */
+enum lval_type {
+  /* Not an lval.  */
+  not_lval,
+  /* In memory.  Could be a saved register.  */
+  lval_memory,
+  /* In a register.  */
+  lval_register,
+  /* In a gdb internal variable.  */
+  lval_internalvar,
+  /* Part of a gdb internal variable (structure field).  */
+  lval_internalvar_component,
+  /* In a register series in a frame not the current one, which may have been
+     partially saved or saved in different places (otherwise would be
+     lval_register or lval_memory).  */
+  lval_reg_frame_relative,
+};
+
+struct value
+  {
+    /* Type of value; either not an lval, or one of the various
+       different possible kinds of lval.  */
+    enum lval_type lval;
+    /* Location of value (if lval).  */
+    union
+      {
+       /* Address in inferior or byte of registers structure.  */
+       CORE_ADDR address;
+       /* Pointer to interrnal variable.  */
+       struct internalvar *internalvar;
+       /* Number of register.  Only used with
+          lval_reg_frame_relative.  */
+       int regnum;
+      } location;
+    /* Describes offset of a value within lval a structure in bytes.  */
+    int offset;        
+    /* Only used for bitfields; number of bits contained in them.  */
+    int bitsize;
+    /* Only used for bitfields; position of start of field.  */
+    int bitpos;
+    /* Frame value is relative to.  In practice, this address is only
+       used if the value is stored in several registers in other than
+       the current frame, and these registers have not all been saved
+       at the same place in memory.  This will be described in the
+       lval enum above as "lval_reg_frame_relative".  */
+    CORE_ADDR frame_addr;
+    /* Type of the value.  */
+    struct type *type;
+    /* Values are stored in a chain, so that they can be deleted
+       easily over calls to the inferior.  Values assigned to internal
+       variables or put into the value history are taken off this
+       list.  */
+    struct value *next;
+    /* If an lval is forced to repeat, a new value is created with
+       these fields set.  The new value is not an lval.  */
+    short repeated;
+    short repetitions;
+    /* Register number if the value is from a register.  Is not kept
+       if you take a field of a structure that is stored in a
+       register.  Shouldn't it be?  */
+    short regno;
+    /* If zero, contents of this value are in the contents field.
+       If nonzero, contents are in inferior memory at address
+       in the location.address field plus the offset field
+       (and the lval field should be lval_memory).  */
+    char lazy;
+    /* If nonzero, this is the value of a variable which does not
+       actually exist in the program.  */
+    char optimized_out;
+    /* Actual contents of the value.  For use of this value; setting
+       it uses the stuff above.  Not valid if lazy is nonzero.
+       Target byte-order.  We force it to be aligned properly for any
+       possible value.  */
+    union {
+      long contents[1];
+      double force_double_align;
+#ifdef LONG_LONG
+      long long force_longlong_align;
+#endif
+    } aligner;
+
+  };
+
+typedef struct value *value;
+
+#define VALUE_TYPE(val) (val)->type
+#define VALUE_LAZY(val) (val)->lazy
+/* VALUE_CONTENTS and VALUE_CONTENTS_RAW both return the address of
+   the gdb buffer used to hold a copy of the contents of the lval.  
+   VALUE_CONTENTS is used when the contents of the buffer are needed --
+   it uses value_fetch_lazy() to load the buffer from the process being 
+   debugged if it hasn't already been loaded.  VALUE_CONTENTS_RAW is 
+   used when data is being stored into the buffer, or when it is 
+   certain that the contents of the buffer are valid.  */
+#define VALUE_CONTENTS_RAW(val) ((char *) (val)->aligner.contents)
+#define VALUE_CONTENTS(val) ((void)(VALUE_LAZY(val) && value_fetch_lazy(val)),\
+                            VALUE_CONTENTS_RAW(val))
+extern int value_fetch_lazy ();
+#define VALUE_LVAL(val) (val)->lval
+#define VALUE_ADDRESS(val) (val)->location.address
+#define VALUE_INTERNALVAR(val) (val)->location.internalvar
+#define VALUE_FRAME_REGNUM(val) ((val)->location.regnum)
+#define VALUE_FRAME(val) ((val)->frame_addr)
+#define VALUE_OFFSET(val) (val)->offset
+#define VALUE_BITSIZE(val) (val)->bitsize
+#define VALUE_BITPOS(val) (val)->bitpos
+#define VALUE_NEXT(val) (val)->next
+#define VALUE_REPEATED(val) (val)->repeated
+#define VALUE_REPETITIONS(val) (val)->repetitions
+#define VALUE_REGNO(val) (val)->regno
+#define VALUE_OPTIMIZED_OUT(val) ((val)->optimized_out)
+
+/* Convert a REF to the object referenced. */
+
+#define COERCE_REF(arg)    \
+{ if (TYPE_CODE ( VALUE_TYPE (arg)) == TYPE_CODE_REF)                  \
+    arg = value_at_lazy (TYPE_TARGET_TYPE (VALUE_TYPE (arg)),          \
+                        unpack_long (VALUE_TYPE (arg),                 \
+                                     VALUE_CONTENTS (arg)));}
+
+/* If ARG is an array, convert it to a pointer.
+   If ARG is an enum, convert it to an integer.
+   If ARG is a function, convert it to a function pointer.
+
+   References are dereferenced.  */
+
+#define COERCE_ARRAY(arg)    \
+{ COERCE_REF(arg);                                                     \
+  if (VALUE_REPEATED (arg)                                             \
+      || TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY)              \
+    arg = value_coerce_array (arg);                                    \
+  if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_FUNC)                   \
+    arg = value_coerce_function (arg);                                  \
+  if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM)                  \
+    arg = value_cast (builtin_type_unsigned_int, arg);                 \
+}
+
+/* If ARG is an enum, convert it to an integer.  */
+
+#define COERCE_ENUM(arg)    \
+{ if (TYPE_CODE ( VALUE_TYPE (arg)) == TYPE_CODE_REF)                  \
+    arg = value_ind (arg);                                             \
+  if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM)                  \
+    arg = value_cast (builtin_type_unsigned_int, arg);                 \
+}
+
+/* Internal variables (variables for convenience of use of debugger)
+   are recorded as a chain of these structures.  */
+
+struct internalvar
+{
+  struct internalvar *next;
+  char *name;
+  value value;
+};
+\f
+#include "symtab.h"
+LONGEST value_as_long ();
+double value_as_double ();
+LONGEST unpack_long ();
+double unpack_double ();
+long unpack_field_as_long ();
+value value_from_long ();
+value value_from_double ();
+value value_at ();
+value value_at_lazy ();
+value value_from_register ();
+value value_of_variable ();
+value value_of_register ();
+value read_var_value ();
+value locate_var_value ();
+value allocate_value ();
+value allocate_repeat_value ();
+value value_string ();
+
+value value_binop ();
+value value_add ();
+value value_sub ();
+value value_coerce_array ();
+value value_coerce_function ();
+value value_ind ();
+value value_addr ();
+value value_assign ();
+value value_neg ();
+value value_lognot ();
+value value_struct_elt (), value_struct_elt_for_address ();
+value value_field (), value_primitive_field ();
+value value_cast ();
+value value_zero ();
+value value_repeat ();
+value value_subscript ();
+
+value value_being_returned ();
+int using_struct_return ();
+void set_return_value ();
+
+value evaluate_expression ();
+value evaluate_type ();
+value parse_and_eval ();
+value parse_to_comma_and_eval ();
+extern CORE_ADDR parse_and_eval_address ();
+extern CORE_ADDR parse_and_eval_address_1 ();
+
+value access_value_history ();
+value value_of_internalvar ();
+void set_internalvar ();
+void set_internalvar_component ();
+struct internalvar *lookup_internalvar ();
+
+int value_equal ();
+int value_less ();
+int value_zerop ();
+
+/* C++ */
+value value_of_this ();
+value value_static_field ();
+value value_x_binop ();
+value value_x_unop ();
+value value_fn_field ();
+value value_virtual_fn_field ();
+value value_static_field ();
+int binop_user_defined_p ();
+int unop_user_defined_p ();
+int typecmp ();
+int fill_in_vptr_fieldno ();
+int destructor_name_p ();
+
+#define value_free(val) free (val)
+void free_all_values ();
+void release_value ();
+int record_latest_value ();
+
+void registers_changed ();
+void read_register_bytes ();
+void write_register_bytes ();
+void read_register_gen ();
+CORE_ADDR read_register ();
+void write_register ();
+void supply_register ();
+void get_saved_register ();
+
+void modify_field ();
+void type_print ();
+void type_print_1 ();
+
+/* Possibilities for prettyprint parameters to routines which print
+   things.  */
+enum val_prettyprint {
+  Val_no_prettyprint = 0,
+  Val_prettyprint,
+  /* Use the default setting which the user has specified.  */
+  Val_pretty_default
+  };
+
+char *baseclass_addr ();
+void print_floating ();
+int value_print ();
+int val_print ();
+void print_variable_value ();
+char *internalvar_name ();
+void clear_value_history ();
+void clear_internalvars ();
+
+#endif /* value.h not already included.  */
diff --git a/gdb/values.c b/gdb/values.c
new file mode 100644 (file)
index 0000000..39ec8ea
--- /dev/null
@@ -0,0 +1,1337 @@
+/* Low level packing and unpacking of values for GDB.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "command.h"
+
+/* The value-history records all the values printed
+   by print commands during this session.  Each chunk
+   records 60 consecutive values.  The first chunk on
+   the chain records the most recent values.
+   The total number of values is in value_history_count.  */
+
+#define VALUE_HISTORY_CHUNK 60
+
+struct value_history_chunk
+{
+  struct value_history_chunk *next;
+  value values[VALUE_HISTORY_CHUNK];
+};
+
+/* Chain of chunks now in use.  */
+
+static struct value_history_chunk *value_history_chain;
+
+static int value_history_count;        /* Abs number of last entry stored */
+
+\f
+/* List of all value objects currently allocated
+   (except for those released by calls to release_value)
+   This is so they can be freed after each command.  */
+
+static value all_values;
+
+/* Allocate a  value  that has the correct length for type TYPE.  */
+
+value
+allocate_value (type)
+     struct type *type;
+{
+  register value val;
+
+  check_stub_type (type);
+
+  val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type));
+  VALUE_NEXT (val) = all_values;
+  all_values = val;
+  VALUE_TYPE (val) = type;
+  VALUE_LVAL (val) = not_lval;
+  VALUE_ADDRESS (val) = 0;
+  VALUE_FRAME (val) = 0;
+  VALUE_OFFSET (val) = 0;
+  VALUE_BITPOS (val) = 0;
+  VALUE_BITSIZE (val) = 0;
+  VALUE_REPEATED (val) = 0;
+  VALUE_REPETITIONS (val) = 0;
+  VALUE_REGNO (val) = -1;
+  VALUE_LAZY (val) = 0;
+  VALUE_OPTIMIZED_OUT (val) = 0;
+  return val;
+}
+
+/* Allocate a  value  that has the correct length
+   for COUNT repetitions type TYPE.  */
+
+value
+allocate_repeat_value (type, count)
+     struct type *type;
+     int count;
+{
+  register value val;
+
+  val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count);
+  VALUE_NEXT (val) = all_values;
+  all_values = val;
+  VALUE_TYPE (val) = type;
+  VALUE_LVAL (val) = not_lval;
+  VALUE_ADDRESS (val) = 0;
+  VALUE_FRAME (val) = 0;
+  VALUE_OFFSET (val) = 0;
+  VALUE_BITPOS (val) = 0;
+  VALUE_BITSIZE (val) = 0;
+  VALUE_REPEATED (val) = 1;
+  VALUE_REPETITIONS (val) = count;
+  VALUE_REGNO (val) = -1;
+  VALUE_LAZY (val) = 0;
+  VALUE_OPTIMIZED_OUT (val) = 0;
+  return val;
+}
+
+/* Free all the values that have been allocated (except for those released).
+   Called after each command, successful or not.  */
+
+void
+free_all_values ()
+{
+  register value val, next;
+
+  for (val = all_values; val; val = next)
+    {
+      next = VALUE_NEXT (val);
+      value_free (val);
+    }
+
+  all_values = 0;
+}
+
+/* Remove VAL from the chain all_values
+   so it will not be freed automatically.  */
+
+void
+release_value (val)
+     register value val;
+{
+  register value v;
+
+  if (all_values == val)
+    {
+      all_values = val->next;
+      return;
+    }
+
+  for (v = all_values; v; v = v->next)
+    {
+      if (v->next == val)
+       {
+         v->next = val->next;
+         break;
+       }
+    }
+}
+
+/* Return a copy of the value ARG.
+   It contains the same contents, for same memory address,
+   but it's a different block of storage.  */
+
+static value
+value_copy (arg)
+     value arg;
+{
+  register value val;
+  register struct type *type = VALUE_TYPE (arg);
+  if (VALUE_REPEATED (arg))
+    val = allocate_repeat_value (type, VALUE_REPETITIONS (arg));
+  else
+    val = allocate_value (type);
+  VALUE_LVAL (val) = VALUE_LVAL (arg);
+  VALUE_ADDRESS (val) = VALUE_ADDRESS (arg);
+  VALUE_OFFSET (val) = VALUE_OFFSET (arg);
+  VALUE_BITPOS (val) = VALUE_BITPOS (arg);
+  VALUE_BITSIZE (val) = VALUE_BITSIZE (arg);
+  VALUE_REGNO (val) = VALUE_REGNO (arg);
+  VALUE_LAZY (val) = VALUE_LAZY (arg);
+  if (!VALUE_LAZY (val))
+    {
+      bcopy (VALUE_CONTENTS_RAW (arg), VALUE_CONTENTS_RAW (val),
+            TYPE_LENGTH (VALUE_TYPE (arg))
+            * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
+    }
+  return val;
+}
+\f
+/* Access to the value history.  */
+
+/* Record a new value in the value history.
+   Returns the absolute history index of the entry.
+   Result of -1 indicates the value was not saved; otherwise it is the
+   value history index of this new item.  */
+
+int
+record_latest_value (val)
+     value val;
+{
+  int i;
+
+  /* Check error now if about to store an invalid float.  We return -1
+     to the caller, but allow them to continue, e.g. to print it as "Nan". */
+  if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) {
+    (void) unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i);
+    if (i) return -1;          /* Indicate value not saved in history */
+  }
+
+  /* Here we treat value_history_count as origin-zero
+     and applying to the value being stored now.  */
+
+  i = value_history_count % VALUE_HISTORY_CHUNK;
+  if (i == 0)
+    {
+      register struct value_history_chunk *new
+       = (struct value_history_chunk *)
+         xmalloc (sizeof (struct value_history_chunk));
+      bzero (new->values, sizeof new->values);
+      new->next = value_history_chain;
+      value_history_chain = new;
+    }
+
+  value_history_chain->values[i] = val;
+  release_value (val);
+
+  /* Now we regard value_history_count as origin-one
+     and applying to the value just stored.  */
+
+  return ++value_history_count;
+}
+
+/* Return a copy of the value in the history with sequence number NUM.  */
+
+value
+access_value_history (num)
+     int num;
+{
+  register struct value_history_chunk *chunk;
+  register int i;
+  register int absnum = num;
+
+  if (absnum <= 0)
+    absnum += value_history_count;
+
+  if (absnum <= 0)
+    {
+      if (num == 0)
+       error ("The history is empty.");
+      else if (num == 1)
+       error ("There is only one value in the history.");
+      else
+       error ("History does not go back to $$%d.", -num);
+    }
+  if (absnum > value_history_count)
+    error ("History has not yet reached $%d.", absnum);
+
+  absnum--;
+
+  /* Now absnum is always absolute and origin zero.  */
+
+  chunk = value_history_chain;
+  for (i = (value_history_count - 1) / VALUE_HISTORY_CHUNK - absnum / VALUE_HISTORY_CHUNK;
+       i > 0; i--)
+    chunk = chunk->next;
+
+  return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]);
+}
+
+/* Clear the value history entirely.
+   Must be done when new symbol tables are loaded,
+   because the type pointers become invalid.  */
+
+void
+clear_value_history ()
+{
+  register struct value_history_chunk *next;
+  register int i;
+  register value val;
+
+  while (value_history_chain)
+    {
+      for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
+       if (val = value_history_chain->values[i])
+         free (val);
+      next = value_history_chain->next;
+      free (value_history_chain);
+      value_history_chain = next;
+    }
+  value_history_count = 0;
+}
+
+static void
+value_history_info (num_exp, from_tty)
+     char *num_exp;
+     int from_tty;
+{
+  register int i;
+  register value val;
+  static int num = 1;
+
+  if (num_exp)
+    {
+      if (num_exp[0] == '+' && num_exp[1] == '\0')
+       /* "info history +" should print from the stored position.  */
+       ;
+      else
+       /* "info history <exp>" should print around value number <exp>.  */
+       num = parse_and_eval_address (num_exp) - 5;
+    }
+  else
+    {
+      /* "info history" means print the last 10 values.  */
+      num = value_history_count - 9;
+    }
+
+  if (num <= 0)
+    num = 1;
+
+  for (i = num; i < num + 10 && i <= value_history_count; i++)
+    {
+      val = access_value_history (i);
+      printf_filtered ("$%d = ", i);
+      value_print (val, stdout, 0, Val_pretty_default);
+      printf_filtered ("\n");
+    }
+
+  /* The next "info history +" should start after what we just printed.  */
+  num += 10;
+
+  /* Hitting just return after this command should do the same thing as
+     "info history +".  If num_exp is null, this is unnecessary, since
+     "info history +" is not useful after "info history".  */
+  if (from_tty && num_exp)
+    {
+      num_exp[0] = '+';
+      num_exp[1] = '\0';
+    }
+}
+\f
+/* Internal variables.  These are variables within the debugger
+   that hold values assigned by debugger commands.
+   The user refers to them with a '$' prefix
+   that does not appear in the variable names stored internally.  */
+
+static struct internalvar *internalvars;
+
+/* Look up an internal variable with name NAME.  NAME should not
+   normally include a dollar sign.
+
+   If the specified internal variable does not exist,
+   one is created, with a void value.  */
+
+struct internalvar *
+lookup_internalvar (name)
+     char *name;
+{
+  register struct internalvar *var;
+
+  for (var = internalvars; var; var = var->next)
+    if (!strcmp (var->name, name))
+      return var;
+
+  var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
+  var->name = concat (name, "", "");
+  var->value = allocate_value (builtin_type_void);
+  release_value (var->value);
+  var->next = internalvars;
+  internalvars = var;
+  return var;
+}
+
+value
+value_of_internalvar (var)
+     struct internalvar *var;
+{
+  register value val;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+  if (IS_TRAPPED_INTERNALVAR (var->name))
+    return VALUE_OF_TRAPPED_INTERNALVAR (var);
+#endif 
+
+  val = value_copy (var->value);
+  if (VALUE_LAZY (val))
+    value_fetch_lazy (val);
+  VALUE_LVAL (val) = lval_internalvar;
+  VALUE_INTERNALVAR (val) = var;
+  return val;
+}
+
+void
+set_internalvar_component (var, offset, bitpos, bitsize, newval)
+     struct internalvar *var;
+     int offset, bitpos, bitsize;
+     value newval;
+{
+  register char *addr = VALUE_CONTENTS (var->value) + offset;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+  if (IS_TRAPPED_INTERNALVAR (var->name))
+    SET_TRAPPED_INTERNALVAR (var, newval, bitpos, bitsize, offset);
+#endif
+
+  if (bitsize)
+    modify_field (addr, (int) value_as_long (newval),
+                 bitpos, bitsize);
+  else
+    bcopy (VALUE_CONTENTS (newval), addr,
+          TYPE_LENGTH (VALUE_TYPE (newval)));
+}
+
+void
+set_internalvar (var, val)
+     struct internalvar *var;
+     value val;
+{
+#ifdef IS_TRAPPED_INTERNALVAR
+  if (IS_TRAPPED_INTERNALVAR (var->name))
+    SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0);
+#endif
+
+  free (var->value);
+  var->value = value_copy (val);
+  release_value (var->value);
+}
+
+char *
+internalvar_name (var)
+     struct internalvar *var;
+{
+  return var->name;
+}
+
+/* Free all internalvars.  Done when new symtabs are loaded,
+   because that makes the values invalid.  */
+
+void
+clear_internalvars ()
+{
+  register struct internalvar *var;
+
+  while (internalvars)
+    {
+      var = internalvars;
+      internalvars = var->next;
+      free (var->name);
+      free (var->value);
+      free (var);
+    }
+}
+
+static void
+convenience_info ()
+{
+  register struct internalvar *var;
+  int varseen = 0;
+
+  for (var = internalvars; var; var = var->next)
+    {
+#ifdef IS_TRAPPED_INTERNALVAR
+      if (IS_TRAPPED_INTERNALVAR (var->name))
+       continue;
+#endif
+      if (!varseen)
+       {
+#if 0
+         /* Useless noise.  */
+         printf ("Debugger convenience variables:\n\n");
+#endif
+         varseen = 1;
+       }
+      printf ("$%s = ", var->name);
+      value_print (var->value, stdout, 0, Val_pretty_default);
+      printf ("\n");
+    }
+  if (!varseen)
+    printf ("No debugger convenience variables now defined.\n\
+Convenience variables have names starting with \"$\";\n\
+use \"set\" as in \"set $foo = 5\" to define them.\n");
+}
+\f
+/* Extract a value as a C number (either long or double).
+   Knows how to convert fixed values to double, or
+   floating values to long.
+   Does not deallocate the value.  */
+
+LONGEST
+value_as_long (val)
+     register value val;
+{
+  /* This coerces arrays and functions, which is necessary (e.g.
+     in disassemble_command).  It also dereferences references, which
+     I suspect is the most logical thing to do.  */
+  if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_ENUM)
+    COERCE_ARRAY (val);
+  return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
+}
+
+double
+value_as_double (val)
+     register value val;
+{
+  double foo;
+  int inv;
+  
+  foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv);
+  if (inv)
+    error ("Invalid floating value found in program.");
+  return foo;
+}
+\f
+/* Unpack raw data (copied from debugee, target byte order) at VALADDR
+   as a long, or as a double, assuming the raw data is described
+   by type TYPE.  Knows how to convert different sizes of values
+   and can convert between fixed and floating point.  We don't assume
+   any alignment for the raw data.  Return value is in host byte order.
+
+   If you want functions and arrays to be coerced to pointers, and
+   references to be dereferenced, call value_as_long() instead.
+
+   C++: It is assumed that the front-end has taken care of
+   all matters concerning pointers to members.  A pointer
+   to member which reaches here is considered to be equivalent
+   to an INT (or some size).  After all, it is only an offset.  */
+
+LONGEST
+unpack_long (type, valaddr)
+     struct type *type;
+     char *valaddr;
+{
+  register enum type_code code = TYPE_CODE (type);
+  register int len = TYPE_LENGTH (type);
+  register int nosign = TYPE_UNSIGNED (type);
+
+  if (code == TYPE_CODE_ENUM)
+    code = TYPE_CODE_INT;
+  if (code == TYPE_CODE_FLT)
+    {
+      if (len == sizeof (float))
+       {
+         float retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+      if (len == sizeof (double))
+       {
+         double retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+      else
+       {
+         error ("Unexpected type of floating point number.");
+       }
+    }
+  else if (code == TYPE_CODE_INT && nosign)
+    {
+      if (len == sizeof (char))
+       {
+         unsigned char retval = * (unsigned char *) valaddr;
+         /* SWAP_TARGET_AND_HOST (&retval, sizeof (unsigned char)); */
+         return retval;
+       }
+
+      if (len == sizeof (short))
+       {
+         unsigned short retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+      if (len == sizeof (int))
+       {
+         unsigned int retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+      if (len == sizeof (long))
+       {
+         unsigned long retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+#ifdef LONG_LONG
+      if (len == sizeof (long long))
+       {
+         unsigned long long retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+#endif
+      else
+       {
+         error ("That operation is not possible on an integer of that size.");
+       }
+    }
+  else if (code == TYPE_CODE_INT)
+    {
+      if (len == sizeof (char))
+       {
+         char retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+      if (len == sizeof (short))
+       {
+         short retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+      if (len == sizeof (int))
+       {
+         int retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+      if (len == sizeof (long))
+       {
+         long retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+#ifdef LONG_LONG
+      if (len == sizeof (long long))
+       {
+         long long retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+#endif
+      else
+       {
+         error ("That operation is not possible on an integer of that size.");
+       }
+    }
+  else if (code == TYPE_CODE_PTR
+          || code == TYPE_CODE_REF)
+    {
+      if (len == sizeof (char *))
+       {
+         CORE_ADDR retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+    }
+  else if (code == TYPE_CODE_MEMBER)
+    error ("not implemented: member types in unpack_long");
+
+  error ("Value not integer or pointer.");
+  return 0;    /* For lint -- never reached */
+}
+
+/* Return a double value from the specified type and address.
+   INVP points to an int which is set to 0 for valid value,
+   1 for invalid value (bad float format).  In either case,
+   the returned double is OK to use.  Argument is in target
+   format, result is in host format.  */
+
+double
+unpack_double (type, valaddr, invp)
+     struct type *type;
+     char *valaddr;
+     int *invp;
+{
+  register enum type_code code = TYPE_CODE (type);
+  register int len = TYPE_LENGTH (type);
+  register int nosign = TYPE_UNSIGNED (type);
+
+  *invp = 0;                   /* Assume valid.   */
+  if (code == TYPE_CODE_FLT)
+    {
+      if (INVALID_FLOAT (valaddr, len))
+       {
+         *invp = 1;
+         return 1.234567891011121314;
+       }
+
+      if (len == sizeof (float))
+       {
+         float retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+
+      if (len == sizeof (double))
+       {
+         double retval;
+         bcopy (valaddr, &retval, sizeof (retval));
+         SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+         return retval;
+       }
+      else
+       {
+         error ("Unexpected type of floating point number.");
+       }
+    }
+  else if (nosign) {
+   /* Unsigned -- be sure we compensate for signed LONGEST.  */
+#ifdef LONG_LONG
+   return (unsigned long long) unpack_long (type, valaddr);
+#else
+   return (unsigned long     ) unpack_long (type, valaddr);
+#endif
+  } else {
+    /* Signed -- we are OK with unpack_long.  */
+    return unpack_long (type, valaddr);
+  }
+}
+\f
+/* Given a value ARG1 (offset by OFFSET bytes)
+   of a struct or union type ARG_TYPE,
+   extract and return the value of one of its fields.
+   FIELDNO says which field.
+
+   For C++, must also be able to return values from static fields */
+
+value
+value_primitive_field (arg1, offset, fieldno, arg_type)
+     register value arg1;
+     int offset;
+     register int fieldno;
+     register struct type *arg_type;
+{
+  register value v;
+  register struct type *type;
+
+  check_stub_type (arg_type);
+  type = TYPE_FIELD_TYPE (arg_type, fieldno);
+
+  /* Handle packed fields */
+
+  offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+  if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
+    {
+      v = value_from_long (type,
+                          unpack_field_as_long (arg_type,
+                                                VALUE_CONTENTS (arg1),
+                                                fieldno));
+      VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
+      VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+    }
+  else
+    {
+      v = allocate_value (type);
+      if (VALUE_LAZY (arg1))
+       VALUE_LAZY (v) = 1;
+      else
+       bcopy (VALUE_CONTENTS_RAW (arg1) + offset,
+              VALUE_CONTENTS_RAW (v),
+              TYPE_LENGTH (type));
+    }
+  VALUE_LVAL (v) = VALUE_LVAL (arg1);
+  if (VALUE_LVAL (arg1) == lval_internalvar)
+    VALUE_LVAL (v) = lval_internalvar_component;
+  VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
+  VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1);
+  return v;
+}
+
+/* Given a value ARG1 of a struct or union type,
+   extract and return the value of one of its fields.
+   FIELDNO says which field.
+
+   For C++, must also be able to return values from static fields */
+
+value
+value_field (arg1, fieldno)
+     register value arg1;
+     register int fieldno;
+{
+  return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
+}
+
+value
+value_fn_field (arg1, fieldno, subfieldno)
+     register value arg1;
+     register int fieldno;
+     int subfieldno;
+{
+  register value v;
+  struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno);
+  register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno);
+  struct symbol *sym;
+
+  sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno),
+                      0, VAR_NAMESPACE, 0, NULL);
+  if (! sym) error ("Internal error: could not find physical method named %s",
+                   TYPE_FN_FIELD_PHYSNAME (f, subfieldno));
+  
+  v = allocate_value (type);
+  VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+  VALUE_TYPE (v) = type;
+  return v;
+}
+
+/* Return a virtual function as a value.
+   ARG1 is the object which provides the virtual function
+   table pointer.  ARG1 is side-effected in calling this function.
+   F is the list of member functions which contains the desired virtual
+   function.
+   J is an index into F which provides the desired virtual function.  */
+value
+value_virtual_fn_field (arg1, f, j)
+     value arg1;
+     struct fn_field *f;
+     int j;
+{
+  /* First, get the virtual function table pointer.  That comes
+     with a strange type, so cast it to type `pointer to long' (which
+     should serve just fine as a function type).  Then, index into
+     the table, and convert final value to appropriate function type.  */
+  value entry, vfn, vtbl;
+  value vi = value_from_long (builtin_type_int, 
+                             (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+  struct type *context = lookup_pointer_type (TYPE_FN_FIELD_FCONTEXT (f, j));
+  if (TYPE_TARGET_TYPE (context) != VALUE_TYPE (arg1))
+    arg1 = value_ind (value_cast (context, value_addr (arg1)));
+
+  context = VALUE_TYPE (arg1);
+
+  /* This type may have been defined before its virtual function table
+     was.  If so, fill in the virtual function table entry for the
+     type now.  */
+  if (TYPE_VPTR_FIELDNO (context) < 0)
+    TYPE_VPTR_FIELDNO (context)
+      = fill_in_vptr_fieldno (context);
+
+  /* The virtual function table is now an array of structures
+     which have the form { int16 offset, delta; void *pfn; }.  */
+  vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (context)));
+
+  /* Index into the virtual function table.  This is hard-coded because
+     looking up a field is not cheap, and it may be important to save
+     time, e.g. if the user has set a conditional breakpoint calling
+     a virtual function.  */
+  entry = value_subscript (vtbl, vi);
+
+  /* Move the `this' pointer according to the virtual function table.  */
+  VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
+  if (! VALUE_LAZY (arg1))
+    {
+      VALUE_LAZY (arg1) = 1;
+      value_fetch_lazy (arg1);
+    }
+
+  vfn = value_field (entry, 2);
+  /* Reinstantiate the function pointer with the correct type.  */
+  VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+
+  return vfn;
+}
+
+/* The value of a static class member does not depend
+   on its instance, only on its type.  If FIELDNO >= 0,
+   then fieldno is a valid field number and is used directly.
+   Otherwise, FIELDNAME is the name of the field we are
+   searching for.  If it is not a static field name, an
+   error is signaled.  TYPE is the type in which we look for the
+   static field member.  */
+value
+value_static_field (type, fieldname, fieldno)
+     register struct type *type;
+     char *fieldname;
+     register int fieldno;
+{
+  register value v;
+  struct symbol *sym;
+  char *phys_name;
+
+  if (fieldno < 0)
+    {
+      register struct type *t = type;
+      /* Look for static field.  */
+      while (t)
+       {
+         int i;
+         for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
+           if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
+             {
+               if (TYPE_FIELD_STATIC (t, i))
+                 {
+                   fieldno = i;
+                   goto found;
+                 }
+               else
+                 error ("field `%s' is not static");
+             }
+         /* FIXME: this does not recursively check multiple baseclasses.  */
+         t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0;
+       }
+
+      t = type;
+
+      if (destructor_name_p (fieldname, t))
+       error ("Cannot get value of destructor");
+
+      while (t)
+       {
+         int i;
+
+         for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
+           {
+             if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname))
+               {
+                 error ("Cannot get value of method \"%s\"", fieldname);
+               }
+           }
+         t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0;
+       }
+      error("there is no field named %s", fieldname);
+    }
+
+ found:
+  phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
+  sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+  if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name);
+
+  type = TYPE_FIELD_TYPE (type, fieldno);
+  v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+  return v;
+}
+
+/* Compute the address of the baseclass which is
+   the INDEXth baseclass of TYPE.  The TYPE base
+   of the object is at VALADDR.  */
+
+char *
+baseclass_addr (type, index, valaddr, valuep)
+     struct type *type;
+     int index;
+     char *valaddr;
+     value *valuep;
+{
+  struct type *basetype = TYPE_BASECLASS (type, index);
+
+  if (BASETYPE_VIA_VIRTUAL (type, index))
+    {
+      /* Must hunt for the pointer to this virtual baseclass.  */
+      register int i, len = TYPE_NFIELDS (type);
+      register int n_baseclasses = TYPE_N_BASECLASSES (type);
+      char *vbase_name, *type_name = type_name_no_tag (basetype);
+
+      if (TYPE_MAIN_VARIANT (basetype))
+       basetype = TYPE_MAIN_VARIANT (basetype);
+
+      vbase_name = (char *)alloca (strlen (type_name) + 8);
+      sprintf (vbase_name, "_vb$%s", type_name);
+      /* First look for the virtual baseclass pointer
+        in the fields.  */
+      for (i = n_baseclasses; i < len; i++)
+       {
+         if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i)))
+           {
+             value v = value_at (basetype,
+                                 unpack_long (TYPE_FIELD_TYPE (type, i),
+                                              valaddr + (TYPE_FIELD_BITPOS (type, i) / 8)));
+             if (valuep)
+               *valuep = v;
+             return (char *) VALUE_CONTENTS (v);
+           }
+       }
+      /* Not in the fields, so try looking through the baseclasses.  */
+      for (i = index+1; i < n_baseclasses; i++)
+       {
+         char *baddr;
+
+         baddr = baseclass_addr (type, i, valaddr, valuep);
+         if (baddr)
+           return baddr;
+       }
+      /* Not found.  */
+      if (valuep)
+       *valuep = 0;
+      return 0;
+    }
+
+  /* Baseclass is easily computed.  */
+  if (valuep)
+    *valuep = 0;
+  return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
+}
+
+/* Ugly hack to convert method stubs into method types.
+
+   He ain't kiddin'.  This demangles the name of the method into a string
+   including argument types, parses out each argument type, generates
+   a string casting a zero to that type, evaluates the string, and stuffs
+   the resulting type into an argtype vector!!!  Then it knows the type
+   of the whole function (including argument types for overloading),
+   which info used to be in the stab's but was removed to hack back
+   the space required for them.  */
+void
+check_stub_method (type, i, j)
+     struct type *type;
+     int i, j;
+{
+  extern char *gdb_mangle_typename (), *strchr ();
+  struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+  char *inner_name = gdb_mangle_typename (type);
+  char *mangled_name
+    = (char *)xmalloc (strlen (TYPE_FN_FIELDLIST_NAME (type, i))
+                      + strlen (inner_name)
+                      + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
+                      + 1);
+  char *demangled_name, *cplus_demangle ();
+  char *argtypetext, *p;
+  int depth = 0, argcount = 1;
+  struct type **argtypes;
+
+  strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
+  strcat (mangled_name, inner_name);
+  strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
+  demangled_name = cplus_demangle (mangled_name, 0);
+
+  /* Now, read in the parameters that define this type.  */
+  argtypetext = strchr (demangled_name, '(') + 1;
+  p = argtypetext;
+  while (*p)
+    {
+      if (*p == '(')
+       depth += 1;
+      else if (*p == ')')
+       depth -= 1;
+      else if (*p == ',' && depth == 0)
+       argcount += 1;
+
+      p += 1;
+    }
+  /* We need one more slot for the void [...] or NULL [end of arglist] */
+  argtypes = (struct type **)xmalloc ((argcount+1) * sizeof (struct type *));
+  p = argtypetext;
+  argtypes[0] = lookup_pointer_type (type);
+  argcount = 1;
+
+  if (*p != ')')                       /* () means no args, skip while */
+    {
+      while (*p)
+       {
+         if (*p == '(')
+           depth += 1;
+         else if (*p == ')')
+           depth -= 1;
+
+         if (depth <= 0 && (*p == ',' || *p == ')'))
+           {
+             char *tmp = (char *)alloca (p - argtypetext + 4);
+             value val;
+             tmp[0] = '(';
+             bcopy (argtypetext, tmp+1, p - argtypetext);
+             tmp[p-argtypetext+1] = ')';
+             tmp[p-argtypetext+2] = '0';
+             tmp[p-argtypetext+3] = '\0';
+             val = parse_and_eval (tmp);
+             argtypes[argcount] = VALUE_TYPE (val);
+             argcount += 1;
+             argtypetext = p + 1;
+           }
+         p += 1;
+       }
+    }
+
+  if (p[-2] != '.')                    /* ... */
+    argtypes[argcount] = builtin_type_void;    /* Ellist terminator */
+  else
+    argtypes[argcount] = NULL;         /* List terminator */
+
+  free (demangled_name);
+  smash_to_method_type (TYPE_FN_FIELD_TYPE (f, j), type,
+                       TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
+                       argtypes);
+  TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
+  TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) &= ~TYPE_FLAG_STUB;
+}
+\f
+long
+unpack_field_as_long (type, valaddr, fieldno)
+     struct type *type;
+     char *valaddr;
+     int fieldno;
+{
+  long val;
+  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+  int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+
+  bcopy (valaddr + bitpos / 8, &val, sizeof val);
+  SWAP_TARGET_AND_HOST (&val, sizeof val);
+
+  /* Extracting bits depends on endianness of the machine.  */
+#ifdef BITS_BIG_ENDIAN
+  val = val >> (sizeof val * 8 - bitpos % 8 - bitsize);
+#else
+  val = val >> (bitpos % 8);
+#endif
+
+  val &= (1 << bitsize) - 1;
+  return val;
+}
+
+void
+modify_field (addr, fieldval, bitpos, bitsize)
+     char *addr;
+     int fieldval;
+     int bitpos, bitsize;
+{
+  long oword;
+
+  /* Reject values too big to fit in the field in question.
+     Otherwise adjoining fields may be corrupted.  */
+  if (fieldval & ~((1<<bitsize)-1))
+    error ("Value %d does not fit in %d bits.", fieldval, bitsize);
+  
+  bcopy (addr, &oword, sizeof oword);
+
+  /* Shifting for bit field depends on endianness of the machine.  */
+#ifdef BITS_BIG_ENDIAN
+  bitpos = sizeof (oword) * 8 - bitpos - bitsize;
+#endif
+
+  oword &= ~(((1 << bitsize) - 1) << bitpos);
+  oword |= fieldval << bitpos;
+  bcopy (&oword, addr, sizeof oword);
+}
+\f
+/* Convert C numbers into newly allocated values */
+
+value
+value_from_long (type, num)
+     struct type *type;
+     register LONGEST num;
+{
+  register value val = allocate_value (type);
+  register enum type_code code = TYPE_CODE (type);
+  register int len = TYPE_LENGTH (type);
+
+  if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM)
+    {
+      if (len == sizeof (char))
+       * (char *) VALUE_CONTENTS_RAW (val) = num;
+      else if (len == sizeof (short))
+       * (short *) VALUE_CONTENTS_RAW (val) = num;
+      else if (len == sizeof (int))
+       * (int *) VALUE_CONTENTS_RAW (val) = num;
+      else if (len == sizeof (long))
+       * (long *) VALUE_CONTENTS_RAW (val) = num;
+#ifdef LONG_LONG
+      else if (len == sizeof (long long))
+       * (long long *) VALUE_CONTENTS_RAW (val) = num;
+#endif
+      else
+       error ("Integer type encountered with unexpected data length.");
+    }
+  else
+    error ("Unexpected type encountered for integer constant.");
+
+  /* num was in host byte order.  So now put the value's contents
+     into target byte order.  */
+  SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len);
+
+  return val;
+}
+
+value
+value_from_double (type, num)
+     struct type *type;
+     double num;
+{
+  register value val = allocate_value (type);
+  register enum type_code code = TYPE_CODE (type);
+  register int len = TYPE_LENGTH (type);
+
+  if (code == TYPE_CODE_FLT)
+    {
+      if (len == sizeof (float))
+       * (float *) VALUE_CONTENTS_RAW (val) = num;
+      else if (len == sizeof (double))
+       * (double *) VALUE_CONTENTS_RAW (val) = num;
+      else
+       error ("Floating type encountered with unexpected data length.");
+    }
+  else
+    error ("Unexpected type encountered for floating constant.");
+
+  /* num was in host byte order.  So now put the value's contents
+     into target byte order.  */
+  SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len);
+
+  return val;
+}
+\f
+/* Deal with the value that is "about to be returned".  */
+
+/* Return the value that a function returning now
+   would be returning to its caller, assuming its type is VALTYPE.
+   RETBUF is where we look for what ought to be the contents
+   of the registers (in raw form).  This is because it is often
+   desirable to restore old values to those registers
+   after saving the contents of interest, and then call
+   this function using the saved values.
+   struct_return is non-zero when the function in question is
+   using the structure return conventions on the machine in question;
+   0 when it is using the value returning conventions (this often
+   means returning pointer to where structure is vs. returning value). */
+
+value
+value_being_returned (valtype, retbuf, struct_return)
+     register struct type *valtype;
+     char retbuf[REGISTER_BYTES];
+     int struct_return;
+     /*ARGSUSED*/
+{
+  register value val;
+  CORE_ADDR addr;
+
+#if defined (EXTRACT_STRUCT_VALUE_ADDRESS)
+  /* If this is not defined, just use EXTRACT_RETURN_VALUE instead.  */
+  if (struct_return) {
+    addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
+    if (!addr)
+      error ("Function return value unknown");
+    return value_at (valtype, addr);
+  }
+#endif
+
+  val = allocate_value (valtype);
+  EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
+
+  return val;
+}
+
+/* Should we use EXTRACT_STRUCT_VALUE_ADDRESS instead of
+   EXTRACT_RETURN_VALUE?  GCC_P is true if compiled with gcc
+   and TYPE is the type (which is known to be struct, union or array).
+
+   On most machines, the struct convention is used unless we are
+   using gcc and the type is of a special size.  */
+#if !defined (USE_STRUCT_CONVENTION)
+#define USE_STRUCT_CONVENTION(gcc_p, type)\
+  (!((gcc_p) && (TYPE_LENGTH (value_type) == 1                \
+                || TYPE_LENGTH (value_type) == 2             \
+                || TYPE_LENGTH (value_type) == 4             \
+                || TYPE_LENGTH (value_type) == 8             \
+                )                                            \
+     ))
+#endif
+
+/* Return true if the function specified is using the structure returning
+   convention on this machine to return arguments, or 0 if it is using
+   the value returning convention.  FUNCTION is the value representing
+   the function, FUNCADDR is the address of the function, and VALUE_TYPE
+   is the type returned by the function.  GCC_P is nonzero if compiled
+   with GCC.  */
+
+int
+using_struct_return (function, funcaddr, value_type, gcc_p)
+     value function;
+     CORE_ADDR funcaddr;
+     struct type *value_type;
+     int gcc_p;
+     /*ARGSUSED*/
+{
+  register enum type_code code = TYPE_CODE (value_type);
+
+  if (code == TYPE_CODE_ERROR)
+    error ("Function return type unknown.");
+
+  if (code == TYPE_CODE_STRUCT ||
+      code == TYPE_CODE_UNION ||
+      code == TYPE_CODE_ARRAY)
+    return USE_STRUCT_CONVENTION (gcc_p, value_type);
+
+  return 0;
+}
+
+/* Store VAL so it will be returned if a function returns now.
+   Does not verify that VAL's type matches what the current
+   function wants to return.  */
+
+void
+set_return_value (val)
+     value val;
+{
+  register enum type_code code = TYPE_CODE (VALUE_TYPE (val));
+  double dbuf;
+  LONGEST lbuf;
+
+  if (code == TYPE_CODE_ERROR)
+    error ("Function return type unknown.");
+
+  if (code == TYPE_CODE_STRUCT
+      || code == TYPE_CODE_UNION)
+    error ("Specifying a struct or union return value is not supported.");
+
+  /* FIXME, this is bogus.  We don't know what the return conventions
+     are, or how values should be promoted.... */
+  if (code == TYPE_CODE_FLT)
+    {
+      dbuf = value_as_double (val);
+
+      STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&dbuf);
+    }
+  else
+    {
+      lbuf = value_as_long (val);
+      STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&lbuf);
+    }
+}
+\f
+void
+_initialize_values ()
+{
+  add_info ("convenience", convenience_info,
+           "Debugger convenience (\"$foo\") variables.\n\
+These variables are created when you assign them values;\n\
+thus, \"print $foo=1\" gives \"$foo\" the value 1.  Values may be any type.\n\n\
+A few convenience variables are given values automatically:\n\
+\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\
+\"$__\" holds the contents of the last address examined with \"x\".");
+
+  add_info ("values", value_history_info,
+           "Elements of value history around item number IDX (or last ten).");
+  add_info_alias ("history", "values", 0);
+}
diff --git a/gdb/vax-opcode.h b/gdb/vax-opcode.h
new file mode 100755 (executable)
index 0000000..18a2ffb
--- /dev/null
@@ -0,0 +1,382 @@
+/* Vax opcde list.
+   Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+GDB and GAS are 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 1, or (at your option)
+any later version.
+
+GDB and GAS are 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 GDB or GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef vax_opcodeT
+#define vax_opcodeT int
+#endif /* no vax_opcodeT */
+
+struct vot_wot                 /* vax opcode table: wot to do with this */
+                               /* particular opcode */
+{
+  char *            args;      /* how to compile said opcode */
+  vax_opcodeT       code;      /* op-code (may be > 8 bits!) */
+};
+
+struct vot                     /* vax opcode text */
+{
+  char *            name;      /* opcode name: lowercase string  [key]  */
+  struct vot_wot    detail;    /* rest of opcode table          [datum] */
+};
+
+#define vot_how args
+#define vot_code code
+#define vot_detail detail
+#define vot_name name
+
+static struct vot
+votstrs[] =
+{
+{    "halt",   {"",                    0x00    } },
+{    "nop",    {"",                    0x01    } },
+{    "rei",    {"",                    0x02    } },
+{    "bpt",    {"",                    0x03    } },
+{    "ret",    {"",                    0x04    } },
+{    "rsb",    {"",                    0x05    } },
+{    "ldpctx", {"",                    0x06    } },
+{    "svpctx", {"",                    0x07    } },
+{    "cvtps",  {"rwabrwab",            0x08    } },
+{    "cvtsp",  {"rwabrwab",            0x09    } },
+{    "index",  {"rlrlrlrlrlwl",        0x0a    } },
+{    "crc",    {"abrlrwab",            0x0b    } },
+{    "prober", {"rbrwab",              0x0c    } },
+{    "probew", {"rbrwab",              0x0d    } },
+{    "insque", {"abab",                0x0e    } },
+{    "remque", {"abwl",                0x0f    } },
+{    "bsbb",   {"bb",                  0x10    } },
+{    "brb",    {"bb",                  0x11    } },
+{    "bneq",   {"bb",                  0x12    } },
+{    "bnequ",  {"bb",                  0x12    } },
+{    "beql",   {"bb",                  0x13    } },
+{    "beqlu",  {"bb",                  0x13    } },
+{    "bgtr",   {"bb",                  0x14    } },
+{    "bleq",   {"bb",                  0x15    } },
+{    "jsb",    {"ab",                  0x16    } },
+{    "jmp",    {"ab",                  0x17    } },
+{    "bgeq",   {"bb",                  0x18    } },
+{    "blss",   {"bb",                  0x19    } },
+{    "bgtru",  {"bb",                  0x1a    } },
+{    "blequ",  {"bb",                  0x1b    } },
+{    "bvc",    {"bb",                  0x1c    } },
+{    "bvs",    {"bb",                  0x1d    } },
+{    "bcc",    {"bb",                  0x1e    } },
+{    "bgequ",  {"bb",                  0x1e    } },
+{    "blssu",  {"bb",                  0x1f    } },
+{    "bcs",    {"bb",                  0x1f    } },
+{    "addp4",  {"rwabrwab",            0x20    } },
+{    "addp6",  {"rwabrwabrwab",        0x21    } },
+{    "subp4",  {"rwabrwab",            0x22    } },
+{    "subp6",  {"rwabrwabrwab",        0x23    } },
+{    "cvtpt",  {"rwababrwab",          0x24    } },
+{    "mulp",   {"rwabrwabrwab",        0x25    } },
+{    "cvttp",  {"rwababrwab",          0x26    } },
+{    "divp",   {"rwabrwabrwab",        0x27    } },
+{    "movc3",  {"rwabab",              0x28    } },
+{    "cmpc3",  {"rwabab",              0x29    } },
+{    "scanc",  {"rwababrb",            0x2a    } },
+{    "spanc",  {"rwababrb",            0x2b    } },
+{    "movc5",  {"rwabrbrwab",          0x2c    } },
+{    "cmpc5",  {"rwabrbrwab",          0x2d    } },
+{    "movtc",  {"rwabrbabrwab",        0x2e    } },
+{    "movtuc", {"rwabrbabrwab",        0x2f    } },
+{    "bsbw",   {"bw",                  0x30    } },
+{    "brw",    {"bw",                  0x31    } },
+{    "cvtwl",  {"rwwl",                0x32    } },
+{    "cvtwb",  {"rwwb",                0x33    } },
+{    "movp",   {"rwabab",              0x34    } },
+{    "cmpp3",  {"rwabab",              0x35    } },
+{    "cvtpl",  {"rwabwl",              0x36    } },
+{    "cmpp4",  {"rwabrwab",            0x37    } },
+{    "editpc", {"rwababab",            0x38    } },
+{    "matchc", {"rwabrwab",            0x39    } },
+{    "locc",   {"rbrwab",              0x3a    } },
+{    "skpc",   {"rbrwab",              0x3b    } },
+{    "movzwl", {"rwwl",                0x3c    } },
+{    "acbw",   {"rwrwmwbw",            0x3d    } },
+{    "movaw",  {"awwl",                0x3e    } },
+{    "pushaw", {"aw",                  0x3f    } },
+{    "addf2",  {"rfmf",                0x40    } },
+{    "addf3",  {"rfrfwf",              0x41    } },
+{    "subf2",  {"rfmf",                0x42    } },
+{    "subf3",  {"rfrfwf",              0x43    } },
+{    "mulf2",  {"rfmf",                0x44    } },
+{    "mulf3",  {"rfrfwf",              0x45    } },
+{    "divf2",  {"rfmf",                0x46    } },
+{    "divf3",  {"rfrfwf",              0x47    } },
+{    "cvtfb",  {"rfwb",                0x48    } },
+{    "cvtfw",  {"rfww",                0x49    } },
+{    "cvtfl",  {"rfwl",                0x4a    } },
+{    "cvtrfl", {"rfwl",                0x4b    } },
+{    "cvtbf",  {"rbwf",                0x4c    } },
+{    "cvtwf",  {"rwwf",                0x4d    } },
+{    "cvtlf",  {"rlwf",                0x4e    } },
+{    "acbf",   {"rfrfmfbw",            0x4f    } },
+{    "movf",   {"rfwf",                0x50    } },
+{    "cmpf",   {"rfrf",                0x51    } },
+{    "mnegf",  {"rfwf",                0x52    } },
+{    "tstf",   {"rf",                  0x53    } },
+{    "emodf",  {"rfrbrfwlwf",          0x54    } },
+{    "polyf",  {"rfrwab",              0x55    } },
+{    "cvtfd",  {"rfwd",                0x56    } },
+                                        /* opcode 57 is not defined yet */
+{    "adawi",  {"rwmw",                0x58    } },
+                                        /* opcode 59 is not defined yet */
+                                        /* opcode 5a is not defined yet */
+                                        /* opcode 5b is not defined yet */
+{    "insqhi", {"abaq",                0x5c    } },
+{    "insqti", {"abaq",                0x5d    } },
+{    "remqhi", {"aqwl",                0x5e    } },
+{    "remqti", {"aqwl",                0x5f    } },
+{    "addd2",  {"rdmd",                0x60    } },
+{    "addd3",  {"rdrdwd",              0x61    } },
+{    "subd2",  {"rdmd",                0x62    } },
+{    "subd3",  {"rdrdwd",              0x63    } },
+{    "muld2",  {"rdmd",                0x64    } },
+{    "muld3",  {"rdrdwd",              0x65    } },
+{    "divd2",  {"rdmd",                0x66    } },
+{    "divd3",  {"rdrdwd",              0x67    } },
+{    "cvtdb",  {"rdwb",                0x68    } },
+{    "cvtdw",  {"rdww",                0x69    } },
+{    "cvtdl",  {"rdwl",                0x6a    } },
+{    "cvtrdl", {"rdwl",                0x6b    } },
+{    "cvtbd",  {"rbwd",                0x6c    } },
+{    "cvtwd",  {"rwwd",                0x6d    } },
+{    "cvtld",  {"rlwd",                0x6e    } },
+{    "acbd",   {"rdrdmdbw",            0x6f    } },
+{    "movd",   {"rdwd",                0x70    } },
+{    "cmpd",   {"rdrd",                0x71    } },
+{    "mnegd",  {"rdwd",                0x72    } },
+{    "tstd",   {"rd",                  0x73    } },
+{    "emodd",  {"rdrbrdwlwd",          0x74    } },
+{    "polyd",  {"rdrwab",              0x75    } },
+{    "cvtdf",  {"rdwf",                0x76    } },
+                                        /* opcode 77 is not defined yet */
+{    "ashl",   {"rbrlwl",              0x78    } },
+{    "ashq",   {"rbrqwq",              0x79    } },
+{    "emul",   {"rlrlrlwq",            0x7a    } },
+{    "ediv",   {"rlrqwlwl",            0x7b    } },
+{    "clrd",   {"wd",                  0x7c    } },
+{    "clrg",   {"wg",                  0x7c    } },
+{    "clrq",   {"wd",                  0x7c    } },
+{    "movq",   {"rqwq",                0x7d    } },
+{    "movaq",  {"aqwl",                0x7e    } },
+{    "movad",  {"adwl",                0x7e    } },
+{    "pushaq", {"aq",                  0x7f    } },
+{    "pushad", {"ad",                  0x7f    } },
+{    "addb2",  {"rbmb",                0x80    } },
+{    "addb3",  {"rbrbwb",              0x81    } },
+{    "subb2",  {"rbmb",                0x82    } },
+{    "subb3",  {"rbrbwb",              0x83    } },
+{    "mulb2",  {"rbmb",                0x84    } },
+{    "mulb3",  {"rbrbwb",              0x85    } },
+{    "divb2",  {"rbmb",                0x86    } },
+{    "divb3",  {"rbrbwb",              0x87    } },
+{    "bisb2",  {"rbmb",                0x88    } },
+{    "bisb3",  {"rbrbwb",              0x89    } },
+{    "bicb2",  {"rbmb",                0x8a    } },
+{    "bicb3",  {"rbrbwb",              0x8b    } },
+{    "xorb2",  {"rbmb",                0x8c    } },
+{    "xorb3",  {"rbrbwb",              0x8d    } },
+{    "mnegb",  {"rbwb",                0x8e    } },
+{    "caseb",  {"rbrbrb",              0x8f    } },
+{    "movb",   {"rbwb",                0x90    } },
+{    "cmpb",   {"rbrb",                0x91    } },
+{    "mcomb",  {"rbwb",                0x92    } },
+{    "bitb",   {"rbrb",                0x93    } },
+{    "clrb",   {"wb",                  0x94    } },
+{    "tstb",   {"rb",                  0x95    } },
+{    "incb",   {"mb",                  0x96    } },
+{    "decb",   {"mb",                  0x97    } },
+{    "cvtbl",  {"rbwl",                0x98    } },
+{    "cvtbw",  {"rbww",                0x99    } },
+{    "movzbl", {"rbwl",                0x9a    } },
+{    "movzbw", {"rbww",                0x9b    } },
+{    "rotl",   {"rbrlwl",              0x9c    } },
+{    "acbb",   {"rbrbmbbw",            0x9d    } },
+{    "movab",  {"abwl",                0x9e    } },
+{    "pushab", {"ab",                  0x9f    } },
+{    "addw2",  {"rwmw",                0xa0    } },
+{    "addw3",  {"rwrwww",              0xa1    } },
+{    "subw2",  {"rwmw",                0xa2    } },
+{    "subw3",  {"rwrwww",              0xa3    } },
+{    "mulw2",  {"rwmw",                0xa4    } },
+{    "mulw3",  {"rwrwww",              0xa5    } },
+{    "divw2",  {"rwmw",                0xa6    } },
+{    "divw3",  {"rwrwww",              0xa7    } },
+{    "bisw2",  {"rwmw",                0xa8    } },
+{    "bisw3",  {"rwrwww",              0xa9    } },
+{    "bicw2",  {"rwmw",                0xaa    } },
+{    "bicw3",  {"rwrwww",              0xab    } },
+{    "xorw2",  {"rwmw",                0xac    } },
+{    "xorw3",  {"rwrwww",              0xad    } },
+{    "mnegw",  {"rwww",                0xae    } },
+{    "casew",  {"rwrwrw",              0xaf    } },
+{    "movw",   {"rwww",                0xb0    } },
+{    "cmpw",   {"rwrw",                0xb1    } },
+{    "mcomw",  {"rwww",                0xb2    } },
+{    "bitw",   {"rwrw",                0xb3    } },
+{    "clrw",   {"ww",                  0xb4    } },
+{    "tstw",   {"rw",                  0xb5    } },
+{    "incw",   {"mw",                  0xb6    } },
+{    "decw",   {"mw",                  0xb7    } },
+{    "bispsw", {"rw",                  0xb8    } },
+{    "bicpsw", {"rw",                  0xb9    } },
+{    "popr",   {"rw",                  0xba    } },
+{    "pushr",  {"rw",                  0xbb    } },
+{    "chmk",   {"rw",                  0xbc    } },
+{    "chme",   {"rw",                  0xbd    } },
+{    "chms",   {"rw",                  0xbe    } },
+{    "chmu",   {"rw",                  0xbf    } },
+{    "addl2",  {"rlml",                0xc0    } },
+{    "addl3",  {"rlrlwl",              0xc1    } },
+{    "subl2",  {"rlml",                0xc2    } },
+{    "subl3",  {"rlrlwl",              0xc3    } },
+{    "mull2",  {"rlml",                0xc4    } },
+{    "mull3",  {"rlrlwl",              0xc5    } },
+{    "divl2",  {"rlml",                0xc6    } },
+{    "divl3",  {"rlrlwl",              0xc7    } },
+{    "bisl2",  {"rlml",                0xc8    } },
+{    "bisl3",  {"rlrlwl",              0xc9    } },
+{    "bicl2",  {"rlml",                0xca    } },
+{    "bicl3",  {"rlrlwl",              0xcb    } },
+{    "xorl2",  {"rlml",                0xcc    } },
+{    "xorl3",  {"rlrlwl",              0xcd    } },
+{    "mnegl",  {"rlwl",                0xce    } },
+{    "casel",  {"rlrlrl",              0xcf    } },
+{    "movl",   {"rlwl",                0xd0    } },
+{    "cmpl",   {"rlrl",                0xd1    } },
+{    "mcoml",  {"rlwl",                0xd2    } },
+{    "bitl",   {"rlrl",                0xd3    } },
+{    "clrf",   {"wf",                  0xd4    } },
+{    "clrl",   {"wl",                  0xd4    } },
+{    "tstl",   {"rl",                  0xd5    } },
+{    "incl",   {"ml",                  0xd6    } },
+{    "decl",   {"ml",                  0xd7    } },
+{    "adwc",   {"rlml",                0xd8    } },
+{    "sbwc",   {"rlml",                0xd9    } },
+{    "mtpr",   {"rlrl",                0xda    } },
+{    "mfpr",   {"rlwl",                0xdb    } },
+{    "movpsl", {"wl",                  0xdc    } },
+{    "pushl",  {"rl",                  0xdd    } },
+{    "moval",  {"alwl",                0xde    } },
+{    "movaf",  {"afwl",                0xde    } },
+{    "pushal", {"al",                  0xdf    } },
+{    "pushaf", {"af",                  0xdf    } },
+{    "bbs",    {"rlabbb",              0xe0    } },
+{    "bbc",    {"rlabbb",              0xe1    } },
+{    "bbss",   {"rlabbb",              0xe2    } },
+{    "bbcs",   {"rlabbb",              0xe3    } },
+{    "bbsc",   {"rlabbb",              0xe4    } },
+{    "bbcc",   {"rlabbb",              0xe5    } },
+{    "bbssi",  {"rlabbb",              0xe6    } },
+{    "bbcci",  {"rlabbb",              0xe7    } },
+{    "blbs",   {"rlbb",                0xe8    } },
+{    "blbc",   {"rlbb",                0xe9    } },
+{    "ffs",    {"rlrbvbwl",            0xea    } },
+{    "ffc",    {"rlrbvbwl",            0xeb    } },
+{    "cmpv",   {"rlrbvbrl",            0xec    } },
+{    "cmpzv",  {"rlrbvbrl",            0xed    } },
+{    "extv",   {"rlrbvbwl",            0xee    } },
+{    "extzv",  {"rlrbvbwl",            0xef    } },
+{    "insv",   {"rlrlrbvb",            0xf0    } },
+{    "acbl",   {"rlrlmlbw",            0xf1    } },
+{    "aoblss", {"rlmlbb",              0xf2    } },
+{    "aobleq", {"rlmlbb",              0xf3    } },
+{    "sobgeq", {"mlbb",                0xf4    } },
+{    "sobgtr", {"mlbb",                0xf5    } },
+{    "cvtlb",  {"rlwb",                0xf6    } },
+{    "cvtlw",  {"rlww",                0xf7    } },
+{    "ashp",   {"rbrwabrbrwab",        0xf8    } },
+{    "cvtlp",  {"rlrwab",              0xf9    } },
+{    "callg",  {"abab",                0xfa    } },
+{    "calls",  {"rlab",                0xfb    } },
+{    "xfc",    {"",                    0xfc    } },
+                                        /* undefined opcodes here */
+{    "cvtdh",  {"rdwh",                0x32fd  } },
+{    "cvtgf",  {"rgwh",                0x33fd  } },
+{    "addg2",  {"rgmg",                0x40fd  } },
+{    "addg3",  {"rgrgwg",              0x41fd  } },
+{    "subg2",  {"rgmg",                0x42fd  } },
+{    "subg3",  {"rgrgwg",              0x43fd  } },
+{    "mulg2",  {"rgmg",                0x44fd  } },
+{    "mulg3",  {"rgrgwg",              0x45fd  } },
+{    "divg2",  {"rgmg",                0x46fd  } },
+{    "divg3",  {"rgrgwg",              0x47fd  } },
+{    "cvtgb",  {"rgwb",                0x48fd  } },
+{    "cvtgw",  {"rgww",                0x49fd  } },
+{    "cvtgl",  {"rgwl",                0x4afd  } },
+{    "cvtrgl", {"rgwl",                0x4bfd  } },
+{    "cvtbg",  {"rbwg",                0x4cfd  } },
+{    "cvtwg",  {"rwwg",                0x4dfd  } },
+{    "cvtlg",  {"rlwg",                0x4efd  } },
+{    "acbg",   {"rgrgmgbw",            0x4ffd  } },
+{    "movg",   {"rgwg",                0x50fd  } },
+{    "cmpg",   {"rgrg",                0x51fd  } },
+{    "mnegg",  {"rgwg",                0x52fd  } },
+{    "tstg",   {"rg",                  0x53fd  } },
+{    "emodg",  {"rgrwrgwlwg",          0x54fd  } },
+{    "polyg",  {"rgrwab",              0x55fd  } },
+{    "cvtgh",  {"rgwh",                0x56fd  } },
+                                        /* undefined opcodes here */
+{    "addh2",  {"rhmh",                0x60fd  } },
+{    "addh3",  {"rhrhwh",              0x61fd  } },
+{    "subh2",  {"rhmh",                0x62fd  } },
+{    "subh3",  {"rhrhwh",              0x63fd  } },
+{    "mulh2",  {"rhmh",                0x64fd  } },
+{    "mulh3",  {"rhrhwh",              0x65fd  } },
+{    "divh2",  {"rhmh",                0x66fd  } },
+{    "divh3",  {"rhrhwh",              0x67fd  } },
+{    "cvthb",  {"rhwb",                0x68fd  } },
+{    "cvthw",  {"rhww",                0x69fd  } },
+{    "cvthl",  {"rhwl",                0x6afd  } },
+{    "cvtrhl", {"rhwl",                0x6bfd  } },
+{    "cvtbh",  {"rbwh",                0x6cfd  } },
+{    "cvtwh",  {"rwwh",                0x6dfd  } },
+{    "cvtlh",  {"rlwh",                0x6efd  } },
+{    "acbh",   {"rhrhmhbw",            0x6ffd  } },
+{    "movh",   {"rhwh",                0x70fd  } },
+{    "cmph",   {"rhrh",                0x71fd  } },
+{    "mnegh",  {"rhwh",                0x72fd  } },
+{    "tsth",   {"rh",                  0x73fd  } },
+{    "emodh",  {"rhrwrhwlwh",          0x74fd  } },
+{    "polyh",  {"rhrwab",              0x75fd  } },
+{    "cvthg",  {"rhwg",                0x76fd  } },
+                                        /* undefined opcodes here */
+{    "clrh",   {"wh",                  0x7cfd  } },
+{    "clro",   {"wo",                  0x7cfd  } },
+{    "movo",   {"rowo",                0x7dfd  } },
+{    "movah",  {"ahwl",                0x7efd  } },
+{    "movao",  {"aowl",                0x7efd  } },
+{    "pushah", {"ah",                  0x7ffd  } },
+{    "pushao", {"ao",                  0x7ffd  } },
+                                        /* undefined opcodes here */
+{    "cvtfh",  {"rfwh",                0x98fd  } },
+{    "cvtfg",  {"rfwg",                0x99fd  } },
+                                        /* undefined opcodes here */
+{    "cvthf",  {"rhwf",                0xf6fd  } },
+{    "cvthd",  {"rhwd",                0xf7fd  } },
+                                        /* undefined opcodes here */
+{    "bugl",   {"rl",                  0xfdff  } },
+{    "bugw",   {"rw",                  0xfeff  } },
+                                        /* undefined opcodes here */
+
+{      ""       ,   ""          } /* empty is end sentinel */
+
+};                             /* votstrs */
+
+/* end: vax.opcode.h */
diff --git a/gdb/vax-pinsn.c b/gdb/vax-pinsn.c
new file mode 100644 (file)
index 0000000..4c159af
--- /dev/null
@@ -0,0 +1,240 @@
+/* Print vax instructions for GDB, the GNU debugger.
+   Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "vax-opcode.h"
+
+/* Vax instructions are never longer than this.  */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table.  */
+#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
+
+extern char *reg_names[];
+
+static unsigned char *print_insn_arg ();
+\f
+/* Print the vax instruction at address MEMADDR in debugged memory,
+   on STREAM.  Returns length of the instruction, in bytes.  */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  unsigned char buffer[MAXLEN];
+  register int i;
+  register unsigned char *p;
+  register char *d;
+
+  read_memory (memaddr, buffer, MAXLEN);
+
+  for (i = 0; i < NOPCODES; i++)
+    if (votstrs[i].detail.code == buffer[0]
+       || votstrs[i].detail.code == *(unsigned short *)buffer)
+      break;
+
+  /* Handle undefined instructions.  */
+  if (i == NOPCODES)
+    {
+      fprintf (stream, "0%o", buffer[0]);
+      return 1;
+    }
+
+  fprintf (stream, "%s", votstrs[i].name);
+
+  /* Point at first byte of argument data,
+     and at descriptor for first argument.  */
+  p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
+  d = votstrs[i].detail.args;
+
+  if (*d)
+    fputc (' ', stream);
+
+  while (*d)
+    {
+      p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
+      d += 2;
+      if (*d)
+       fprintf (stream, ",");
+    }
+  return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, p, addr, stream)
+     char *d;
+     register char *p;
+     CORE_ADDR addr;
+     FILE *stream;
+{
+  register int regnum = *p & 0xf;
+  float floatlitbuf;
+
+  if (*d == 'b')
+    {
+      if (d[1] == 'b')
+       fprintf (stream, "0x%x", addr + *p++ + 1);
+      else
+       {
+         fprintf (stream, "0x%x", addr + *(short *)p + 2);
+         p += 2;
+       }
+    }
+  else
+    switch ((*p++ >> 4) & 0xf)
+      {
+      case 0:
+      case 1:
+      case 2:
+      case 3:                  /* Literal mode */
+       if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
+         {
+           *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
+           fprintf (stream, "$%f", floatlitbuf);
+         }
+       else
+         fprintf (stream, "$%d", p[-1] & 0x3f);
+       break;
+
+      case 4:                  /* Indexed */
+       p = (char *) print_insn_arg (d, p, addr + 1, stream);
+       fprintf (stream, "[%s]", reg_names[regnum]);
+       break;
+
+      case 5:                  /* Register */
+       fprintf (stream, reg_names[regnum]);
+       break;
+
+      case 7:                  /* Autodecrement */
+       fputc ('-', stream);
+      case 6:                  /* Register deferred */
+       fprintf (stream, "(%s)", reg_names[regnum]);
+       break;
+
+      case 9:                  /* Autoincrement deferred */
+       fputc ('@', stream);
+       if (regnum == PC_REGNUM)
+         {
+           fputc ('#', stream);
+           print_address (*(long *)p, stream);
+           p += 4;
+           break;
+         }
+      case 8:                  /* Autoincrement */
+       if (regnum == PC_REGNUM)
+         {
+           fputc ('#', stream);
+           switch (d[1])
+             {
+             case 'b':
+               fprintf (stream, "%d", *p++);
+               break;
+
+             case 'w':
+               fprintf (stream, "%d", *(short *)p);
+               p += 2;
+               break;
+
+             case 'l':
+               fprintf (stream, "%d", *(long *)p);
+               p += 4;
+               break;
+
+             case 'q':
+               fprintf (stream, "0x%x%08x", ((long *)p)[1], ((long *)p)[0]);
+               p += 8;
+               break;
+
+             case 'o':
+               fprintf (stream, "0x%x%08x%08x%08x",
+                        ((long *)p)[3], ((long *)p)[2],
+                        ((long *)p)[1], ((long *)p)[0]);
+               p += 16;
+               break;
+
+             case 'f':
+               if (INVALID_FLOAT (p, 4))
+                 fprintf (stream, "<<invalid float 0x%x>>", *(int *) p);
+               else
+                 fprintf (stream, "%f", *(float *) p);
+               p += 4;
+               break;
+
+             case 'd':
+               if (INVALID_FLOAT (p, 8))
+                 fprintf (stream, "<<invalid float 0x%x%08x>>",
+                          ((long *)p)[1], ((long *)p)[0]);
+               else
+                 fprintf (stream, "%f", *(double *) p);
+               p += 8;
+               break;
+
+             case 'g':
+               fprintf (stream, "g-float");
+               p += 8;
+               break;
+
+             case 'h':
+               fprintf (stream, "h-float");
+               p += 16;
+               break;
+
+             }
+         }
+       else
+         fprintf (stream, "(%s)+", reg_names[regnum]);
+       break;
+
+      case 11:                 /* Byte displacement deferred */
+       fputc ('@', stream);
+      case 10:                 /* Byte displacement */
+       if (regnum == PC_REGNUM)
+         print_address (addr + *p + 2, stream);
+       else
+         fprintf (stream, "%d(%s)", *p, reg_names[regnum]);
+       p += 1;
+       break;
+
+      case 13:                 /* Word displacement deferred */
+       fputc ('@', stream);
+      case 12:                 /* Word displacement */
+       if (regnum == PC_REGNUM)
+         print_address (addr + *(short *)p + 3, stream);
+       else
+         fprintf (stream, "%d(%s)", *(short *)p, reg_names[regnum]);
+       p += 2;
+       break;
+
+      case 15:                 /* Long displacement deferred */
+       fputc ('@', stream);
+      case 14:                 /* Long displacement */
+       if (regnum == PC_REGNUM)
+         print_address (addr + *(long *)p + 5, stream);
+       else
+         fprintf (stream, "%d(%s)", *(long *)p, reg_names[regnum]);
+       p += 4;
+      }
+
+  return (unsigned char *) p;
+}
diff --git a/gdb/vx-share/dbgRpcLib.h b/gdb/vx-share/dbgRpcLib.h
new file mode 100644 (file)
index 0000000..c420075
--- /dev/null
@@ -0,0 +1,28 @@
+/* dbgRpcLib.h - header file for remote debugging via rpc */
+
+/*
+modification history
+--------------------
+01b,04oct90,maf  added VX_BOOT_FILE_INQ.
+01a,05jun90,llk  extracted from xdr_dbx.h.
+*/
+
+#ifndef INCdbxRpcLibh
+#define INCdbxRpcLibh  1
+
+#define PROCESS_START          50
+#define PROCESS_WAIT           51
+#define VX_STATE_INQ           60
+#define VX_LOAD                        61
+#define VX_SYMBOL_INQ          62
+#define VX_BREAK_ADD           63
+#define VX_BREAK_DELETE                64
+#define VX_FP_INQUIRE          65
+#define VX_TASK_SUSPEND                66
+#define VX_CALL_FUNC           67
+#define VX_CONV_FROM_68881     68
+#define VX_CONV_TO_68881       69
+#define VX_BOOT_FILE_INQ       70
+#define        VX_SOURCE_STEP          71
+
+#endif INCdbxRpcLibh
diff --git a/gdb/vx-share/ptrace.h b/gdb/vx-share/ptrace.h
new file mode 100644 (file)
index 0000000..34801c7
--- /dev/null
@@ -0,0 +1,44 @@
+/*     @(#)ptrace.h 1.1 86/07/07 SMI   */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  borrowed.
+*/
+
+#ifndef _PTRACE_
+#define _PTRACE_
+
+/*
+ * Request values for the ptrace system call
+ */
+enum ptracereq {
+       PTRACE_TRACEME = 0,             /* 0, by tracee to begin tracing */
+       PTRACE_CHILDDONE = 0,           /* 0, tracee is done with his half */
+       PTRACE_PEEKTEXT,                /* 1, read word from text segment */
+       PTRACE_PEEKDATA,                /* 2, read word from data segment */
+       PTRACE_PEEKUSER,                /* 3, read word from user struct */
+       PTRACE_POKETEXT,                /* 4, write word into text segment */
+       PTRACE_POKEDATA,                /* 5, write word into data segment */
+       PTRACE_POKEUSER,                /* 6, write word into user struct */
+       PTRACE_CONT,                    /* 7, continue process */
+       PTRACE_KILL,                    /* 8, terminate process */
+       PTRACE_SINGLESTEP,              /* 9, single step process */
+       PTRACE_ATTACH,                  /* 10, attach to an existing process */
+       PTRACE_DETACH,                  /* 11, detach from a process */
+       PTRACE_GETREGS,                 /* 12, get all registers */
+       PTRACE_SETREGS,                 /* 13, set all registers */
+       PTRACE_GETFPREGS,               /* 14, get all floating point regs */
+       PTRACE_SETFPREGS,               /* 15, set all floating point regs */
+       PTRACE_READDATA,                /* 16, read data segment */
+       PTRACE_WRITEDATA,               /* 17, write data segment */
+       PTRACE_READTEXT,                /* 18, read text segment */
+       PTRACE_WRITETEXT,               /* 19, write text segment */
+       PTRACE_GETFPAREGS,              /* 20, get all fpa regs */
+       PTRACE_SETFPAREGS,              /* 21, set all fpa regs */
+};
+#endif !_PTRACE
diff --git a/gdb/vx-share/reg.h b/gdb/vx-share/reg.h
new file mode 100644 (file)
index 0000000..84658b7
--- /dev/null
@@ -0,0 +1,209 @@
+/*      @(#)reg.h 1.1 86/07/07 SMI      */
+
+/*
+ * Copyright (c) 1986 by Sun Microsystems, Inc.
+ */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  borrowed.
+*/
+
+#ifndef _REG_
+#define _REG_
+
+#ifdef I80960
+
+/* Intel 960 register values passed over the wire by RPC:  */
+
+struct regs
+{
+  int r_lreg[16];              /* local registers              */
+  int r_greg[16];              /* global registers             */
+  int r_pcw;                   /* process control word         */
+  int r_acw;                   /* arithmetic control word      */
+  int r_tcw;                   /* trace control word           */
+};
+
+#define FP_REG_SIZE    12
+
+struct fp_status {
+       char    fps_regs[4][FP_REG_SIZE];       /* floating point regs */
+};
+
+#else  /* For now, just 68000 */
+
+/*
+ * Location of the users' stored
+ * registers relative to R0.
+ * Usage is u.u_ar0[XX].
+ */
+#define        R0      (0)
+#define        R1      (1)
+#define        R2      (2)
+#define        R3      (3)
+#define        R4      (4)
+#define        R5      (5)
+#define        R6      (6)
+#define        R7      (7)
+#define        AR0     (8)
+#define        AR1     (9)
+#define        AR2     (10)
+#define        AR3     (11)
+#define        AR4     (12)
+#define        AR5     (13)
+#define        AR6     (14)
+#define        AR7     (15)
+#define        SP      (15)
+#define        PS      (16)
+#define        PC      (17)
+
+/*
+ * And now for something completely the same...
+ */
+#ifndef LOCORE
+struct regs {  
+       int     r_dreg[8];      /* data registers */
+#define r_r0   r_dreg[0]       /* r0 for portability */
+       int     r_areg[8];      /* address registers */
+#define r_sp   r_areg[7]       /* user stack pointer */
+       int     r_sr;           /* status register (actually a short) */
+#define        r_ps    r_sr
+       int     r_pc;           /* program counter */
+};
+
+struct stkfmt {
+       int     f_stkfmt : 4;   /* stack format */
+       int              : 2;
+       int     f_vector : 10;  /* vector offset */
+       short   f_beibase;      /* start of bus error info (if any) */
+};
+
+
+/*
+ * Struct for floating point registers and general state
+ * for the MC68881 (the sky fpp has no user visible state).
+ * If fps_flags == FPS_UNUSED, the other 68881 fields have no meaning.
+ * fps_code and fps_flags are software implemented fields.
+ * fps_flags is not used when set by user level programs,
+ * but changing fps_code has the side effect of changing u.u_code.
+ */
+
+typedef        struct ext_fp {
+       int     fp[3];
+} ext_fp;              /* extended 96-bit 68881 fp registers */
+
+struct fp_status {
+       ext_fp  fps_regs[8];            /* 68881 floating point regs */
+       int     fps_control;            /* 68881 control reg */
+       int     fps_status;             /* 68881 status reg */
+       int     fps_iaddr;              /* 68881 instruction address reg */
+       int     fps_code;               /* additional word for signals */
+       int     fps_flags;              /* r/o - unused, idle or busy */
+};
+#endif !LOCORE
+
+/*
+ * Values defined for `fps_flags'.
+ */
+#define        FPS_UNUSED      0               /* 68881 never used yet */
+#define        FPS_IDLE        1               /* 68881 instruction completed */
+#define        FPS_BUSY        2               /* 68881 instruction interrupted */
+
+/*
+ * The EXT_FPS_FLAGS() macro is used to convert a pointer to an
+ * fp_istate into a value to be used for the user visible state
+ * found in fps_flags.  As a speed optimization, this convertion
+ * is only done is required (e.g.  the PTRACE_GETFPREGS ptrace
+ * call or when dumping core) instead of on each context switch.
+ * The tests that we base the state on are that a fpis_vers of
+ * FPIS_VERSNULL means NULL state, else a fpis_bufsiz of FPIS_IDLESZ
+ * means IDLE state, else we assume BUSY state.
+ */
+#define        FPIS_VERSNULL   0x0
+#define        FPIS_IDLESIZE   0x18
+
+#define EXT_FPS_FLAGS(istatep) \
+       ((istatep)->fpis_vers == FPIS_VERSNULL ? FPS_UNUSED : \
+           (istatep)->fpis_bufsiz == FPIS_IDLESIZE ? FPS_IDLE : FPS_BUSY)
+
+#ifndef LOCORE
+/*
+ * Struct for the internal state of the MC68881
+ * Although the MC68881 can have a smaller maximum for
+ * internal state, we allow for more to allow for expansion.
+ */
+#define        FPIS_BUFSIZ     0xc0
+
+struct fp_istate {
+       unsigned char   fpis_vers;              /* version number */
+       unsigned char   fpis_bufsiz;            /* size of info in fpis_buf */
+       unsigned short  fpis_reserved;          /* reserved word */
+       unsigned char   fpis_buf[FPIS_BUFSIZ];  /* fpp internal state buffer */
+};
+
+/* 
+ * Structures for the status and data registers are defined here.
+ * Struct fpa_status are included in the u area.
+ * Struct fpa_regs is included in struct core.
+ */
+
+/* struct fpa_status is saved/restored during context switch */
+struct fpa_status {
+       unsigned int    fpas_state;     /* STATE, supervisor privileged reg */
+       unsigned int    fpas_imask;     /* IMASK */
+       unsigned int    fpas_load_ptr;  /* LOAD_PTR */
+       unsigned int    fpas_ierr;      /* IERR */
+       unsigned int    fpas_act_instr; /* pipe active instruction halves */
+       unsigned int    fpas_nxt_instr; /* pipe next instruction halves */
+       unsigned int    fpas_act_d1half;/* pipe active data first half */
+       unsigned int    fpas_act_d2half;/* pipe active data second half */
+       unsigned int    fpas_nxt_d1half;/* pipe next data first half */
+       unsigned int    fpas_nxt_d2half;/* pipe next data second half */
+       unsigned int    fpas_mode3_0;   /* FPA MODE3_0 register */
+       unsigned int    fpas_wstatus;   /* FPA WSTATUS register */
+};
+
+/* 
+ * Since there are 32 contexts supported by the FPA hardware,
+ * when we do context switch on the FPA, we don't save/restore
+ * the data registers between the FPA and the u area.
+ * If there are already 32 processes using the fpa concurrently,
+ * we give an error message to the 33rd process trying to use the fpa.
+ * (Hopefully there will not be this many processes using FPA concurrently.)
+ */
+
+#define FPA_NCONTEXTS          32
+#define FPA_NDATA_REGS         32
+
+typedef struct fpa_long {
+       int     fpl_data[2];
+} fpa_long;             /* 64 bit double precision registers */
+
+/* Struct fpa_regs is included in struct core. */
+struct fpa_regs {
+       unsigned int    fpar_flags; /* if zero, other fields are meaningless */
+        struct fpa_status      fpar_status;
+        fpa_long       fpar_data[FPA_NDATA_REGS];
+};
+
+/*
+ * The size of struct fpa_regs is changed from 141 ints in 3.0 to
+ * 77 ints in 3.x.  A pad of this size difference is added to struct core.
+ */
+#define CORE_PADLEN     64
+
+/*
+ * If there is going to be external FPU state then we must define the FPU
+ * variable
+ */
+struct fpu {
+        struct  fp_status f_fpstatus;   /* External FPP state, if any */
+        struct  fpa_regs f_fparegs;     /* FPA registers, if any */
+        int     f_pad[CORE_PADLEN];     /* see comment above */
+};
+
+#endif !LOCORE
+#endif /* !I80960 */
+#endif !_REG_
diff --git a/gdb/vx-share/vxTypes.h b/gdb/vx-share/vxTypes.h
new file mode 100644 (file)
index 0000000..3ebd7c6
--- /dev/null
@@ -0,0 +1,70 @@
+/* vxTypes.h - VxWorks type definition header */
+
+/* Copyright 1984-1990 Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01c,05oct90,shl  added copyright notice.
+                 made #endif ANSI style.
+01b,10aug90,dnw  added VOIDFUNCPTR
+01a,29may90,del  written.
+*/
+
+#ifndef INCvxTypesh
+#define INCvxTypesh
+
+/* The following stuff must NOT be included if this include file is used
+ * from assembly language.  Just #define ASMLANGUAGE before the include,
+ * to get rid of it.
+ */
+
+#ifndef ASMLANGUAGE
+
+/* vxWorks types */
+
+typedef        char            INT8;
+typedef        short           INT16;
+typedef        int             INT32;
+
+typedef        unsigned char   UINT8;
+typedef        unsigned short  UINT16;
+typedef        unsigned int    UINT32;
+
+typedef        unsigned char   UCHAR;
+typedef unsigned short USHORT;
+typedef        unsigned int    UINT;
+typedef unsigned long  ULONG;
+
+typedef        int             BOOL;
+typedef        int             VOID;
+typedef        int             STATUS; 
+typedef int            ARGINT;
+
+typedef int            (*FUNCPTR) ();      /* ptr to function returning int */
+typedef VOID           (*VOIDFUNCPTR) ();  /* ptr to function returning VOID */
+
+
+/* historical definitions - now obsolete */
+
+typedef char           TINY;           /* obsolete */
+typedef char           TBOOL;          /* obsolete */
+typedef unsigned char  UTINY;          /* obsolete */
+
+
+/* architecture dependent typedefs */
+
+#ifdef CPU_FAMILY
+
+#if    CPU_FAMILY==MC680X0
+typedef unsigned short INSTR;          /* word-aligned instructions */
+#endif /* CPU_FAMILY==MC680X0 */
+
+#if    CPU_FAMILY==SPARC
+typedef unsigned long INSTR;           /* 32 bit word-aligned instructions */
+#endif /* CPU_FAMILY==SPARC */
+
+#endif 
+
+#endif /* ASMLANGUAGE */
+#endif /* INCvxTypesh */
diff --git a/gdb/vx-share/vxWorks.h b/gdb/vx-share/vxWorks.h
new file mode 100644 (file)
index 0000000..483313e
--- /dev/null
@@ -0,0 +1,177 @@
+/* vxWorks.h - VxWorks standard definitions header */
+
+/* Copyright 1984-1990 Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01z,05oct90,shl  added copyright notice.
+                 made #endif ANSI style.
+01y,28sep90,del  added I960 defines.
+01x,29may90,del         moved types to vxTypes.h
+01w,09apr90,jcf  added timeout definitions.
+01v,24jan90,gae  moved network configuration flags here from makefile's.
+01u,01sep88,mcl  definition of INSTR dependent on processor family; added SPARC.
+          +gae  added MC680X0 and defined CPU_FAMILY.
+01t,08apr89,dnw  added ifdef to prevent inclusion of vxWorks.h more than once.
+01s,22jun88,dnw         moved READ, WRITE, and UPDATE back here from ioLib.h.
+01r,22apr88,gae  oops! forgot some #endif's in 01q.
+01q,12apr88,gae  removed QUICK & WAIT; added STD_{IN,OUT,ERR}.
+                fixed #define's of FALSE, TRUE, etc.
+                moved READ, WRITE, and UPDATE to ioLib.h.
+01p,04dec87,dnw  added undefine of MC68000 to get around Green Hills bug that
+                  pre-defines MC68000.
+01o,12nov87,ecs  added type ULONG.
+01n,08feb86,dnw  added types INSTR, UINT, USHORT.
+01m,14oct85,rdc  added BUS types.
+01l,16jul85,jlf  added conditional for NULL and EOF.
+01k,24jun85,rdc  installed condtional compile so we can include in
+                assembly language files.  See instructions below.
+                Added System type macro and CPU type macro.
+01j,13jun85,dnw  cleaned-up, removed more obsolete stuff to wrs.h
+01i,11sep84,jlf  changed name from wrs.h to vxWorks.h.  removed GLOBAL.
+01h,03jun84,dnw  removed IGNORE declaration.
+01g,09apr84,jlf  added MEMBER_SIZE macro.
+01f,14dec83,dnw  added MSB, LSB macros
+01e,17nov83,jlf  added STATUS type, for routines which return a status.
+01d,13jul83,dnw  added NELEMENTS macro
+01c,14May83,dnw  added OFFSET macro
+01b,17Feb83,dnw  added stuff from Whitesmiths std.h
+01a,15Feb83,dnw  written
+*/
+
+#ifndef INCvxWorksh
+#define INCvxWorksh
+
+#if    !defined(NULL) || (NULL!=0)
+#define NULL           0
+#endif 
+
+#if    !defined(EOF) || (EOF!=(-1))
+#define EOF            (-1)
+#endif 
+
+#if    !defined(FALSE) || (FALSE!=0)
+#define FALSE          0
+#endif 
+
+#if    !defined(TRUE) || (TRUE!=1)
+#define TRUE           1
+#endif 
+
+
+#define NONE           (-1)    /* for times when NULL won't do */
+#define EOS            '\0'    /* C string terminator */
+
+
+/* return status values */
+
+#define OK             0
+#define ERROR          (-1)
+
+/* timeout defines */
+
+#define NO_WAIT                0
+#define WAIT_FOREVER   (-1)
+
+/* low-level I/O input, output, error fd's */
+
+#define        STD_IN  0
+#define        STD_OUT 1
+#define        STD_ERR 2
+
+/* modes - must match O_RDONLY/O_WRONLY/O_RDWR in ioLib.h! */
+
+#define READ           0
+#define WRITE          1
+#define UPDATE         2
+
+/* SYSTEM types */
+
+#define V7             1       /* ATT version 7 */
+#define SYS_V          2       /* ATT System 5 */
+#define BSD_4_2                3       /* Berkeley BSD 4.2 */
+
+/* CPU types */
+
+/* The Green Hills compiler pre-defines "MC68000"!! */
+#ifdef MC68000
+#undef MC68000
+#endif 
+
+#define MC68000                1
+#define MC68010                2
+#define MC68020                3
+#define MC68030                4
+#define MC68040                5
+#define MC680X0                9
+
+#define SPARC          10
+
+#ifndef I960
+#define        I960            20
+#endif 
+
+#define        I960KB          21
+#define        I960CA          22
+
+#if    CPU==MC68000 || CPU==MC68010 || CPU==MC68020 || CPU==MC68030
+#define        CPU_FAMILY      MC680X0
+#endif /* CPU==MC68000 || CPU==MC68010 || CPU==MC68020 || CPU==MC68030 */
+
+#if    CPU==SPARC
+#define        CPU_FAMILY      SPARC
+#endif /* CPU==SPARC */
+
+#if    CPU==I960KB
+#define        CPU_FAMILY      I960
+#endif /*      CPU==I960KB */
+
+#if    CPU==I960CA
+#define        CPU_FAMILY      I960
+#endif /*      CPU==I960CA */
+
+/* BUS types */
+
+#define VME_BUS                1
+#define MULTI_BUS      2
+
+/* network configuration parameters */
+
+#define        INET            /* include internet protocols */
+#define        BSD     43      /* BSD 4.3 -like OS */
+#define        BSDDEBUG        /* turn on debug */
+#define        GATEWAY         /* tables to be initialized for gateway routing */
+
+/* common macros */
+
+#define MSB(x) (((x) >> 8) & 0xff)     /* most signif byte of 2-byte integer */
+#define LSB(x) ((x) & 0xff)            /* least signif byte of 2-byte integer*/
+
+#define OFFSET(structure, member)      /* byte offset of member in structure*/\
+               ((int) &(((structure *) 0) -> member))
+
+#define MEMBER_SIZE(structure, member) /* size of a member of a structure */\
+               (sizeof (((structure *) 0) -> member))
+
+#define NELEMENTS(array)               /* number of elements in an array */ \
+               (sizeof (array) / sizeof ((array) [0]))
+
+#define FOREVER        for (;;)
+
+#define max(x, y)      (((x) < (y)) ? (y) : (x))
+#define min(x, y)      (((x) < (y)) ? (x) : (y))
+
+
+/* storage class specifier definitions */
+
+#define FAST   register
+#define IMPORT extern
+#define LOCAL  static
+
+
+/* include typedefs - must come after CPU_FAMILY definitions above */
+
+#include "vxTypes.h"
+
+#endif /* INCvxWorksh */
diff --git a/gdb/vx-share/wait.h b/gdb/vx-share/wait.h
new file mode 100644 (file)
index 0000000..bb81f5b
--- /dev/null
@@ -0,0 +1,42 @@
+/* wait.h - header file for remote wait call */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  borrowed.
+*/
+
+/* Define how to access the structure that the wait system call stores.
+   On many systems, there is a structure defined for this.
+   But on vanilla-ish USG systems there is not.  */
+
+#ifndef HAVE_WAIT_STRUCT
+#define WAITTYPE int
+#define WIFSTOPPED(w) (((w)&0377) == 0177)
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#define WIFEXITED(w) (((w)&0377) == 0)
+#define WRETCODE(w) ((w) >> 8)
+#define WSTOPSIG(w) ((w) >> 8)
+#define WCOREDUMP(w) (((w)&0200) != 0)
+#define WTERMSIG(w) ((w) & 0177)
+#define WSETEXIT(w, status) ((w) = (status))
+#define WSETSTOP(w,sig)  ((w) = (0177 | ((sig) << 8)))
+#else
+#if FALSE
+#ifndef ORIG
+
+/* don't include sys/wait.h */
+
+#else ORIG
+#include <sys/wait.h>
+#endif ORIG
+#endif FALSE
+#define WAITTYPE union wait
+#define WRETCODE(w) (w).w_retcode
+#define WSTOPSIG(w) (w).w_stopsig
+#define WCOREDUMP(w) (w).w_coredump
+#define WTERMSIG(w) (w).w_termsig
+#define WSETEXIT(w, status) ((w).w_status = (status))
+#define WSETSTOP(w,sig)  \
+  ((w).w_stopsig = (sig), (w).w_coredump = 0, (w).w_termsig = 0177)
+#endif
diff --git a/gdb/vx-share/xdr_ld.c b/gdb/vx-share/xdr_ld.c
new file mode 100644 (file)
index 0000000..4935c34
--- /dev/null
@@ -0,0 +1,82 @@
+/* xdr_ld.c  - xdr routines for remote dbx interface to VxWorks  */
+
+/* Copyright 1984,1985,1986,1987,1988,1989 Wind River Systems, Inc. */
+/*extern char copyright_wind_river[]; static char *copyright=copyright_wind_river;*/
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  extracted from xdr_dbx.c.
+*/
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for object files that are downloaded to VxWorks.  They are used by
+remote debuggers that use RPC (such as dbxWorks and vxGdb).
+*/
+
+#include "vxWorks.h"
+#include "rpc/rpc.h"
+#include "xdr_ld.h"
+
+/* forward declarations */
+
+bool_t xdr_String();           /* xdr routine for argument list */
+
+
+/*******************************************************************************
+*
+* xdr_String - xdr routine for strings.
+* 
+* Used by xdr_arg_info to handle the actual argument
+* strings.  normally calls xdr_string - but does something 
+* reasonable encode of null pointer.
+*/
+
+bool_t xdr_String (xdrs, strp)
+    XDR        *xdrs;
+    char **strp;
+
+    {
+    if ((*strp == NULL) & (xdrs->x_op == XDR_ENCODE)) 
+       return(FALSE);
+    else 
+       return(xdr_string(xdrs, strp, MAXSTRLEN));
+    }
+/*******************************************************************************
+*
+* xdr_ldfile - xdr routine for a single element in the load table 
+*/
+
+bool_t xdr_ldfile (xdrs, objp)
+    XDR *xdrs;
+    ldfile *objp;
+
+    {
+    if (! xdr_String(xdrs, &objp->name)) 
+       return(FALSE);
+    if (! xdr_int(xdrs, &objp->txt_addr)) 
+       return(FALSE);
+    if (! xdr_int(xdrs, &objp->data_addr)) 
+       return(FALSE);
+    if (! xdr_int(xdrs, &objp->bss_addr)) 
+       return(FALSE);
+
+    return(TRUE);
+    }
+/*******************************************************************************
+*
+* xdr_ldtabl -
+*
+* xdr routine for a list of files and load addresses loaded into VxWorks.
+*/
+
+bool_t xdr_ldtabl (xdrs,objp)
+    XDR *xdrs;
+    ldtabl *objp;
+
+    {
+    return (xdr_array (xdrs, (char *) &objp->tbl_ent, (UINT *) &objp->tbl_size, 
+           MAXTBLSZ, sizeof(ldfile), xdr_ldfile));
+    }
diff --git a/gdb/vx-share/xdr_ld.h b/gdb/vx-share/xdr_ld.h
new file mode 100644 (file)
index 0000000..8021ccf
--- /dev/null
@@ -0,0 +1,41 @@
+/* xdr_ld.h - xdr for additional dbxWorks structures */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  extracted from xdr_dbx.h.
+*/
+
+#ifndef INCxdrldh
+#define INCxdrldh
+
+#define MAXSTRLEN 256
+#define MAXTBLSZ 100
+
+/*
+ * structure used to pass back the information for a single file
+ * loaded in VxWorks
+ */
+struct ldfile {
+       char    *name;
+       int     txt_addr;
+       int     data_addr;
+       int     bss_addr;
+};
+typedef struct ldfile ldfile;
+
+/*
+ * structure used to return a list of all files loaded over to 
+ * VxWorks. (VX_STATE_INQ return)
+ */
+struct ldtabl {
+       u_int tbl_size;
+       ldfile *tbl_ent;
+};
+typedef struct ldtabl ldtabl;
+
+
+bool_t xdr_ldfile();
+bool_t xdr_ldtabl();
+
+#endif INCxdrldh
diff --git a/gdb/vx-share/xdr_ptrace.c b/gdb/vx-share/xdr_ptrace.c
new file mode 100644 (file)
index 0000000..08813fc
--- /dev/null
@@ -0,0 +1,171 @@
+/* xdr_ptrace.c  - xdr routines for remote ptrace calls */
+/* Copyright 1984,1985,1986,1987,1988,1989 Wind River Systems, Inc. */
+/* extern char copyright_wind_river[]; static char *copyright=copyright_wind_river;*/
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  extracted from xdr_ptrace.h, version 01c.
+*/
+
+#include <vxWorks.h>
+#include <rpc/rpc.h>
+#include <xdr_ptrace.h>
+
+#define MAX_LEN 32000
+
+/********************************************************************
+*
+* xdr_regs_ptr -
+*
+* xdr routine to get regs* branch of discriminated union ptrace_info
+*
+*/
+
+LOCAL bool_t xdr_regs_ptr(xdrs,objp)
+    XDR *xdrs;
+    struct regs **objp;
+    {
+    return (xdr_pointer(xdrs, (char **) objp, sizeof(struct regs), xdr_regs));
+    } /* xdr_regs_ptr */
+
+/********************************************************************
+*
+* xdr_fp_status_ptr -
+*
+* xdr routine for fp_status * branch of discrimanated union
+*
+*/
+
+LOCAL bool_t xdr_fp_status_ptr(xdrs,objp)
+    XDR *xdrs;
+    struct fp_status **objp;
+    {
+    return(xdr_pointer(xdrs, (char **) objp, sizeof(struct fp_status), 
+           xdr_fp_status));
+    } /* xdr_fp_status_ptr */
+
+#ifndef I80960
+/********************************************************************
+*
+* xdr_fpa_regs_ptr - 
+*
+* xdr routine for fpa_regs* branch of ptrace_info
+*
+*/
+
+LOCAL bool_t xdr_fpa_regs_ptr(xdrs,objp)
+    XDR *xdrs;
+    struct fpa_regs **objp;
+    {
+    if (! xdr_pointer(xdrs, (char **) objp, sizeof(struct fpa_regs), 
+                     xdr_fpa_regs)) 
+       return(FALSE);
+    else
+       return(TRUE);
+    } /* xdr_fpa_regs_ptr */
+#endif
+
+/********************************************************************
+*
+* xdr_c_bytes_ptr -
+*
+* xdr routine for counted bytes branch of ptrace_info
+*
+*/
+
+LOCAL bool_t xdr_c_bytes_ptr(xdrs,objp)
+    XDR *xdrs;
+    C_bytes **objp;
+    {
+    return(xdr_pointer(xdrs, (char **) objp, sizeof(C_bytes), xdr_c_bytes));
+    } /* xdr_c_bytes_ptr */
+
+/********************************************************************
+*
+* xdr_ptrace_info -
+*
+* xdr routine for discriminated union ptrace_info
+*
+*/
+
+bool_t xdr_ptrace_info(xdrs,objp)
+    XDR *xdrs;
+    Ptrace_info *objp;
+    {
+    static struct xdr_discrim choices[] = 
+       {
+           { (int) REGS, xdr_regs_ptr },
+           { (int) FPREGS, xdr_fp_status_ptr },
+#ifndef I80960
+           { (int) FPAREGS, xdr_fpa_regs_ptr },
+#endif
+           { (int) DATA, xdr_c_bytes_ptr },
+           { __dontcare__, NULL }
+       };
+
+    return(xdr_union(xdrs, (enum_t *) &objp->ttype, 
+       (char *) &objp->more_data, choices, xdr_void));
+    } /* xdr_ptrace_info */
+
+/********************************************************************
+*
+* xdr_rptrace - 
+*
+* xdr routine for remote ptrace data into server
+*
+*/
+
+bool_t xdr_rptrace(xdrs,objp)
+    XDR *xdrs;
+    Rptrace *objp;
+    {
+    if (! xdr_int(xdrs, &objp->pid)) 
+       return(FALSE);
+    if (! xdr_int(xdrs, &objp->data)) 
+       return(FALSE);
+    if (! xdr_int(xdrs, &objp->addr)) 
+       return(FALSE);
+    if (! xdr_ptrace_info(xdrs, &objp->info)) 
+       return(FALSE);
+
+    return(TRUE);
+    } /* xdr_rptrace */
+
+/********************************************************************
+*
+* xdr_ptrace_return - 
+*
+* xdr routine for remote ptrace data returned by server
+*
+*/
+
+bool_t xdr_ptrace_return(xdrs, objp)
+    XDR *xdrs;
+    Ptrace_return *objp;
+    {
+    if (! xdr_int(xdrs, &objp->status)) 
+       return(FALSE);
+    if (! xdr_int(xdrs, &objp->errno)) 
+       return(FALSE);
+    if (! xdr_ptrace_info(xdrs, &objp->info)) 
+       return(FALSE);
+
+    return(TRUE);
+    } /* xdr_ptrace_return */  
+
+/********************************************************************
+*
+* xdr_c_bytes -
+*
+* xdr routine for counted bytes  
+*
+*/
+bool_t xdr_c_bytes(xdrs,objp)
+    XDR *xdrs;
+    C_bytes *objp;
+    {
+    return(xdr_bytes(xdrs, &objp->bytes, (u_int *) &objp->len, MAX_LEN));
+    } /* xdr_c_bytes */
+
diff --git a/gdb/vx-share/xdr_ptrace.h b/gdb/vx-share/xdr_ptrace.h
new file mode 100644 (file)
index 0000000..1fe7ab4
--- /dev/null
@@ -0,0 +1,68 @@
+/* xdr_ptrace.h - xdr header for remote ptrace structures */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  extracted from xdr_ptrace.h.
+*/
+
+
+#include "xdr_regs.h"
+#include "reg.h"
+
+/*
+ *  Counted byte structure used by READ/WRITE TEXT/DATA
+ */
+struct c_bytes {
+       u_int   len;
+       caddr_t bytes;
+};
+typedef struct c_bytes C_bytes;
+
+/*
+ * enum for discriminated union ptrace_info
+ */
+enum ptype {
+       NOINFO = 0,             /* no additional infomation     */
+       REGS = 1,               /* regs         (SETREGS)       */
+       FPREGS = 2,             /* fp_status    (SETFPREGS)     */
+       FPAREGS = 3,            /* fpa_regs     (SETFPAREGS)    */
+       DATA = 4,               /* c_bytes      (WRITETEXT/DATA)*/
+};
+typedef enum ptype ptype;
+
+/*
+ * discrimnated union for passing additional data to be 
+ * written to the debugged process. With the exception of
+ * c_bytes, the structures are defined in <machine/reg.h>
+ */
+struct ptrace_info {
+       ptype   ttype;
+       caddr_t more_data;      
+};
+typedef struct ptrace_info Ptrace_info;
+
+/*
+ * structure passed to server on all remote ptrace calls
+ */
+struct rptrace {
+       int     pid;
+       int     data;
+       int     addr;   /* FIX! this really should be caddr_t or something */
+       Ptrace_info     info;
+};
+typedef struct rptrace Rptrace;
+/*
+ * structure returned by server on all remote ptrace calls
+ */
+struct ptrace_return {
+       int status;
+       int errno;
+       Ptrace_info     info;
+};
+typedef struct ptrace_return Ptrace_return;
+
+bool_t xdr_c_bytes();
+bool_t xdr_ptrace_info();
+bool_t xdr_rptrace();
+bool_t xdr_ptrace_return();
diff --git a/gdb/vx-share/xdr_rdb.c b/gdb/vx-share/xdr_rdb.c
new file mode 100644 (file)
index 0000000..3c70fbf
--- /dev/null
@@ -0,0 +1,207 @@
+/* xdr_rdb.c  - xdr routines for Remote Debug interface to VxWorks  */
+
+/*
+modification history
+--------------------
+01a,21mar90,llk  created using modification 01d of xdr_dbx.c.
+*/
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for the RDB interface for VxWorks.
+*/
+
+#include "vxWorks.h"
+#include <rpc/rpc.h>
+#include "xdr_rdb.h"
+
+/* forward declarations */
+
+bool_t
+xdr_arg_type(xdrs, objp)
+        XDR *xdrs;
+        arg_type *objp;
+{
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+        return (TRUE);
+}
+
+bool_t
+xdr_arg_value(xdrs, objp)
+        XDR *xdrs;
+        arg_value *objp;
+{
+        if (!xdr_arg_type(xdrs, &objp->type)) {
+                return (FALSE);
+        }
+        switch (objp->type) {
+        case T_BYTE:
+                if (!xdr_char(xdrs, &objp->arg_value_u.v_byte)) {
+                        return (FALSE);
+                }
+                break;
+        case T_WORD:
+                if (!xdr_short(xdrs, &objp->arg_value_u.v_word)) {
+                        return (FALSE);
+                }
+                break;
+        case T_INT:
+                if (!xdr_int(xdrs, &objp->arg_value_u.v_int)) {
+                        return (FALSE);
+                }
+                break;
+        case T_FLOAT:
+                if (!xdr_float(xdrs, &objp->arg_value_u.v_fp)) {
+                        return (FALSE);
+                }
+                break;
+        case T_DOUBLE:
+                if (!xdr_double(xdrs, &objp->arg_value_u.v_dp)) {
+                        return (FALSE);
+                }
+                break;
+        case T_UNKNOWN:
+                break;
+        }
+        return (TRUE);
+}
+
+bool_t
+xdr_func_call(xdrs, objp)
+        XDR *xdrs;
+        func_call *objp;
+{
+        if (!xdr_int(xdrs, &objp->func_addr)) {
+                return (FALSE);
+        }
+        if (!xdr_array(xdrs, (char **)&objp->args.args_val, (u_int *)&objp->args.args_len, MAX_FUNC_ARGS, sizeof(arg_value), xdr_arg_value)) {
+                return (FALSE);
+        }
+        return (TRUE);
+}
+
+bool_t
+xdr_arg_one(xdrs, objp)
+        XDR *xdrs;
+        arg_one *objp;
+{
+        if (!xdr_string(xdrs, objp, MAX_ARG_LEN)) {
+                return (FALSE);
+        }
+        return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_arg_array(xdrs, objp)
+        XDR *xdrs;
+        arg_array *objp;
+{
+        if (!xdr_array(xdrs, (char **)&objp->arg_array_val, (u_int *)&objp->arg_array_len, MAX_ARG_CNT, sizeof(arg_one), xdr_arg_one)) {
+                return (FALSE);
+        }
+        return (TRUE);
+}
+
+/*********************************************************************
+*
+* xdr_EVENT_TYPE -
+*
+*/
+
+bool_t xdr_EVENT_TYPE(xdrs, objp)
+    XDR *xdrs;
+    EVENT_TYPE *objp;
+
+    {
+    if (!xdr_enum (xdrs, (enum_t *) objp))
+       return (FALSE);
+    return (TRUE);
+    }
+
+/*********************************************************************
+*
+* xdr_RDB_EVENT -
+*
+*/
+
+bool_t xdr_RDB_EVENT (xdrs, objp)
+    XDR *xdrs;
+    RDB_EVENT *objp;
+
+    {
+    if (!xdr_int (xdrs, &objp->status))
+       return (FALSE);
+    if (!xdr_int (xdrs, &objp->taskId))
+       return (FALSE);
+    if (!xdr_EVENT_TYPE (xdrs, &objp->eventType))
+       return (FALSE);
+    if (!xdr_int (xdrs, &objp->sigType))
+       return (FALSE);
+    return (TRUE);
+    }        
+
+/*********************************************************************
+*
+* xdr_TASK_START -
+*
+*/
+
+bool_t
+xdr_TASK_START (xdrs, objp)
+    XDR *xdrs;
+    TASK_START *objp;
+
+    {
+    if (!xdr_int (xdrs, &objp->status))
+       return (FALSE);
+    if (!xdr_int (xdrs, &objp->pid))
+       return (FALSE);
+    return (TRUE);
+    }
+
+
+/*********************************************************************
+*
+* xdr_SYMBOL_ADDR -
+*
+*/
+
+bool_t
+xdr_SYMBOL_ADDR (xdrs, objp)
+    XDR *xdrs;
+    SYMBOL_ADDR *objp;
+
+    {
+    if (!xdr_int (xdrs, &objp->status))
+       return (FALSE);
+    if (!xdr_u_int (xdrs, &objp->addr))
+       return (FALSE);
+    return (TRUE);
+    }
+
+/*********************************************************************
+*
+* xdr_SOURCE_STEP -
+*
+*/
+
+bool_t
+xdr_SOURCE_STEP (xdrs, objp)
+    XDR *xdrs;
+    SOURCE_STEP *objp;
+
+    {
+    if (!xdr_int (xdrs, &objp->taskId))
+       return (FALSE);
+    if (!xdr_u_int (xdrs, &objp->startAddr))
+       return (FALSE);
+    if (!xdr_u_int (xdrs, &objp->endAddr))
+       return (FALSE);
+    return (TRUE);
+    }
diff --git a/gdb/vx-share/xdr_rdb.h b/gdb/vx-share/xdr_rdb.h
new file mode 100644 (file)
index 0000000..eebec43
--- /dev/null
@@ -0,0 +1,132 @@
+/* xdr_rdb.h - xdr for additional rdb structures */
+
+/*
+modification history
+--------------------
+01a,23may90,llk  created using xdr_dbx.h.
+                added arg_array to replace arg_info.  arg_info had
+                  MAXNCMDARGS (= 100) as the max limit of char strings,
+                  but it should be MAX_TASK_ARGS (= 10).
+*/
+
+#ifndef INCxdrrdbh
+#define INCxdrrdbh
+
+enum arg_type {
+        T_UNKNOWN = 0,
+        T_BYTE = 1,
+        T_WORD = 2,
+        T_INT = 3,
+        T_FLOAT = 4,
+        T_DOUBLE = 5,
+};
+typedef enum arg_type arg_type;
+bool_t xdr_arg_type();
+
+
+struct arg_value {
+        arg_type type;
+        union {
+                char v_byte;
+                short v_word;
+                int v_int;
+                float v_fp;
+                double v_dp;
+        } arg_value_u;
+};
+typedef struct arg_value arg_value;
+bool_t xdr_arg_value();
+
+struct func_call {
+        int func_addr;
+        struct {
+                u_int args_len;
+                arg_value *args_val;
+        } args;
+};
+typedef struct func_call func_call;
+bool_t xdr_func_call();
+
+
+typedef char *arg_one;
+bool_t xdr_arg_one();
+
+
+typedef struct {
+        u_int arg_array_len;
+        arg_one *arg_array_val;
+} arg_array;
+bool_t xdr_arg_array();
+
+
+/*
+ * Structures used to pass structures required for
+ * process control but not part of the standard ptrace interface
+ */
+
+/*
+ * arg_info is used to pass arguments into process start
+ */
+struct arg_info {
+       int rargc;
+       char **rargv;
+};
+typedef struct arg_info Arg_info;
+
+
+enum EVENT_TYPE {
+        EVENT_BREAK = 0,
+        EVENT_STOP = 1,
+        EVENT_EXIT = 2,
+        EVENT_BUS_ERR = 3,
+        EVENT_SUSPEND = 4,
+        EVENT_ZERO_DIV = 5,
+        EVENT_SIGNAL = 6,
+        EVENT_START = 7,
+};
+typedef enum EVENT_TYPE EVENT_TYPE;
+
+
+struct RDB_EVENT {
+       int status;
+       int taskId;
+        EVENT_TYPE eventType;
+        int sigType;
+};
+typedef struct RDB_EVENT RDB_EVENT;
+
+
+struct TASK_START {
+        int status;
+        int pid;
+};
+typedef struct TASK_START TASK_START;
+
+
+struct SYMBOL_ADDR {
+        int status;
+        u_int addr;
+};
+typedef struct SYMBOL_ADDR SYMBOL_ADDR;
+
+struct SOURCE_STEP {
+       int taskId;
+       u_int startAddr;
+       u_int endAddr;
+};
+typedef struct SOURCE_STEP SOURCE_STEP;
+
+#define MAX_ARG_CNT 10
+#define MAX_FUNC_ARGS 100
+#define MAX_ARG_LEN   100
+
+bool_t xdr_arg_info();
+bool_t xdr_EVENT_TYPE();
+bool_t xdr_RDB_EVENT();
+bool_t xdr_TASK_START();
+bool_t xdr_SYMBOL_ADDR();
+bool_t xdr_SOURCE_STEP();
+
+#define RDBPROG (u_long) 0x44444444
+#define RDBVERS (u_long) 1
+#endif INCxdrrdbh
diff --git a/gdb/vx-share/xdr_regs.c b/gdb/vx-share/xdr_regs.c
new file mode 100644 (file)
index 0000000..9152423
--- /dev/null
@@ -0,0 +1,216 @@
+/* xdr_regs.c - xdr routines for 68k registers */
+
+/* Copyright 1984,1985,1986,1987,1988,1989 Wind River Systems, Inc. */
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for the GDB interface for VxWorks.
+*/
+
+#include <vxWorks.h>
+#include <rpc/rpc.h>
+#include <reg.h>
+#include <xdr_regs.h>
+
+
+#ifdef I80960
+/*******************************************************************************
+*
+* xdr_regs - xdr routine for i960 registers
+*/
+
+bool_t xdr_regs (xdrs, objp)
+    XDR *xdrs;
+    struct regs *objp;
+
+    {
+    if (! xdr_opaque(xdrs, (char *) objp->r_lreg, 16 * sizeof(int)))
+       return(FALSE);
+    if (! xdr_opaque(xdrs, (char *) objp->r_greg, 16 * sizeof(int)))
+       return(FALSE);
+    if (! xdr_opaque(xdrs, (char *) &objp->r_pcw, sizeof(int)))
+       return(FALSE);
+    if (! xdr_opaque(xdrs, (char *) &objp->r_acw, sizeof(int)))
+       return(FALSE);
+    if (! xdr_opaque(xdrs, (char *) &objp->r_tcw, sizeof(int)))
+       return(FALSE);
+
+    return(TRUE);
+    }
+
+/*******************************************************************************
+*
+* xdr_fp_status - xdr routine for i960 floating point registers
+*/
+
+bool_t xdr_fp_status (xdrs, objp)
+    XDR *xdrs;
+    struct fp_status *objp;
+
+    {
+    unsigned int size = 4 * FP_REG_SIZE;
+
+    /* We use xdr_bytes to indicate how many bytes of FP regs there are! */
+    if (! xdr_bytes (xdrs, (char *) objp->fps_regs, &size, 4 * FP_REG_SIZE))
+       return (FALSE);
+    return (TRUE);
+    }
+
+/*******************************************************************************
+*
+* xdr_ext_fp - xdr for a single fp register
+*/
+
+bool_t xdr_ext_fp (xdrs, objp)
+    XDR *xdrs;
+    char *objp;
+
+    {
+    unsigned int size = FP_REG_SIZE;
+
+    if (! xdr_bytes (xdrs, objp, &size, FP_REG_SIZE)) 
+       return(FALSE);
+
+    return(TRUE);
+    }
+#else  /* Must be 68K if it isn't i960 -- for now.  FIXME!  */
+
+/*******************************************************************************
+*
+* xdr_regs - xdr routine for 68k registers
+*/
+
+bool_t xdr_regs (xdrs, objp)
+    XDR *xdrs;
+    struct regs *objp;
+
+    {
+    if (! xdr_opaque(xdrs, (char *) objp->r_dreg, 8 * sizeof(int)))
+       return(FALSE);
+    if (! xdr_opaque(xdrs, (char *) objp->r_areg, 8 * sizeof(int)))
+       return(FALSE);
+    if (! xdr_opaque(xdrs, (char *) &objp->r_sr, sizeof(int)))
+       return(FALSE);
+    if (! xdr_opaque(xdrs, (char *) &objp->r_pc, sizeof(int)))
+       return(FALSE);
+
+    return(TRUE);
+    }
+
+/*******************************************************************************
+*
+* xdr_ext_fp - xdr for a single fp register
+*/
+
+bool_t xdr_ext_fp (xdrs, objp)
+    XDR *xdrs;
+    ext_fp *objp;
+
+    {
+    if (! xdr_vector(xdrs, (char *) objp->fp, 3, sizeof(int), xdr_int)) 
+       return(FALSE);
+
+    return(TRUE);
+    }
+/*******************************************************************************
+*
+* xdr_fp_status - xdr routine for floating point registers
+*/
+
+bool_t xdr_fp_status (xdrs, objp)
+    XDR *xdrs;
+    struct fp_status *objp;
+
+    {
+    if (! xdr_vector (xdrs, (char *) objp->fps_regs, 8, 
+               sizeof(ext_fp), xdr_ext_fp))
+       return (FALSE);
+    if (! xdr_int (xdrs, &objp->fps_control)) 
+       return (FALSE);
+    if (! xdr_int (xdrs, &objp->fps_status)) 
+       return (FALSE);
+    if (! xdr_int (xdrs, &objp->fps_iaddr)) 
+       return (FALSE);
+    if (! xdr_int (xdrs, &objp->fps_code)) 
+       return (FALSE);
+    if (! xdr_int (xdrs, &objp->fps_flags)) 
+       return (FALSE);
+
+    return (TRUE);
+    }
+/*******************************************************************************
+*
+* xdr_fpa_status - xdr for fpa status
+*/
+
+bool_t xdr_fpa_status (xdrs, objp)
+    XDR *xdrs;
+    struct fpa_status *objp;
+
+    {
+    if (! xdr_u_int (xdrs, &objp->fpas_state)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_imask)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_load_ptr)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_ierr)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_act_instr)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_nxt_instr)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_act_d1half)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_act_d2half)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_nxt_d1half)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_nxt_d2half)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_mode3_0)) 
+       return (FALSE);
+    if (! xdr_u_int (xdrs, &objp->fpas_wstatus)) 
+       return (FALSE);
+
+    return (TRUE);
+    }
+/*******************************************************************************
+*
+* xdr_fpa_long - xdr for fpa data register
+*/
+
+bool_t xdr_fpa_long (xdrs,objp)
+    XDR *xdrs;
+    fpa_long *objp;
+
+    {
+    if (! xdr_vector (xdrs, (char *) objp->fpl_data, 2, sizeof(int), xdr_int)) 
+       return (FALSE);
+
+    return (TRUE);
+    }
+/*******************************************************************************
+*
+* xdr_fpa_regs - xdr for fpa_regs 
+*/
+
+bool_t xdr_fpa_regs (xdrs, objp)
+    XDR *xdrs;
+    struct fpa_regs *objp;
+
+    {
+    if (! xdr_u_int (xdrs, &objp->fpar_flags)) 
+       return (FALSE);
+    if (! xdr_fpa_status (xdrs, &objp->fpar_status)) 
+       return (FALSE);
+    if (! xdr_vector (xdrs, (char *) objp->fpar_data, 
+                   FPA_NDATA_REGS, sizeof(fpa_long), xdr_fpa_long)) 
+       return (FALSE);
+
+    return (TRUE);
+    }
+
+#endif /* I80960 */
+
diff --git a/gdb/vx-share/xdr_regs.h b/gdb/vx-share/xdr_regs.h
new file mode 100644 (file)
index 0000000..c829d64
--- /dev/null
@@ -0,0 +1,16 @@
+/* xdr_regs.h - xdr header for 68k registers */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk  extracted from xdr_regs.h.
+*/
+
+/* xdr structures are defined in reg.h (a bad place for them, i might add) */
+
+bool_t xdr_regs();
+bool_t xdr_ext_fp();
+bool_t xdr_fp_status();
+bool_t xdr_fpa_status();
+bool_t xdr_fpa_long();
+bool_t xdr_fpa_regs();
diff --git a/gdb/xm-3b1.h b/gdb/xm-3b1.h
new file mode 100644 (file)
index 0000000..6efef40
--- /dev/null
@@ -0,0 +1,87 @@
+/* Parameters for execution on a 3b1.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_TERMIO
+#define USG
+
+#define MAXPATHLEN 200
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR 0x70000
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{ addr = blockend + regno * 4; }
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
+
+#endif
diff --git a/gdb/xm-altos.h b/gdb/xm-altos.h
new file mode 100644 (file)
index 0000000..3a4dc5f
--- /dev/null
@@ -0,0 +1,208 @@
+/* Definitions to make GDB run on an Altos 3068 (m68k running SVR2)
+   Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* The altos support would make a good base for a port to other USGR2 systems
+   (like the 3b1 and the Convergent miniframe).  */
+
+/* This is only needed in one file, but it's cleaner to put it here than
+   putting in more #ifdef's.  */
+#include <sys/page.h>
+#include <sys/net.h>
+
+#define USG
+
+#define HAVE_TERMIO
+
+#define CBREAK XTABS   /* It takes all kinds... */
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#define F_OK 0
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN (1024)
+#endif
+
+/* Get sys/wait.h ie. from a Sun and edit it a little (mc68000 to m68k) */
+/* Why bother?  */
+#if 0
+#define HAVE_WAIT_STRUCT
+#endif
+
+#define vfork fork
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0x1fbf000
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{      if (regno <= SP_REGNUM) \
+         addr = blockend + regno * 4; \
+       else if (regno == PS_REGNUM) \
+         addr = blockend + regno * 4 + 4; \
+       else if (regno == PC_REGNUM) \
+         addr = blockend + regno * 4 + 2; \
+}
+
+#define REGISTER_ADDR(u_ar0, regno)                                    \
+  (((regno) < PS_REGNUM)                                               \
+   ? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)])     \
+   : (((regno) == PS_REGNUM)                                           \
+      ? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS))                \
+      : (&((struct exception_stack *) (u_ar0))->e_PC)))
+
+#define FP_REGISTER_ADDR(u, regno)                                     \
+  (((char *)                                                           \
+    (((regno) < FPC_REGNUM)                                            \
+     ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
+     : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)])))   \
+   - ((char *) (& u)))
+
+\f
+#ifndef __GNUC__
+#undef USE_GAS
+#define ALTOS_AS
+#else
+#define USE_GAS
+#endif
+
+/* Motorola assembly format */
+#if !defined(USE_GAS) && !defined(ALTOS)
+#define MOTOROLA
+#endif
+
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#ifdef MOTOROLA
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("move.l $ end, sp");      \
+  asm ("clr.l fp"); }
+#else
+#ifdef ALTOS_AS
+#define INIT_STACK(beg, end)  \
+{ asm ("global end");         \
+  asm ("mov.l &end,%sp");      \
+  asm ("clr.l %fp"); }
+#else
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+#endif
+#endif
+
+/* Push the frame pointer register on the stack.  */
+#ifdef MOTOROLA
+#define PUSH_FRAME_PTR        \
+  asm ("move.l fp, -(sp)");
+#else
+#ifdef ALTOS_AS
+#define PUSH_FRAME_PTR        \
+  asm ("mov.l %fp, -(%sp)");
+#else
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+#endif
+#endif
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#ifdef MOTOROLA
+#define POP_FRAME_PTR  \
+  asm ("move.l (sp), fp");
+#else
+#ifdef ALTOS_AS
+#define POP_FRAME_PTR  \
+  asm ("mov.l (%sp), %fp");
+#else
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+#endif
+#endif
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#ifdef MOTOROLA
+#define PUSH_REGISTERS        \
+{ asm ("clr.w -(sp)");       \
+  asm ("pea (10,sp)");       \
+  asm ("movem $ 0xfffe,-(sp)"); }
+#else
+#ifdef ALTOS_AS
+#define PUSH_REGISTERS        \
+{ asm ("clr.w -(%sp)");              \
+  asm ("pea (10,%sp)");              \
+  asm ("movm.l &0xfffe,-(%sp)"); }
+#else
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+#endif
+#endif
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#ifdef MOTOROLA
+#define POP_REGISTERS          \
+{ asm ("subi.l $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
+#else
+#ifdef ALTOS_AS
+#define POP_REGISTERS          \
+{ asm ("sub.l &8,28(%sp)");     \
+  asm ("movem (%sp),&0xffff"); \
+  asm ("rte"); }
+#else
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
+#endif
+#endif
diff --git a/gdb/xm-arm.h b/gdb/xm-arm.h
new file mode 100644 (file)
index 0000000..3251fae
--- /dev/null
@@ -0,0 +1,88 @@
+/* Definitions to make GDB run on an ARM under RISCiX (4.3bsd).
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR (0x01000000 - (UPAGES * NBPG))
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+#define FETCH_INFERIOR_REGISTERS
+
+\f
+#if 0
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+  0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movl $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("pushl 8(sp)");        \
+  asm ("pushl 8(sp)");        \
+  asm ("pushal 0x14(sp)");    \
+  asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS      \
+{ asm ("popr $037777");    \
+  asm ("subl2 $8,(sp)");   \
+  asm ("movl (sp),sp");    \
+  asm ("rei"); }
+#endif /* 0 */
diff --git a/gdb/xm-bigmips.h b/gdb/xm-bigmips.h
new file mode 100644 (file)
index 0000000..0c1102d
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#include "xm-mips.h"
diff --git a/gdb/xm-convex.h b/gdb/xm-convex.h
new file mode 100644 (file)
index 0000000..ed102bb
--- /dev/null
@@ -0,0 +1,51 @@
+/* Definitions to make GDB run on Convex Unix (4bsd)
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define LONG_LONG
+#define ATTACH_DETACH
+#define HAVE_WAIT_STRUCT
+#define NO_SIGINTERRUPT
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Use SIGCONT rather than SIGTSTP because convex Unix occasionally
+   turkeys SIGTSTP.  I think.  */
+
+#define STOP_SIGNAL SIGCONT
+
+/* Use csh to do argument expansion so we get ~ and such.  */
+
+/* Doesn't work.  */
+/* #define SHELL_FILE "/bin/csh" */
+
+/* Compensate for lack of `vprintf' function.  */
+#define MISSING_VPRINTF
+
+/* Hook to call after creating inferior process.  */
+
+#define CREATE_INFERIOR_HOOK create_inferior_hook
+
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* (no kdb) */
diff --git a/gdb/xm-hp300bsd.h b/gdb/xm-hp300bsd.h
new file mode 100644 (file)
index 0000000..4ae5a5c
--- /dev/null
@@ -0,0 +1,113 @@
+/* Parameters for execution on a Hewlett-Packard 9000/300, running bsd.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Configuration file for HP9000/300 series machine running
+ * University of Utah's 4.3bsd port.  This is NOT for HP-UX.
+ * Problems to hpbsd-bugs@cs.utah.edu
+ */
+
+#include <machine/endian.h>
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Get kernel u area address at run-time using BSD style nlist ().  */
+#define KERNEL_U_ADDR_BSD
+
+/* This is a piece of magic that is given a register number REGNO
+   and as BLOCKEND the address in the system of the end of the user structure
+   and stores in ADDR the address in the kernel or core dump
+   of that register.  */
+
+#define REGISTER_U_ADDR(addr, blockend, regno)                         \
+{                                                                      \
+  if (regno < PS_REGNUM)                                               \
+    addr = (int) &((struct frame *)(blockend))->f_regs[regno];         \
+  else if (regno == PS_REGNUM)                                         \
+    addr = (int) &((struct frame *)(blockend))->f_stackadj;            \
+  else if (regno == PC_REGNUM)                                         \
+    addr = (int) &((struct frame *)(blockend))->f_pc;                  \
+  else if (regno < FPC_REGNUM)                                         \
+    addr = (int)                                                       \
+      &((struct user *)0)->u_pcb.pcb_fpregs.fpf_regs[((regno)-FP0_REGNUM)*3];\
+  else if (regno == FPC_REGNUM)                                                \
+    addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpcr;       \
+  else if (regno == FPS_REGNUM)                                                \
+    addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpsr;       \
+  else                                                                 \
+    addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpiar;      \
+}
+
+/* Compensate for lack of `vprintf' function.  */
+#define MISSING_VPRINTF
+
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel #end, sp");      \
+  asm ("movel #0,a6"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel a6,sp@-");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl sp@,a6");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea sp@(10)");       \
+  asm ("movem #0xfffe,sp@-"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil #8,sp@(28)");     \
+  asm ("movem sp@,#0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/xm-hp300hpux.h b/gdb/xm-hp300hpux.h
new file mode 100644 (file)
index 0000000..6583748
--- /dev/null
@@ -0,0 +1,173 @@
+/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Define this to indicate problems with traps after continuing.  */
+#define HP_OS_BUG
+
+/* fetch_inferior_registers is in hp300hpux-dep.c.  */
+#define FETCH_INFERIOR_REGISTERS
+
+/* Set flag to indicate whether HP's assembler is in use. */
+#ifdef __GNUC__
+#ifdef __HPUX_ASM__
+#define HPUX_ASM
+#endif
+#else /* not GNU C.  */
+#define HPUX_ASM
+#endif /* not GNU C.  */
+
+/* Define this for versions of hp-ux older than 6.0 */
+/* #define HPUX_VERSION_5 */
+
+/* define USG if you are using sys5 /usr/include's */
+#undef USG     /* In case it was defined in the Makefile for cplus-dem.c */
+#define USG
+
+#define HAVE_TERMIO
+
+/* Get rid of any system-imposed stack limit if possible.  */
+/* The hp9k320.h doesn't seem to have this feature.  */
+/* #define SET_STACK_LIMIT_HUGE */
+/* So we'll just have to avoid big alloca's.  */
+#define BROKEN_LARGE_ALLOCA
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#ifdef HPUX_VERSION_5
+#define KERNEL_U_ADDR 0x00979000
+#else /* Not HPUX version 5.  */
+/* Use HPUX-style nlist() to get kernel_u_addr.  */
+#define KERNEL_U_ADDR_HPUX
+#endif /* Not HPUX version 5.  */
+
+#define REGISTER_ADDR(u_ar0, regno)                                    \
+  (unsigned int)                                                       \
+  (((regno) < PS_REGNUM)                                               \
+   ? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)])     \
+   : (((regno) == PS_REGNUM)                                           \
+      ? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS))                \
+      : (&((struct exception_stack *) (u_ar0))->e_PC)))
+
+#define FP_REGISTER_ADDR(u, regno)                                     \
+  (((char *)                                                           \
+    (((regno) < FPC_REGNUM)                                            \
+     ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
+     : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)])))   \
+   - ((char *) (& u)))
+\f
+/* Do implement the attach and detach commands.  */
+
+#define ATTACH_DETACH
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+#ifndef HPUX_ASM
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
+
+#else /* HPUX_ASM */
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)                                           \
+{ asm ("global end");                                                  \
+  asm ("mov.l &end,%sp");                                              \
+  asm ("clr.l %a6"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR                                                 \
+  asm ("mov.l %fp,-(%sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR                                                  \
+  asm ("mov.l (%sp),%fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS                                                 \
+{ asm ("clr.w -(%sp)");                                                        \
+  asm ("pea 10(%sp)");                                                 \
+  asm ("movm.l &0xfffe,-(%sp)"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS                                                  \
+{ asm ("subi.l &8,28(%sp)");                                           \
+  asm ("mov.m (%sp),&0xffff");                                         \
+  asm ("rte"); }
+
+#endif /* HPUX_ASM */
diff --git a/gdb/xm-i386v.h b/gdb/xm-i386v.h
new file mode 100644 (file)
index 0000000..840cb58
--- /dev/null
@@ -0,0 +1,99 @@
+/* Macro defintions for i386.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
+Sys V/386 3.2.
+
+On some machines, gdb crashes when it's starting up while calling the
+vendor's termio tgetent() routine.  It always works when run under
+itself (actually, under 3.2, it's not an infinitely recursive bug.)
+After some poking around, it appears that depending on the environment
+size, or whether you're running YP, or the phase of the moon or something,
+the stack is not always long-aligned when main() is called, and tgetent()
+takes strong offense at that.  On some machines this bug never appears, but
+on those where it does, it occurs quite reliably.  */
+#define ALIGN_STACK_ON_STARTUP
+
+/* define USG if you are using sys5 /usr/include's */
+#define USG
+
+/* USG systems need these */
+#define vfork() fork()
+#define MAXPATHLEN 500
+
+#define HAVE_TERMIO
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+/* #define SET_STACK_LIMIT_HUGE not in sys5 */
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR 0xe0000000
+
+\f
+#if 0
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  {}
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        {}
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  {}
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        {}
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS      {}
+#endif /* 0 */
diff --git a/gdb/xm-i386v32.h b/gdb/xm-i386v32.h
new file mode 100644 (file)
index 0000000..b343be0
--- /dev/null
@@ -0,0 +1,28 @@
+/* Macro defintions for i386, running System V 3.2.
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "xm-i386v.h"
+
+/* Apparently there is inconsistency among various System V's about what
+   the name of this field is.  */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
+
+/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
+   is not.  This makes problems for inflow.c.  */
+#define TIOCGETC_BROKEN
diff --git a/gdb/xm-isi.h b/gdb/xm-isi.h
new file mode 100644 (file)
index 0000000..21c0134
--- /dev/null
@@ -0,0 +1,95 @@
+/* Definitions to make GDB run on an ISI Optimum V (3.05) under 4.3bsd.
+   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This has not been tested on ISI's running BSD 4.2, but it will probably
+   work.  */
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+/*#define KERNEL_U_ADDR 0x10800000*/
+#define KERNEL_U_ADDR 0
+
+/* expects blockend to be u.u_ar0 */
+extern int rloc[];     /* Defined in isi-dep.c */
+#define REGISTER_U_ADDR(addr, blockend, regno)                  \
+{       blockend &= UPAGES*NBPG - 1;                            \
+       if (regno < 18) addr = (int)blockend + rloc[regno]*4;   \
+        else if (regno < 26) addr = (int) &((struct user *)0)->u_68881_regs \
+            + (regno - 18) * 12;                                \
+        else if (regno < 29) addr = (int) &((struct user *)0)->u_68881_regs \
+            + 8 * 12 + (regno - 26) * 4;                        \
+}
+
+/* Compensate for lack of `vprintf' function.  */
+#define MISSING_VPRINTF
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movl $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/xm-m88k.h b/gdb/xm-m88k.h
new file mode 100644 (file)
index 0000000..240459b
--- /dev/null
@@ -0,0 +1,124 @@
+/* Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is currently for a 88000 running DGUX.  If other 88k ports are
+   done, OS-specific stuff should be moved (see tm-68k.h, for example).  */
+/* g++ support is not yet included.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define USG
+/* DGUX has bcopy(), etc.  */
+#define USG_UTILS 0
+
+#include <sys/param.h>
+
+#define vfork() fork()
+#define index strchr
+#define rindex strrchr
+#define getwd(BUF) getcwd(BUF,MAXPATHLEN);
+#define bzero(ptr,count) (memset((ptr),0,(count)))
+#define bcopy(src,dst,count) (memcpy((dst),(src),(count)))
+#define bcmp(left,right,count) (memcmp((right),(left),(count)))
+#ifdef __GNUC__
+#define memcpy __builtin_memcpy
+#define memset __builtin_memset
+#define strcmp __builtin_strcmp
+#endif
+
+#ifdef DGUX
+#define x_foff _x_x._x_offset
+#define x_fname _x_name
+#define USER ptrace_user
+#define _BSD_WAIT_FLAVOR
+#endif
+
+#define HAVE_TERMIO
+
+
+#define USIZE 2048
+#define NBPG NBPC
+#define UPAGES USIZE
+
+#define HAVE_GETPAGESIZE
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* number of traps that happen between exec'ing the shell
+ * to run an inferior, and when we finally get to
+ * the inferior code.  This is 2 on most implementations.
+ */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+/* Since registers r0 through r31 are stored directly in the struct ptrace_user,
+   (for m88k BCS)
+   the ptrace_user offsets are sufficient and KERNEL_U_ADDRESS can be 0 */
+
+#define KERNEL_U_ADDR 0
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+        (addr) = m88k_register_u_addr ((blockend),(regno));
+
+#define HAVE_WAIT_STRUCT
+
+#define FETCH_INFERIOR_REGISTERS
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  {}
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        {}
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  {}
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        {}
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS      {}
diff --git a/gdb/xm-merlin.h b/gdb/xm-merlin.h
new file mode 100644 (file)
index 0000000..54c1baf
--- /dev/null
@@ -0,0 +1,120 @@
+/* Definitions to make GDB run on a merlin under utek 2.1
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This machine doesn't have the siginterrupt call.  */
+#define NO_SIGINTERRUPT
+
+/* Under Utek, a ptrace'd process can be the only active process for
+   an executable.  Therefore instead of /bin/sh use gdb-sh (which should
+   just be a copy of /bin/sh which is world readable and writeable).  */
+#define SHELL_FILE "/usr/gnu/lib/gdb-sh"
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR (0xfef000)
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{                                                                      \
+  switch (regno) {                                                     \
+  case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:      \
+       addr = blockend + (R0 - regno) * sizeof (int); break;           \
+  case PC_REGNUM:                                                      \
+       addr = blockend + PC * sizeof (int); break;                     \
+  case SP_REGNUM:                                                      \
+       addr = blockend + SP * sizeof (int); break;                     \
+  case FP_REGNUM:                                                      \
+       addr = blockend + FP * sizeof (int); break;                     \
+  case PS_REGNUM:                                                      \
+       addr = blockend + 12 * sizeof (int); break;                     \
+  case FPS_REGNUM:                                                     \
+       addr = 108; break;                                              \
+  case FP0_REGNUM + 0: case FP0_REGNUM + 1:                            \
+  case FP0_REGNUM + 2: case FP0_REGNUM + 3:                            \
+  case FP0_REGNUM + 4: case FP0_REGNUM + 5:                            \
+  case FP0_REGNUM + 6: case FP0_REGNUM + 7:                            \
+       addr = 76 + (regno - FP0_REGNUM) * sizeof (float); break;       \
+  case LP0_REGNUM + 0: case LP0_REGNUM + 1:                            \
+  case LP0_REGNUM + 2: case LP0_REGNUM + 3:                            \
+       addr = 76 + (regno - LP0_REGNUM) * sizeof (double); break;      \
+  default:                                                             \
+       printf ("bad argument to REGISTER_U_ADDR %d\n", regno);         \
+       abort ();                                                       \
+  }                                                                    \
+}
+
+/* Compensate for lack of `vprintf' function.  */
+#define MISSING_VPRINTF
+\f
+#if 0
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+  0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movl $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("pushl 8(sp)");        \
+  asm ("pushl 8(sp)");        \
+  asm ("pushal 0x14(sp)");    \
+  asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS      \
+{ asm ("popr $037777");    \
+  asm ("subl2 $8,(sp)");   \
+  asm ("movl (sp),sp");    \
+  asm ("rei"); }
+#endif /* 0 */
diff --git a/gdb/xm-mips.h b/gdb/xm-mips.h
new file mode 100644 (file)
index 0000000..3f7fce2
--- /dev/null
@@ -0,0 +1,44 @@
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+   Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+   and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* wait.h */
+#define HAVE_WAIT_STRUCT
+
+/* Get rid of any system-imposed stack limit if possible */
+
+#define        SET_STACK_LIMIT_HUGE
+
+/* This WOULD BE the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.
+   But Mips' ptrace works on regnums, not displacements */
+
+#define KERNEL_U_ADDR (int)u.u_ar0
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+#define FETCH_INFERIOR_REGISTERS
+\f
+/* Interface definitions for kernel debugger KDB */
+
+/* I am not going to pretend I've done anything about this */
diff --git a/gdb/xm-news.h b/gdb/xm-news.h
new file mode 100644 (file)
index 0000000..1c5c6f1
--- /dev/null
@@ -0,0 +1,143 @@
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_WAIT_STRUCT
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* We can't use "isatty" or "fileno" on this machine.  This isn't good,
+   but it will have to do.  */
+#define ISATTY(FP)     ((FP) == stdin || (FP) == stdout)
+
+/* THis is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR UADDR
+
+/* The offsets in this macro are from /usr/include/machine/reg.h */
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{   static char offsets[] = { \
+       /*d0-d7:*/1,2,3,4,5,6,7,8, \
+       /*a0-a6:*/9,10,11,12,13,14,15, /*sp:*/-4, /*ps:*/0, /*pc:*/-1, \
+       /*fp0-fp7:*/19,22,25,28,31,34,37,40, /*fpc:*/16,17,18 }; \
+       addr = blockend + 4 * offsets[regno]; \
+}
+
+/* Compensate for lack of `vprintf' function.  */
+#define MISSING_VPRINTF
+
+/* NewsOS 3 apparently dies on large alloca's -- roland@ai.mit.edu.  */
+#define        BROKEN_LARGE_ALLOCA
+
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Use GNU assembler instead of standard assembler */
+#define USE_GAS
+
+/* Motorola assembly format */
+#ifndef USE_GAS
+#define MOTOROLA
+#endif
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#ifdef MOTOROLA
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("move.l $ end, sp");      \
+  asm ("clr.l fp"); }
+#else
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+#endif
+
+/* Push the frame pointer register on the stack.  */
+#ifdef MOTOROLA
+#define PUSH_FRAME_PTR        \
+  asm ("move.l fp, -(sp)");
+#else
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+#endif
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#ifdef MOTOROLA
+#define POP_FRAME_PTR  \
+  asm ("move.l (sp), fp");
+#else
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+#endif
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#ifdef MOTOROLA
+#define PUSH_REGISTERS        \
+{ asm ("clr.w -(sp)");       \
+  asm ("pea (10,sp)");       \
+  asm ("movem $ 0xfffe,-(sp)"); }
+#else
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+#endif
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#ifdef MOTOROLA
+#define POP_REGISTERS          \
+{ asm ("subi.l $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
+#else
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
+#endif
diff --git a/gdb/xm-news1000.h b/gdb/xm-news1000.h
new file mode 100644 (file)
index 0000000..aade898
--- /dev/null
@@ -0,0 +1,26 @@
+/* Parameters for a Sony/NEWS series 1000 with News-OS version 3,
+   for GDB, the GNU debugger.
+   Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is required by Sony include files like <sys/user.h> so we
+   get the right offset into the u area.  Relying on the compiler
+   to define this only works for cc, not gcc.  */
+#undef mc68030
+#define mc68030
+#include "xm-news.h"
diff --git a/gdb/xm-np1.h b/gdb/xm-np1.h
new file mode 100644 (file)
index 0000000..0608e36
--- /dev/null
@@ -0,0 +1,99 @@
+/* Parameters for execution on a Gould NP1, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+#define SET_STACK_LIMIT_HUGE
+
+/* Address of U in kernel space */
+#define        KERNEL_U_ADDR           0x7fffc000
+
+/* This is a piece of magic that is given a register number REGNO
+   and as BLOCKEND the address in the system of the end of the user structure
+   and stores in ADDR the address in the kernel or core dump
+   of that register. */
+#define REGISTER_U_ADDR(addr, blockend, regno) {                       \
+       addr = blockend + regno * 4;                                    \
+       if (regno == VE_REGNUM) addr = blockend - 9 * 4;                \
+       if (regno == PC_REGNUM) addr = blockend - 8 * 4;                \
+       if (regno == PS_REGNUM) addr = blockend - 7 * 4;                \
+       if (regno == FP_REGNUM) addr = blockend - 6 * 4;                \
+       if (regno >= V1_REGNUM)                                         \
+           addr = blockend + 16 * 4 + (regno - V1_REGNUM) * VR_SIZE;   \
+}
+
+/* Don't try to write the frame pointer.  */
+#define CANNOT_STORE_REGISTER(regno) ((regno) == FP_REGNUM)
+
+#define MISSING_VPRINTF
+\f
+/*
+ * No KDB support, Yet! */
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/xm-pn.h b/gdb/xm-pn.h
new file mode 100644 (file)
index 0000000..f9fa986
--- /dev/null
@@ -0,0 +1,82 @@
+/* Parameters for execution on a Gould PN, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+#define SET_STACK_LIMIT_HUGE
+
+#define MISSING_VPRINTF
+
+/* Address of U in kernel space */
+#define        KERNEL_U_ADDR           0x3fc000
+\f
+/*
+ * No KDB support, Yet! */
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/xm-pyr.h b/gdb/xm-pyr.h
new file mode 100644 (file)
index 0000000..8a01569
--- /dev/null
@@ -0,0 +1,105 @@
+/* Definitions to make GDB run on a Pyramidax under OSx 4.0 (4.2bsd).
+   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Define PYRAMID_CONTROL_FRAME_DEBUGGING to get copious messages
+   about reading the control stack on standard output. This
+   makes gdb unusable as a debugger. */
+
+/* #define PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+/* Define PYRAMID_FRAME_DEBUGGING for ? */
+
+/* use Pyramid's slightly strange ptrace */
+#define PYRAMID_PTRACE
+
+/* Traditional Unix virtual address spaces have thre regions: text,
+   data and stack.  The text, initialised data, and uninitialised data
+   are represented in separate segments of the a.out file.
+   When a process dumps core, the data and stack regions are written
+   to a core file.  This gives a debugger enough information to
+   reconstruct (and debug) the virtual address space at the time of
+   the coredump.
+   Pyramids have an distinct fourth region of the virtual address
+   space, in which the contents of the windowed registers are stacked
+   in fixed-size frames.  Pyramid refer to this region as the control
+   stack.  Each call (or trap) automatically allocates a new register
+   frame; each return deallocates the current frame and restores the
+   windowed registers to their values before the call.
+
+   When dumping core, the control stack is written to a core files as
+   a third segment. The core-handling functions need to know to deal
+   with it. */ 
+
+/* Tell dep.c what the extra segment is.  */
+#define PYRAMID_CORE
+
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* Define offsets of registers in the core file (or maybe u area) */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ struct user __u;                                     \
+  addr = blockend  + (regno - 16 ) * 4;                        \
+  if (regno == 67) {                                           \
+      printf("\\geting reg 67\\");                     \
+      addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u;   \
+  } else if (regno == KSP_REGNUM) {                    \
+      printf("\\geting KSP (reg %d)\\", KSP_REGNUM);   \
+      addr = (int)(&__u.u_pcb.pcb_ksp) - (int) &__u;   \
+  } else if (regno == CSP_REGNUM) {                    \
+      printf("\\geting CSP (reg %d\\",CSP_REGNUM);     \
+      addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u;   \
+  } else if (regno == 64) {                            \
+      printf("\\geting reg 64\\");                     \
+      addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u;   \
+   } else if (regno == PS_REGNUM)                      \
+      addr = blockend - 4;                             \
+  else if (1 && ((16 > regno) && (regno > 11)))                \
+      addr = last_frame_offset + (4 *(regno+32));      \
+  else if (0 && (12 > regno))                          \
+      addr = global_reg_offset + (4 *regno);           \
+  else if (16 > regno)                                 \
+      addr = global_reg_offset + (4 *regno);           \
+ else                                                  \
+      addr = blockend  + (regno - 16 ) * 4;            \
+}
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+#define FETCH_INFERIOR_REGISTERS
+
+/* Compensate for lack of `vprintf' function.  */
+#define MISSING_VPRINTF
+
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* I have *no idea* how to debug OSx kernels, so this
+   is flushed, possible forever. */
diff --git a/gdb/xm-sparc.h b/gdb/xm-sparc.h
new file mode 100644 (file)
index 0000000..c8b9b34
--- /dev/null
@@ -0,0 +1,60 @@
+/* Parameters for execution on a Sun 4, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+   Contributed by Michael Tiemann (tiemann@mcc.com)
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Enable use of alternate code for Sun's format of core dump file.  */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands.  */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Before storing, we need to read all the registers.  */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* It does have a wait structure, and it might help things out . . . */
+
+#define HAVE_WAIT_STRUCT
+
+/* Optimization for storing registers to the inferior.  The hook
+   DO_DEFERRED_STORES
+   actually executes any deferred stores.  It is called any time
+   we are going to proceed the child, or read its registers.
+   The hook CLEAR_DEFERRED_STORES is called when we want to throw
+   away the inferior process, e.g. when it dies or we kill it.
+   FIXME, this does not handle remote debugging cleanly.  */
+
+extern int deferred_stores;
+extern int store_inferior_registers ();
+#define        DO_DEFERRED_STORES      \
+  if (deferred_stores)         \
+    store_inferior_registers (-2);
+#define        CLEAR_DEFERRED_STORES   \
+  deferred_stores = 0;
diff --git a/gdb/xm-sun2.h b/gdb/xm-sun2.h
new file mode 100644 (file)
index 0000000..278198a
--- /dev/null
@@ -0,0 +1,96 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR 0x2800
+
+/* Enable use of alternate code for Sun's format of core dump file.  */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands.  */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+#define FETCH_INFERIOR_REGISTERS
+
+/* This is a piece of magic that is given a register number REGNO
+   and as BLOCKEND the address in the system of the end of the user structure
+   and stores in ADDR the address in the kernel or core dump
+   of that register.  */
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{ addr = blockend + regno * 4; }
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea 10(sp)");        \
+  asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil $8,28(sp)");     \
+  asm ("movem (sp),$ 0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/xm-sun3.h b/gdb/xm-sun3.h
new file mode 100644 (file)
index 0000000..e67cc13
--- /dev/null
@@ -0,0 +1,93 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Enable use of alternate code for Sun's format of core dump file.  */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands.  */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We have to grab the regs since we store all regs at once.  */
+
+#define CHILD_PREPARE_TO_STORE() \
+       read_register_bytes (0, (char *)NULL, REGISTER_BYTES)
+\f
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+  0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movel #end, sp");      \
+  asm ("movel #0,a6"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("movel a6,sp@-");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl sp@,a6");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("clrw -(sp)");        \
+  asm ("pea sp@(10)");       \
+  asm ("movem #0xfffe,sp@-"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS          \
+{ asm ("subil #8,sp@(28)");     \
+  asm ("movem sp@,#0xffff"); \
+  asm ("rte"); }
diff --git a/gdb/xm-sun386.h b/gdb/xm-sun386.h
new file mode 100644 (file)
index 0000000..69b3673
--- /dev/null
@@ -0,0 +1,37 @@
+/* Parameters for execution on a Sun 386i, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Enable use of alternate code for Sun's format of core dump file.  */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands.  */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+#define FETCH_INFERIOR_REGISTERS
+
+#define PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
diff --git a/gdb/xm-sun3os4.h b/gdb/xm-sun3os4.h
new file mode 100644 (file)
index 0000000..b9ffc8d
--- /dev/null
@@ -0,0 +1,28 @@
+/* Macro definitions for a sun 3 running os 4.
+   Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "xm-sun3.h"
+#define FPU
+
+/* There is a bug which can cause alloca to fail to allocate large
+   areas of memory one time in every 4096 (we think).  */
+/* chase@orc.olivetti.com says that 4 megabyte alloca's consistently fail,
+   even though the stack limit (SET_STACK_LIMIT_HUGE) has been set
+   to 250 megabytes.  */
+#define BROKEN_LARGE_ALLOCA
diff --git a/gdb/xm-sun4os4.h b/gdb/xm-sun4os4.h
new file mode 100644 (file)
index 0000000..eaf7473
--- /dev/null
@@ -0,0 +1,22 @@
+/* Macro definitions for running gdb on a Sun 4 running sunos 4.
+   Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "xm-sparc.h"
+
+#define FPU
diff --git a/gdb/xm-symmetry.h b/gdb/xm-symmetry.h
new file mode 100644 (file)
index 0000000..c941cf0
--- /dev/null
@@ -0,0 +1,152 @@
+/* Definitions to make GDB run on a Sequent Symmetry under dynix 3.0,
+   with Weitek 1167 and i387 support.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Symmetry version by Jay Vosburgh (uunet!sequent!fubar) */
+
+/* This machine doesn't have the siginterrupt call.  */
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+/* XPT_DEBUG doesn't work yet under Dynix 3.0.12, but UNDEBUG does... */
+/* #define PTRACE_ATTACH XPT_DEBUG
+#define PTRACE_DETACH XPT_UNDEBUG
+#define ATTACH_DETACH  */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* Compensate for lack of `vprintf' function.  */
+
+#define MISSING_VPRINTF
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We must fetch all the regs before storing, since we store all at once.  */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+\f
+/* Interface definitions for kernel debugger KDB.  */
+/* This doesn't work... */
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+  0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movl $ end, %esp");      \
+  asm ("movl %ebp, $0"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("pushl %ebp");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (%esp), %ebp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm("pushad"); }
+/*
+{ asm("pushl %eax"); \
+  asm("pushl %edx"); \
+  asm("pushl %ecx"); \
+  asm("pushl %st(0)"); \
+  asm("pushl %st(1)"); \
+  asm("pushl %ebx"); \
+  asm("pushl %esi"); \
+  asm("pushl %edi"); \
+  asm("pushl %st(2)"); \
+  asm("pushl %st(3)"); \
+  asm("pushl %st(4)"); \
+  asm("pushl %st(5)"); \
+  asm("pushl %st(6)"); \
+  asm("pushl %st(7)"); \
+  asm("pushl %esp"); \
+  asm("pushl %ebp"); \
+  asm("pushl %eip"); \
+  asm("pushl %eflags"); \
+  asm("pushl %fp1"); \
+  asm("pushl %fp2"); \
+  asm("pushl %fp3"); \
+  asm("pushl %fp4"); \
+  asm("pushl %fp5"); \
+  asm("pushl %fp6"); \
+  asm("pushl %fp7"); \
+  asm("pushl %fp8"); \ 
+  asm("pushl %fp9"); \
+  asm("pushl %fp10"); \
+  asm("pushl %fp11"); \
+  asm("pushl %fp12"); \
+  asm("pushl %fp13"); \
+  asm("pushl %fp14"); \
+  asm("pushl %fp15"); \
+  asm("pushl %fp16"); \
+  asm("pushl %fp17"); \
+  asm("pushl %fp18"); \
+  asm("pushl %fp19"); \
+  asm("pushl %fp20"); \
+  asm("pushl %fp21"); \
+  asm("pushl %fp22"); \ 
+  asm("pushl %fp23"); \
+  asm("pushl %fp24"); \
+  asm("pushl %fp25"); \
+  asm("pushl %fp26"); \
+  asm("pushl %fp27"); \
+  asm("pushl %fp28"); \
+  asm("pushl %fp29"); \
+  asm("pushl %fp30"); \
+  asm("pushl %fp31"); \
+}
+*/
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS      \
+{ asm ("popad"); }
diff --git a/gdb/xm-umax.h b/gdb/xm-umax.h
new file mode 100644 (file)
index 0000000..873e808
--- /dev/null
@@ -0,0 +1,64 @@
+/* Definitions to make GDB run on an encore under umax 4.2
+   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#define HAVE_WAIT_STRUCT
+
+/* Offset of registers within u area.  */
+#define U_REGS_OFFSET 0
+
+/* Do implement the attach and detach commands...  */
+#define ATTACH_DETACH
+
+/* Doesn't have siginterupt.  */
+#define NO_SIGINTERRUPT
+
+/* called from register_addr() -- blockend not used for now */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{                                                                      \
+  switch (regno) {                                                     \
+  case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:      \
+       addr = PU_R0 - (regno * sizeof (int)); break;                   \
+  case SP_REGNUM:                                                      \
+       addr = PU_SP; break;                                            \
+  case PC_REGNUM:                                                      \
+       addr = PU_PC; break;                                            \
+  case FP_REGNUM:                                                      \
+       addr = PU_FP; break;                                            \
+  case PS_REGNUM:                                                      \
+       addr = PU_PSL; break;                                           \
+  case FPS_REGNUM:                                                     \
+       addr = PU_FSR; break;                                           \
+  case FP0_REGNUM + 0: case FP0_REGNUM + 1:                            \
+  case FP0_REGNUM + 2: case FP0_REGNUM + 3:                            \
+  case FP0_REGNUM + 4: case FP0_REGNUM + 5:                            \
+  case FP0_REGNUM + 6: case FP0_REGNUM + 7:                            \
+       addr = PU_F0 + (regno - FP0_REGNUM) * sizeof (float); break;    \
+  case LP0_REGNUM + 0: case LP0_REGNUM + 1:                            \
+  case LP0_REGNUM + 2: case LP0_REGNUM + 3:                            \
+       addr = PU_F0 + (regno - LP0_REGNUM) * sizeof (double); break;   \
+  default:                                                             \
+       printf ("bad argument to REGISTER_U_ADDR %d\n", regno);         \
+       abort ();                                                       \
+  }                                                                    \
+}
+
+/* Compensate for lack of `vprintf' function.  */
+#define MISSING_VPRINTF
diff --git a/gdb/xm-vax.h b/gdb/xm-vax.h
new file mode 100644 (file)
index 0000000..1bc6aa4
--- /dev/null
@@ -0,0 +1,90 @@
+/* Definitions to make GDB run on a vax under 4.2bsd.
+   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+#define REGISTER_U_ADDR(addr, blockend, regno)         \
+{ addr = blockend - 0110 + regno * 4;                  \
+  if (regno == PC_REGNUM) addr = blockend - 8;         \
+  if (regno == PS_REGNUM) addr = blockend - 4;         \
+  if (regno == FP_REGNUM) addr = blockend - 0120;      \
+  if (regno == AP_REGNUM) addr = blockend - 0124;      \
+  if (regno == SP_REGNUM) addr = blockend - 20; }
+
+/* Interface definitions for kernel debugger KDB.  */
+
+/* Map machine fault codes into signal numbers.
+   First subtract 0, divide by 4, then index in a table.
+   Faults for which the entry in this table is 0
+   are not handled by KDB; the program's own trap handler
+   gets to handle then.  */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE    \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+  0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+  0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+   BEG and END should be symbols meaningful to the assembler.
+   This is used only for kdb.  */
+
+#define INIT_STACK(beg, end)  \
+{ asm (".globl end");         \
+  asm ("movl $ end, sp");      \
+  asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack.  */
+#define PUSH_FRAME_PTR        \
+  asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register.  */
+#define POP_FRAME_PTR  \
+  asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+   that GDB thinks about (all NUM_REGS of them),
+   so that they appear in order of ascending GDB register number.
+   The fault code will be on the stack beyond the last register.  */
+
+#define PUSH_REGISTERS        \
+{ asm ("pushl 8(sp)");        \
+  asm ("pushl 8(sp)");        \
+  asm ("pushal 0x14(sp)");    \
+  asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+   pushed on the stack in order of ascending GDB register number,
+   restore them and return to the address in the saved PC register.  */
+
+#define POP_REGISTERS      \
+{ asm ("popr $037777");    \
+  asm ("subl2 $8,(sp)");   \
+  asm ("movl (sp),sp");    \
+  asm ("rei"); }
diff --git a/include/a.out.encap.h b/include/a.out.encap.h
new file mode 100755 (executable)
index 0000000..39c84d7
--- /dev/null
@@ -0,0 +1,172 @@
+/* Another try at encapsulating bsd object files in coff.
+   Copyright (C) 1988, 1989, Free Software Foundation, Inc.
+   Written by Pace Willisson 12/9/88
+
+   This file 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 1, or (at your option)
+   any later version.
+
+   This file 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 file; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   
+/*
+ * This time, we will only use the coff headers to tell the kernel
+ * how to exec the file.  Therefore, the only fields that need to 
+ * be filled in are the scnptr and vaddr for the text and data
+ * sections, and the vaddr for the bss.  As far as coff is concerned,
+ * there is no symbol table, relocation, or line numbers.
+ *
+ * A normal bsd header (struct exec) is placed after the coff headers,
+ * and before the real text.  I defined a the new fields 'a_machtype'
+ * and a_flags.  If a_machtype is M_386, and a_flags & A_ENCAP is
+ * true, then the bsd header is preceeded by a coff header.  Macros
+ * like N_TXTOFF and N_TXTADDR use this field to find the bsd header.
+ * 
+ * The only problem is to track down the bsd exec header.  The
+ * macros HEADER_OFFSET, etc do this.  Look at nm.c, dis.c, etc
+ * for examples.
+ */
+#ifndef A_OUT_ENCAP_H_SEEN
+#define A_OUT_ENCAP_H_SEEN
+
+#include "a.out.gnu.h"
+
+/* Figure out what our target machine is */
+#include "target.h"
+
+#define N_FLAGS_COFF_ENCAPSULATE 0x20 /* coff header precedes bsd header */
+
+/* Describe the COFF header used for encapsulation.  */
+
+struct coffheader
+{
+  /* filehdr */
+  unsigned short f_magic;
+  unsigned short f_nscns;
+  long f_timdat;
+  long f_symptr;
+  long f_nsyms;
+  unsigned short f_opthdr;
+  unsigned short f_flags;
+  /* aouthdr */
+  short magic;
+  short vstamp;
+  long tsize;
+  long dsize;
+  long bsize;
+  long entry;
+  long text_start;
+  long data_start;
+  struct coffscn
+    {
+      char s_name[8];
+      long s_paddr;
+      long s_vaddr;
+      long s_size;
+      long s_scnptr;
+      long s_relptr;
+      long s_lnnoptr;
+      unsigned short s_nreloc;
+      unsigned short s_nlnno;
+      long s_flags;
+    } scns[3];         /* text, data, bss */
+};
+\f
+/* Describe some of the parameters of the encapsulation,
+   including how to find the encapsulated BSD header.  */
+
+#if TARGET == TARGET_I386
+#define COFF_MAGIC 0514 /* I386MAGIC */
+#endif
+#if TARGET == TARGET_M68K
+#define COFF_MAGIC 0520 /* MC68MAGIC */
+#endif
+#if TARGET == TARGET_SPARC
+#define        COFF_MAGIC UNKNOWN!!!   /* Used by TTI */
+#endif
+#if TARGET == TARGET_AM29K
+#define        COFF_MAGIC 0x17A        /* Used by asm29k cross-tools */
+#endif
+
+#ifdef COFF_MAGIC
+short __header_offset_temp;
+
+/* FIXME, this is dumb.  The same tools can't handle a.outs for different
+   architectures, just because COFF_MAGIC is different; so you need a
+   separate GNU nm for every architecture!!?  Also note that for
+   expediency, this macros accepts COFF_MAGIC in either byte order.
+   The right thing to do is to call read_aout_header to handle all this.  */
+   
+#define HEADER_OFFSET(f) \
+       (__header_offset_temp = 0, \
+        fread ((char *)&__header_offset_temp, sizeof (short), 1, (f)), \
+        fseek ((f), -sizeof (short), 1), \
+        (__header_offset_temp==COFF_MAGIC || __header_offset_temp == \
+           ((COFF_MAGIC >> 8)|((COFF_MAGIC&0xFF)<<8)) \
+                   ? sizeof(struct coffheader) : 0))
+
+#define HEADER_OFFSET_FD(fd) \
+       (__header_offset_temp = 0, \
+        read (fd, (char *)&__header_offset_temp, sizeof (short)), \
+        lseek ((fd), -sizeof (short), 1), \
+        (__header_offset_temp==COFF_MAGIC || __header_offset_temp == \
+           ((COFF_MAGIC >> 8)|((COFF_MAGIC&0xFF)<<8)) \
+                   ? sizeof(struct coffheader) : 0))
+
+
+#else
+#define HEADER_OFFSET(f) 0
+#define HEADER_OFFSET_FD(fd) 0
+#endif
+
+#define HEADER_SEEK(f) (fseek ((f), HEADER_OFFSET((f)), 1))
+#define HEADER_SEEK_FD(fd) (lseek ((fd), HEADER_OFFSET_FD((fd)), 1))
+
+\f
+/* Describe the characteristics of the BSD header
+   that appears inside the encapsulation.  */
+
+#undef _N_HDROFF
+#undef N_TXTADDR
+#undef N_DATADDR
+
+/* Encapsulated coff files that are linked ZMAGIC have a text segment
+   offset just past the header (and a matching TXTADDR), excluding
+   the headers from the text segment proper but keeping the physical
+   layout and the virtual memory layout page-aligned.
+
+   Non-encapsulated a.out files that are linked ZMAGIC have a text
+   segment that starts at 0 and an N_TXTADR similarly offset to 0.
+   They too are page-aligned with each other, but they include the
+   a.out header as part of the text. 
+
+   The _N_HDROFF gets sizeof struct exec added to it, so we have
+   to compensate here.  See <a.out.gnu.h>.  */
+
+#define _N_HDROFF(x) ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
+                     sizeof (struct coffheader) : -sizeof (struct exec))
+
+/* Address of text segment in memory after it is loaded.  */
+#define N_TXTADDR(x) \
+       (TEXT_START_ADDR + \
+       ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
+        sizeof (struct coffheader) + sizeof (struct exec) : 0))
+
+/* I have no idea what this is doing here.  -- gnu@toad.com  20Mar90
+   Perhaps it is to give a size that is acceptable to any machine?  */
+#undef SEGMENT_SIZE
+#define SEGMENT_SIZE 0x400000
+
+#define N_DATADDR(x) \
+       ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
+        (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))) : \
+        (N_TXTADDR(x)+(x).a_text))
+
+#endif /* A_OUT_ENCAP_H_SEEN */
diff --git a/include/a.out.hp.h b/include/a.out.hp.h
new file mode 100755 (executable)
index 0000000..87e7219
--- /dev/null
@@ -0,0 +1,79 @@
+/* Special version of <a.out.h> for use under hp-ux.
+   Copyright (C) 1988 Free Software Foundation, Inc.
+
+   This file 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 1, or (at your option)
+   any later version.
+
+   This file 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 file; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* The `exec' structure and overall layout must be close to HP's when
+   we are running on an HP system, otherwise we will not be able to
+   execute the resulting file. */
+
+/* Allow this file to be included twice. */
+#ifndef __GNU_EXEC_MACROS__
+
+struct exec
+{
+  unsigned short a_machtype;   /* machine type */
+  unsigned short a_magic;      /* magic number */
+  unsigned long a_spare1;
+  unsigned long a_spare2;
+  unsigned long a_text;                /* length of text, in bytes */
+  unsigned long a_data;                /* length of data, in bytes */
+  unsigned long a_bss;         /* length of uninitialized data area for file, in bytes */
+  unsigned long a_trsize;      /* length of relocation info for text, in bytes */
+  unsigned long a_drsize;      /* length of relocation info for data, in bytes */
+  unsigned long a_spare3;      /* HP = pascal interface size */
+  unsigned long a_spare4;      /* HP = symbol table size */
+  unsigned long a_spare5;      /* HP = debug name table size */
+  unsigned long a_entry;       /* start address */
+  unsigned long a_spare6;      /* HP = source line table size */
+  unsigned long a_spare7;      /* HP = value table size */
+  unsigned long a_syms;                /* length of symbol table data in file, in bytes */
+  unsigned long a_spare8;
+};
+
+/* Tell a.out.gnu.h not to define `struct exec'.  */
+#define __STRUCT_EXEC_OVERRIDE__
+
+#include "../a.out.gnu.h"
+
+#undef N_MAGIC
+#undef N_MACHTYPE
+#undef N_FLAGS
+#undef N_SET_INFO
+#undef N_SET_MAGIC
+#undef N_SET_MACHTYPE
+#undef N_SET_FLAGS
+
+#define N_MAGIC(exec) ((exec) . a_magic)
+#define N_MACHTYPE(exec) ((exec) . a_machtype)
+#define N_SET_MAGIC(exec, magic) (((exec) . a_magic) = (magic))
+#define N_SET_MACHTYPE(exec, machtype) (((exec) . a_machtype) = (machtype))
+
+#undef N_BADMAG
+#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x)))
+
+#define _N_BADMACH(x)                                                  \
+(((N_MACHTYPE (x)) != HP9000S200_ID) &&                                        \
+ ((N_MACHTYPE (x)) != HP98x6_ID))
+
+#define HP98x6_ID 0x20A
+#define HP9000S200_ID 0x20C
+
+#undef _N_HDROFF
+#define _N_HDROFF(x) (SEGMENT_SIZE - (sizeof (struct exec)))
+
+#define SEGMENT_SIZE 0x1000
+
+#endif /* __GNU_EXEC_MACROS__ */
diff --git a/include/gdbm.h b/include/gdbm.h
new file mode 100644 (file)
index 0000000..b27f8e7
--- /dev/null
@@ -0,0 +1,91 @@
+/* gdbm.h  -  The include file for dbm users.  */
+
+/*  GNU DBM  - DataBase Manager (database subroutines) by Philip A. Nelson
+    Copyright (C) 1989  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.
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department
+                Western Washington University
+                Bellingham, WA 98226
+        phone:  (206) 676-3035
+       
+*************************************************************************/
+
+/* Parameters to gdbm_open for READERS, WRITERS, and WRITERS who
+   can create the database. */
+#define  GDBM_READER  0
+#define  GDBM_WRITER  1
+#define  GDBM_WRCREAT 2
+#define  GDBM_NEWDB   3
+
+/* Parameters to gdbm_store for simple insertion or replacement. */
+#define  GDBM_INSERT  0
+#define  GDBM_REPLACE 1
+
+
+/* The data and key structure.  This structure is defined for compatibility. */
+typedef struct {
+       char *dptr;
+       int   dsize;
+      } datum;
+
+
+/* The file information header. This is good enough for most applications. */
+typedef struct {int dummy[10];} *GDBM_FILE;
+
+
+/* These are the routines! */
+
+extern GDBM_FILE gdbm_open ();
+
+extern void     gdbm_close ();
+
+extern datum    gdbm_fetch ();
+
+extern int      gdbm_store ();
+
+extern int      gdbm_delete ();
+
+extern datum    gdbm_firstkey ();
+
+extern datum    gdbm_nextkey ();
+
+extern int      gdbm_reorganize ();
+
+
+/* gdbm sends back the following error codes in the variable gdbm_errno. */
+typedef enum { NO_ERROR,
+               MALLOC_ERROR,
+               BLOCK_SIZE_ERROR,
+               FILE_OPEN_ERROR,
+               FILE_WRITE_ERROR,
+               FILE_SEEK_ERROR,
+               FILE_READ_ERROR,
+               BAD_MAGIC_NUMBER,
+               EMPTY_DATABASE,
+               CANT_BE_READER,
+               CANT_BE_WRITER,
+               READER_CANT_RECOVER,
+               READER_CANT_DELETE,
+               READER_CANT_STORE,
+               READER_CANT_REORGANIZE,
+               UNKNOWN_UPDATE,
+               ITEM_NOT_FOUND,
+               REORGANIZE_FAILED,
+               CANNOT_REPLACE}
+       gdbm_error;
diff --git a/include/getopt.h b/include/getopt.h
new file mode 100644 (file)
index 0000000..1e5db6c
--- /dev/null
@@ -0,0 +1,76 @@
+/* declarations for getopt
+   Copyright (C) 1989 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Describe the long-named options requested by the application.
+   _GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+   The field `has_arg' is:
+   0 if the option does not take an argument,
+   1 if the option requires an argument,
+   2 if the option takes an optional argument.
+   If the field `flag' is nonzero, it points to a variable that is set to
+   the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.  */
+
+struct option
+{
+  char *name;
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+extern struct option *_getopt_long_options;
+
+/* Name of long-named option actually found.
+   Only changed when a long-named option is found.  */
+
+extern char *_getopt_option_name;
+
+/* The index in GETOPT_LONG_OPTIONS of the long-named option found.
+   Only valid when a long-named option has been found by the most
+   recent call to `getopt'.  */
+
+extern int option_index;
+
diff --git a/include/ranlib.h b/include/ranlib.h
new file mode 100755 (executable)
index 0000000..07bc0ab
--- /dev/null
@@ -0,0 +1,55 @@
+/*  ranlib.h -- archive library index member definition for GNU.
+    Copyright (C) 1990  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.
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* The Symdef member of an archive contains two things:
+   a table that maps symbol-string offsets to file offsets,
+   and a symbol-string table.  All the symbol names are
+   run together (each with trailing null) in the symbol-string
+   table.  There is a single longword bytecount on the front
+   of each of these tables.  Thus if we have two symbols,
+   "foo" and "_bar", that are in archive members at offsets
+   200 and 900, it would look like this:
+        16             ; byte count of index table
+       0               ; offset of "foo" in string table
+       200             ; offset of foo-module in file
+       4               ; offset of "bar" in string table
+       900             ; offset of bar-module in file
+       9               ; byte count of string table
+       "foo\0_bar\0"   ; string table  */
+
+/* Format of __.SYMDEF:
+   First, a longword containing the size of the 'symdef' data that follows.
+   Second, zero or more 'symdef' structures.
+   Third, a longword containing the length of symbol name strings.
+   Fourth, zero or more symbol name strings (each followed by a null).  */
+
+struct symdef
+  {
+    union
+      {
+       unsigned long string_offset;    /* In the file */
+       char *name;                     /* In memory, sometimes */
+      } s;
+    unsigned long file_offset;
+  };
+
+/* Compatability with BSD code */
+
+#define        ranlib  symdef
+#define        ran_un  s
+#define        ran_str string_offset
+#define        ran_name name
+#define        ran_off file_offset
diff --git a/include/stab.def b/include/stab.def
new file mode 100755 (executable)
index 0000000..58364e1
--- /dev/null
@@ -0,0 +1,182 @@
+/* Table of DBX symbol codes for the GNU system.
+   Copyright (C) 1988 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+/* Global variable.  Only the name is significant.
+   To find the address, look in the corresponding external symbol.  */
+__define_stab (N_GSYM, 0x20, "GSYM")
+
+/* Function name for BSD Fortran.  Only the name is significant.
+   To find the address, look in the corresponding external symbol.  */
+__define_stab (N_FNAME, 0x22, "FNAME")
+
+/* Function name or text-segment variable for C.  Value is its address.
+   Desc is supposedly starting line number, but GCC doesn't set it
+   and DBX seems not to miss it.  */
+__define_stab (N_FUN, 0x24, "FUN")
+
+/* Data-segment variable with internal linkage.  Value is its address.  */
+__define_stab (N_STSYM, 0x26, "STSYM")
+
+/* BSS-segment variable with internal linkage.  Value is its address.  */
+__define_stab (N_LCSYM, 0x28, "LCSYM")
+
+/* Name of main routine.  Only the name is significant.
+   This is not used in C.  */
+__define_stab (N_MAIN, 0x2a, "MAIN")
+
+/* Register variable.  Value is number of register.  */
+__define_stab (N_RSYM, 0x40, "RSYM")
+
+/* Structure or union element.  Value is offset in the structure.  */
+__define_stab (N_SSYM, 0x60, "SSYM")
+
+/* Parameter variable.  Value is offset from argument pointer.
+   (On most machines the argument pointer is the same as the frame pointer.  */
+__define_stab (N_PSYM, 0xa0, "PSYM")
+
+/* Automatic variable in the stack.  Value is offset from frame pointer.
+   Also used for type descriptions.  */
+__define_stab (N_LSYM, 0x80, "LSYM")
+
+/* Alternate entry point.  Value is its address.  */
+__define_stab (N_ENTRY, 0xa4, "ENTRY")
+
+/* Name of main source file.
+   Value is starting text address of the compilation.  */
+__define_stab (N_SO, 0x64, "SO")
+
+/* Name of sub-source file.
+   Value is starting text address of the compilation.  */
+__define_stab (N_SOL, 0x84, "SOL")
+
+/* Line number in text segment.  Desc is the line number;
+   value is corresponding address.  */
+__define_stab (N_SLINE, 0x44, "SLINE")
+/* Similar, for data segment.  */
+__define_stab (N_DSLINE, 0x66, "DSLINE")
+/* Similar, for bss segment.  */
+__define_stab (N_BSLINE, 0x68, "BSLINE")
+
+/* Beginning of an include file.  Only Sun uses this.
+   In an object file, only the name is significant.
+   The Sun linker puts data into some of the other fields.  */
+__define_stab (N_BINCL, 0x82, "BINCL")
+/* End of an include file.  No name.
+   These two act as brackets around the file's output.
+   In an object file, there is no significant data in this entry.
+   The Sun linker puts data into some of the fields.  */
+__define_stab (N_EINCL, 0xa2, "EINCL")
+/* Place holder for deleted include file.
+   This appears only in output from the Sun linker.  */
+__define_stab (N_EXCL, 0xc2, "EXCL")
+
+/* Beginning of lexical block.
+   The desc is the nesting level in lexical blocks.
+   The value is the address of the start of the text for the block.
+   The variables declared inside the block *precede* the N_LBRAC symbol.  */
+__define_stab (N_LBRAC, 0xc0, "LBRAC")
+/* End of a lexical block.  Desc matches the N_LBRAC's desc.
+   The value is the address of the end of the text for the block.  */
+__define_stab (N_RBRAC, 0xe0, "RBRAC")
+
+/* Begin named common block.  Only the name is significant.  */
+__define_stab (N_BCOMM, 0xe2, "BCOMM")
+/* Begin named common block.  Only the name is significant
+   (and it should match the N_BCOMM).  */
+__define_stab (N_ECOMM, 0xe4, "ECOMM")
+/* End common (local name): value is address.
+   I'm not sure how this is used.  */
+__define_stab (N_ECOML, 0xe8, "ECOML")
+/* Second symbol entry containing a length-value for the preceding entry.
+   The value is the length.  */
+__define_stab (N_LENG, 0xfe, "LENG")
+
+/* Global symbol in Pascal.
+   Supposedly the value is its line number; I'm skeptical.  */
+__define_stab (N_PC, 0x30, "PC")
+
+/* Modula-2 compilation unit.  Can someone say what info it contains?  */
+__define_stab (N_M2C, 0x42, "M2C")
+/* Modula-2 scope information.  Can someone say what info it contains?  */
+__define_stab (N_SCOPE, 0xc4, "SCOPE")
+
+/* Sun's source-code browser stabs.  ?? Don't know what the fields are.
+   Supposedly the field is "path to associated .cb file".  */
+__define_stab (N_BROWS, 0x48, "BROWS")
+
+/* GNU C++ exception stabs.  */
+
+/* GNU C++ exception variable.  Name is variable name.  */
+__define_stab (N_EHDECL, 0x50, "EHDECL")
+
+/* GNU C++ `catch' clause.  Value is its address.  Desc is nonzero if
+   this entry is immediately followed by a CAUGHT stab saying what exception
+   was caught.  Multiple CAUGHT stabs means that multiple exceptions
+   can be caught here.  If Desc is 0, it means all exceptions are caught
+   here.  */
+__define_stab (N_CATCH, 0x54, "CATCH")
+
+/* These STAB's are used on Gould systems for Non-Base register symbols
+   or something like that.  FIXME.  I have assigned the values at random
+   since I don't have a Gould here.  Fixups from Gould folk welcome... */
+__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
+__define_stab (N_NBDATA, 0xF2, "NBDATA")
+__define_stab (N_NBBSS,  0xF4, "NBBSS")
+__define_stab (N_NBSTS,  0xF6, "NBSTS")
+__define_stab (N_NBLCS,  0xF8, "NBLCS")
+__define_stab (N_NSYMS,  0xFA, "NSYMS")
+\f
+/* The above information, in matrix format.
+
+                       STAB MATRIX
+       _________________________________________________
+       | 00 - 1F are not dbx stab symbols              |
+       | Entries with bits 01 set are external symbols |
+       | N_UNDEF   | N_ABS     | N_TEXT    | N_DATA    |
+       | N_BSS     | N_COMM    |           | N_FN      |
+       |_______________________________________________|
+       | 20 GSYM   | 22 FNAME  | 24 FUN    | 26 STSYM  |
+       | 28 LCSYM  | 2A MAIN   | 2C        | 2E        |
+       | 30 PC     | 32        | 34        | 36        |
+       | 38        | 3A        | 3C        | 3E        |
+       | 40 RSYM   | 42 M2C    | 44 SLINE  | 46        |
+       | 48 BROWS  | 4A        | 4C        | 4E        |
+       | 50 EHDECL | 52        | 54 CATCH  | 56        |
+       | 58        | 5A        | 5C        | 5E        |
+       | 60 SSYM   | 62        | 64 SO     | 66 DSLINE |
+       | 68 BSLINE | 6A        | 6C        | 6E        |
+       | 70        | 72        | 74        | 76        |
+       | 78        | 7A        | 7C        | 7E        |
+       | 80 LSYM   | 82 BINCL  | 84 SOL    | 86        |
+       | 88        | 8A        | 8C        | 8E        |
+       | 90        | 92        | 94        | 96        |
+       | 98        | 9A        | 9C        | 9E        |
+       | A0 PSYM   | A2 EINCL  | A4 ENTRY  | A6        |
+       | A8        | AA        | AC        | AE        |
+       | B0        | B2        | B4        | B6        |
+       | B8        | BA        | BC        | BE        |
+       | C0 LBRAC  | C2 EXCL   | C4 SCOPE  | C6        |
+       | C8        | CA        | CC        | CE        |
+       | D0        | D2        | D4        | D6        |
+       | D8        | DA        | DC        | DE        |
+       | E0 RBRAC  | E2 BCOMM  | E4 ECOMM  | E6        |
+       | E8 ECOML  | EA        | EC        | EE        |
+       | F0        | F2        | F4        | F6        |
+       | F8        | FA        | FC        | FE LENG   |
+       +-----------------------------------------------+
+
+*/
diff --git a/include/stab.gnu.h b/include/stab.gnu.h
new file mode 100755 (executable)
index 0000000..77f2d41
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __GNU_STAB__
+
+/* Indicate the GNU stab.h is in use.  */
+
+#define __GNU_STAB__
+
+#define __define_stab(NAME, CODE, STRING) NAME=CODE,
+
+enum __stab_debug_code
+{
+#include "stab.def"
+};
+
+#undef __define_stab
+
+#endif /* __GNU_STAB_ */
diff --git a/ld/Makefile b/ld/Makefile
new file mode 100755 (executable)
index 0000000..51b596e
--- /dev/null
@@ -0,0 +1,195 @@
+#
+# Makefile for ld version 2
+#
+# $Id$
+#
+srcdir = ../common
+VPATH = ../common
+BASEDIR        = ../..
+HOSTDIR = ../$(HOST)/
+INCLUDE        = $(srcdir)/$(BASEDIR)/include-cygnus
+INCLUDES = -I. -I$(srcdir)  -I$(INCLUDE) 
+DEBUG  = -g
+
+
+#__sun3__#EXTRA_DEF=-DHOST_SYS=SUN3_SYS
+#__sun4__#EXTRA_DEF=-DHOST_SYS=SUN4_SYS
+
+CFLAGS = $(INCLUDES) $(EXTRA_DEF) $(DEBUG)
+LINTFLAGS =  $(INCLUDES) $(EXTRA_DEF) 
+# go directly to ld.new in case this ld isn't capable of
+# linking native object on this host.  It can be renamed on
+# install.
+PROGS  = $(HOSTDIR)/ld.new
+
+# for self hosting
+GNUTARGET=a.out-generic-big
+LDEMULATION=gld
+bfdlib=$(srcdir)/$(BASEDIR)/bfd/$(HOST)/libbfd.a
+
+OBJS= ldgram.o ldlex.o ldlang.o ldmain.o ldwrite.o ldexp.o ld-lnk960.o ld-gld68k.o \
+       ld-gld.o ld-gld960.o ld-emul.o ldversion.o ldmisc.o ldsym.o ldfile.o
+
+HEADERS=config.h ldmain.h ldmain.h ldmisc.h ldsym.h ldlang.h ldexp.h \
+       ldlex.h ldwrite.h ldversion.h ld-emul.h ldfile.h ldgram.h ld.h
+
+MANSOURCES=ld.tex
+
+LDCSOURCES=ldlang.c ldmain.c ldwrite.c ld-lnk960.c ld-gld.c ld-gld68k.c \
+       ld-gld960.c ld-emul.c ldversion.c ldmisc.c ldexp.c ldsym.c ldfile.c
+
+GENERATED_SOURCES=ldgram.tab.c ldlex.c ldgram.tab.h y.tab.h
+GENERATED_HEADERS=ldgram.tab.h
+
+LDSOURCES=$(LDCSOURCES) ldgram.y ldlex.l
+
+BFDSOURCES=../../bfd/common/*.c
+
+SOURCES= $(LDSOURCES) $(BFDSOURCES)
+LINTSOURCES=   $(LDCSOURCES) $(BFDSOURCES) $(GENERATED_SOURCES)
+
+all: Makefile $(PROGS) 
+
+
+
+$(BFDLIB): $(BFDSOURCES)
+       (cd ../bfd; make)
+
+$(PROGS): $(OBJS) $(BFDLIB)
+#      (cd ../bfd; make)
+#      LDEMULATION=gld; export LDEMULATION;  GNUTARGET=a.out-generic-big;./ldok -format a.out-generic-big  -o ld /lib/crt0.o   $(OBJS) $(bfdlib) -lc /usr/local/lib/gcc/sparc/1.91/gnulib
+#      gld -o ld /lib/crt0.o   $(OBJS) $(bfdlib) -lc /usr/local/lib/gcc/sparc/1.91/gnulib
+       $(CC) -Bstatic -o ld.new $(OBJS) $(bfdlib)
+
+
+ld1: ld
+       gcc -v  -B./ -o ld1  $(OBJS) $(bfdlib)
+
+ld2: ld1
+       mv ld1 ld
+       gcc -v  -B./ -o ld2  $(OBJS) $(bfdlib)
+
+ld3: ld2
+       mv ld2 ld
+       gcc -v  -B./ -o ld3  $(OBJS) $(bfdlib)
+
+ld.dvi:ld.tex
+       tex ld.tex
+
+ldgram.o:ldgram.y
+       yacc -d ldgram.y
+       mv y.tab.c ldgram.tab.c
+       $(CC) -c $(CFLAGS) ldgram.tab.c
+       mv ldgram.tab.o ldgram.o
+
+ldgram.tab.h:y.tab.h
+       cp y.tab.h ldgram.tab.h
+       
+ldlex.c: ldlex.l ldgram.tab.h
+ldlex.o: ldlex.c ldgram.tab.h
+
+ldmain.o: ldmain.c
+ldversion.o: ldversion.c
+ldfile.o: ldfile.c
+ldwrite.o: ldwrite.c
+ldlang.o: ldlang.c ldgram.tab.h
+ld-gld.o: ld-gld.c
+ld-gld68k.o: ld-gld68k.c
+ld-gld960.o: ld-gld960.c
+ld-emul.o:ld-emul.c
+ld-lnk960.o:ld-lnk960.c
+ldexp.o:ldexp.c ldgram.tab.h
+ldmisc.o:ldmisc.c 
+ldsym.o:ldsym.c 
+
+clean:
+       - rm -f $(OBJS) $(GENERATED_SOURCES) $(GENERATED_HEADERS)
+       - rm -f ld ld1 ld2 ld3 ld.new
+
+
+lintlog:$(SOURCES) Makefile
+       $(LINT) -abhxzn  $(LINTFLAGS)  $(LINTSOURCES) \
+| grep -v "pointer casts may be troublesome" \
+| grep -v "possible pointer alignment problem" \
+| grep -v "ignore" \
+| grep -v "conversion from long may lose accuracy" \
+| grep -v "warning: constant argument to NOT" \
+| grep -v "enumeration type clash, operator CAST" \
+| grep -v "warning: constant in conditional context"\
+| grep -v "archive\.c"
+
+
+tags TAGS:$(SOURCES) $(HEADERS)
+       etags -t $(SOURCES) $(HEADERS)
+
+release:
+       (cd /4/steve/ld; tar cf -  $(LDSOURCES) $(HEADERS) $(MANSOURCES)) | tar xf - 
+
+objdump:objdump.c 
+
+install: $(PROGS)
+       rm -f $G960BASE/bin/$(PROGS)
+       cp $(PROGS) $$G960BASE/bin/gld960c
+
+#-----------------------------------------------------------------------------
+#              'STANDARD' GNU/960 TARGETS BELOW THIS POINT
+#
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#-----------------------------------------------------------------------------
+
+ver960.c: FORCE
+       rm -f ver960.c
+       echo "char ${TARG}_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+       @V=`cat VERSION`                ; \
+       MAJ=`sed 's/\..*//' VERSION`    ; \
+       MIN=`sed 's/.*\.//' VERSION`    ; \
+       V=$$MAJ.`expr $$MIN + 1`        ; \
+       rm -f VERSION                   ; \
+       echo $$V >VERSION               ; \
+       echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+.force:
+FORCE:
+
+# Target to uncomment host-specific lines in this makefile.  Such lines must
+# have the following string beginning in column 1: #__<hostname>__#
+# Original Makefile is backed up as 'Makefile.old'.
+#
+# Invoke with:  make make HOST=xxx
+#
+make:
+       -@if test $(HOST)x = x ; then \
+               echo '\aSpecify "make make HOST=???"'; \
+               exit 1; \
+       fi ; \
+       grep -s "^#The next line was generated by 'make make'" Makefile; \
+       if test $$? = 0 ; then  \
+               echo "\aMakefile has already been processed with 'make make'";\
+               exit 1; \
+       fi ; \
+       mv -f Makefile Makefile.old; \
+       echo "#The next line was generated by 'make make'"       >Makefile ; \
+       echo "HOST=$(HOST)"                                     >>Makefile ; \
+       echo                                                    >>Makefile ; \
+       sed "s/^#__$(HOST)__#//" < Makefile.old                 >>Makefile
+
+#\f
+
+Makefile: ../common/Makefile
+       mv Makefile Makefile.backup
+       cp ../common/Makefile .
+       $(MAKE) "HOST=$(HOST)" make
+
+### Local Variables: ***
+### mode:fundamental ***
+### page-delimiter: "^#\f" ***
+### End: ***
+### end of file
diff --git a/ld/config.h b/ld/config.h
new file mode 100644 (file)
index 0000000..ca4cc87
--- /dev/null
@@ -0,0 +1,42 @@
+/* config.h -
+
+   Copyright (C) 1991 Free Software Foundation, Inc.
+
+   This file is part of GLD, the Gnu Linker.
+
+   GLD 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 1, or (at your option)
+   any later version.
+
+   GLD 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 GLD; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Look in this environment name for the linker to pretend to be */
+#define EMULATION_ENVIRON "LDEMULATION"
+/* If in there look for the strings: */
+#define GLD_EMULATION_NAME "gld"
+#define GLD68K_EMULATION_NAME "gld68k"
+#define GLD960_EMULATION_NAME "gld960"
+#define LNK960_EMULATION_NAME "lnk960"
+/* Otherwise default to this emulation */
+#define DEFAULT_EMULATION GLD68K_EMULATION_NAME
+
+
+/* Look in this variable for a target format */
+#define TARGET_ENVIRON "GNUTARGET"
+/* If not there then choose this */
+#define GLD_TARGET "a.out-generic-big"
+#define GLD68K_TARGET "a.out-generic-big"
+#define LNK960_TARGET "coff-Intel-big"
+#define GLD960_TARGET "b.out.big"
+
+
+
+
diff --git a/ld/ld-emul.c b/ld/ld-emul.c
new file mode 100755 (executable)
index 0000000..5c20791
--- /dev/null
@@ -0,0 +1,127 @@
+
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+   $Id$ 
+ *
+*/
+/*
+ * clearing house for ld emulation states 
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "config.h"
+#include "ld.h"
+#include "ld-emul.h"
+#include "ldmisc.h"
+
+extern ld_emulation_xfer_type ld_lnk960_emulation;
+extern ld_emulation_xfer_type ld_gld_emulation;
+extern ld_emulation_xfer_type ld_gld68k_emulation;
+extern ld_emulation_xfer_type ld_gld960_emulation;
+
+
+
+ld_emulation_xfer_type *ld_emulation;
+
+void
+ldemul_hll(name)
+char *name;
+{
+  ld_emulation->hll(name);
+}
+
+
+void ldemul_syslib(name)
+char *name;
+{
+  ld_emulation->syslib(name);
+}
+
+void
+ldemul_after_parse()
+{
+  ld_emulation->after_parse();
+}
+
+void
+ldemul_before_parse()
+{
+  ld_emulation->before_parse();
+}
+
+void 
+ldemul_after_allocation()
+{
+  ld_emulation->after_allocation();
+}
+
+void 
+ldemul_before_allocation()
+{
+  if (ld_emulation->before_allocation) {
+    ld_emulation->before_allocation();
+  }
+}
+
+
+void
+ldemul_set_output_arch()
+{
+  ld_emulation->set_output_arch();
+}
+
+char *
+ldemul_choose_target()
+{
+  return ld_emulation->choose_target();
+}
+
+char *
+ldemul_get_script()
+{
+  return ld_emulation->get_script();
+}
+
+void
+ldemul_choose_mode(target)
+char *target;
+{
+  if (strcmp(target,LNK960_EMULATION_NAME)==0) {
+    ld_emulation = &ld_lnk960_emulation;
+  }
+  else if (strcmp(target,GLD_EMULATION_NAME)==0) {
+    ld_emulation = &ld_gld_emulation;
+  }
+  else if (strcmp(target,GLD68K_EMULATION_NAME)==0) {
+    ld_emulation = &ld_gld68k_emulation;
+  }
+  else if (strcmp(target,GLD960_EMULATION_NAME)==0) {
+    ld_emulation = &ld_gld960_emulation;
+  }
+  else {
+    info("%P%F unrecognised emulation mode: %s",target);
+  }
+}
+
+
+
diff --git a/ld/ld-gld.c b/ld/ld-gld.c
new file mode 100755 (executable)
index 0000000..00d4493
--- /dev/null
@@ -0,0 +1,258 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ *  $Id$ 
+ *
+ *  $Log$
+ *  Revision 1.2  1991/03/22 23:02:29  steve
+ *  Brought up to sync with Intel again.
+ *
+ * Revision 1.2  1991/03/15  18:45:55  rich
+ * foo
+ *
+ * Revision 1.1  1991/03/13  00:48:11  chrisb
+ * Initial revision
+ *
+ * Revision 1.7  1991/03/10  09:31:18  rich
+ *  Modified Files:
+ *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.6  1991/03/09  03:23:12  sac
+ * Added -Ur loader script.
+ *
+ * Revision 1.5  1991/03/06  21:59:29  sac
+ * Completed G++ support
+ *
+ * Revision 1.4  1991/03/06  02:23:34  sac
+ * Added support for partial linking.
+ *
+ * Revision 1.3  1991/02/22  17:14:56  sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/* 
+ * emulate the original gld
+ *
+ *  Written by Steve Chamberlain steve@cygnus.com
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+
+#include "ld.h"
+#include "config.h"
+#include "ld-emul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+extern  boolean lang_float_flag;
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+extern bfd *output_bfd;
+
+
+
+static void gld_before_parse()
+{
+  ldfile_add_library_path("/lib");
+  ldfile_add_library_path("/usr/lib");
+  ldfile_add_library_path("/usr/local/lib/lib");
+  ldfile_output_architecture = bfd_arch_sparc;
+}
+
+
+static void 
+gld_after_parse()
+{
+
+}
+
+static void
+gld_after_allocation()
+{
+
+}
+
+static void
+gld_before_allocation()
+{
+
+}
+
+
+static void
+gld_set_output_arch()
+{
+  /* Set the output architecture and machine if possible */
+  unsigned long  machine = 0;
+  bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
+}
+
+static char *
+gld_choose_target()
+{
+  char *from_outside = getenv(TARGET_ENVIRON);
+  if (from_outside != (char *)NULL)
+    return from_outside;
+  return GLD_TARGET;
+}
+
+static void
+gld_syslib()
+{
+  info("%S SYSLIB ignored\n");
+}
+
+static void
+gld_hll(ignore)
+char  *ignore;
+{
+  info("%S HLL ignored\n");
+}
+
+static char *gld_script = "  \
+SEARCH_DIR(/lib)                       \
+SEARCH_DIR(/usr/lib)                   \
+SEARCH_DIR(/usr/local/lib)             \
+__DYNAMIC = 0;                                 \
+SECTIONS                               \
+{                                      \
+  .text 0x2020 BLOCK(0x2000):          \
+  {                                    \
+   CREATE_OBJECT_SYMBOLS               \
+    *(.text)                           \
+    _etext = ALIGN( 0x2000);           \
+    }                                          \
+  .data  ALIGN(0x2000)  :              \
+  {                                    \
+    *(.data)                           \
+    ___DTOR_LIST__=. ;                 \
+    LONG((___CTOR_LIST__ - .)/4 -2)    \
+    *(___DTOR_LIST__)                   \
+    LONG(0)                             \
+    ___CTOR_LIST__=. ;                 \
+    LONG((_edata  - .)/4 -2)            \
+    *(___CTOR_LIST__)                   \
+    LONG(0)                             \
+      _edata = .;                      \
+  }                                    \
+  .bss   SIZEOF(.data) + ADDR(.data) : \
+  {                                    \
+   *(.bss)                             \
+   [COMMON]                            \
+     _end=.;                           \
+    }                                  \
+}";
+
+
+static char *gld_script_option_Ur = "\
+SEARCH_DIR(/lib)                       \
+SEARCH_DIR(/usr/lib)                   \
+SEARCH_DIR(/usr/local/lib)             \
+SECTIONS                               \
+{                                      \
+  .text 0:                             \
+  {                                    \
+   CREATE_OBJECT_SYMBOLS                \
+    *(.text)                           \
+    }                                  \
+  .data SIZEOF(.text) + ADDR(.text) :  \
+  {                                    \
+    *(.data)                           \
+    ___DTOR_LIST__=. ;                 \
+    LONG((___CTOR_LIST__ - .)/4 -2)    \
+    *(___DTOR_LIST__)                   \
+    LONG(0)                             \
+    ___CTOR_LIST__=. ;                 \
+    LONG((___end_list__  - .)/4 -2)     \
+    *(___CTOR_LIST__)                   \
+    LONG(0)                             \
+    ___end_list__ = . ;                        \
+    }                                  \
+  .bss SIZEOF(.data) + ADDR(.data) :   \
+  {                                    \
+    *(.bss)                            \
+   [COMMON]                            \
+    }                                  \
+}                                      \
+";                          
+
+static char *gld_script_option_r = "\
+SEARCH_DIR(/lib)                       \
+SEARCH_DIR(/usr/lib)                   \
+SEARCH_DIR(/usr/local/lib)             \
+SECTIONS                               \
+{                                      \
+  .text 0:                             \
+  {                                    \
+   CREATE_OBJECT_SYMBOLS                \
+    *(.text)                           \
+    }                                  \
+  .data SIZEOF(.text) + ADDR(.text) :  \
+  {                                    \
+    *(.data)                           \
+    }                                  \
+  .bss SIZEOF(.data) + ADDR(.data) :   \
+  {                                    \
+    *(.bss)                            \
+   [COMMON]                            \
+    }                                  \
+}                                      \
+";                          
+                            
+static char *gld_get_script()
+{                           
+  extern ld_config_type config;
+  if (config.relocateable_output == true &&
+      config.build_constructors == true) {
+    return gld_script_option_Ur;
+  }
+  if (config.relocateable_output) {
+    return gld_script_option_r;
+  }
+       
+  return gld_script;
+}
+struct ld_emulation_xfer_struct ld_gld_emulation = 
+{
+  gld_before_parse,
+  gld_syslib,
+  gld_hll,
+  gld_after_parse,
+  gld_after_allocation,
+  gld_set_output_arch,
+  gld_choose_target,
+  gld_before_allocation,
+  gld_get_script,
+};
+
diff --git a/ld/ld-gld68k.c b/ld/ld-gld68k.c
new file mode 100755 (executable)
index 0000000..004594b
--- /dev/null
@@ -0,0 +1,223 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ *  $Id:#
+*/
+
+/* 
+ * emulate the original gld running on a 68k system
+ *
+ *  Written by Steve Chamberlain steve@cygnus.com
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ld.h"
+#include "config.h"
+#include "ld-emul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+extern  boolean lang_float_flag;
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+extern bfd *output_bfd;
+
+
+
+static void gld68k_before_parse()
+{
+  ldfile_add_library_path("/lib");
+  ldfile_add_library_path("/usr/lib");
+  ldfile_add_library_path("/usr/local/lib/lib");
+  ldfile_output_architecture = bfd_arch_m68k;
+}
+
+
+static void 
+gld68k_after_parse()
+{
+
+}
+
+static void
+gld68k_after_allocation()
+{
+
+}
+
+static void
+gld68k_before_allocation()
+{
+
+}
+
+
+static void
+gld68k_set_output_arch()
+{
+  /* Set the output architecture and machine if possible */
+  unsigned long  machine = 0;
+  bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
+}
+
+static char *
+gld68k_choose_target()
+{
+  char *from_outside = getenv(TARGET_ENVIRON);
+  if (from_outside != (char *)NULL)
+    return from_outside;
+  return GLD68K_TARGET;
+}
+
+static void
+gld68k_syslib()
+{
+  info("%S SYSLIB ignored\n");
+}
+
+static void
+gld68k_hll(ignore)
+char  *ignore;
+{
+  info("%S HLL ignored\n");
+}
+
+static char *gld68k_script = "  \
+SEARCH_DIR(/lib)                       \
+SEARCH_DIR(/usr/lib)                   \
+SEARCH_DIR(/usr/local/lib)             \
+__DYNAMIC = 0;                                 \
+SECTIONS                               \
+{                                      \
+  .text 0x2020 BLOCK(0x2000):          \
+  {                                    \
+   CREATE_OBJECT_SYMBOLS               \
+    *(.text)                           \
+    _etext = ALIGN( 0x2000);           \
+    }                                          \
+  .data  ALIGN(0x20000)  :             \
+  {                                    \
+    *(.data)                           \
+    ___DTOR_LIST__=. ;                 \
+    LONG((___CTOR_LIST__ - .)/4 -2)    \
+    *(___DTOR_LIST__)                   \
+    LONG(0)                             \
+    ___CTOR_LIST__=. ;                 \
+    LONG((_edata  - .)/4 -2)            \
+    *(___CTOR_LIST__)                   \
+    LONG(0)                             \
+      _edata = .;                      \
+  }                                    \
+  .bss   SIZEOF(.data) + ADDR(.data) : \
+  {                                    \
+   *(.bss)                             \
+   [COMMON]                            \
+     _end=.;                           \
+    }                                  \
+}";
+
+
+static char *gld68k_script_option_Ur = "\
+SEARCH_DIR(/lib)                       \
+SEARCH_DIR(/usr/lib)                   \
+SEARCH_DIR(/usr/local/lib)             \
+SECTIONS                               \
+{                                      \
+  .text 0:                             \
+  {                                    \
+   CREATE_OBJECT_SYMBOLS                \
+    *(.text)                           \
+    }                                  \
+  .data SIZEOF(.text) + ADDR(.text) :  \
+  {                                    \
+    *(.data)                           \
+    ___DTOR_LIST__=. ;                 \
+    LONG((___CTOR_LIST__ - .)/4 -2)    \
+    *(___DTOR_LIST__)                   \
+    LONG(0)                             \
+    ___CTOR_LIST__=. ;                 \
+    LONG((___end_list__  - .)/4 -2)     \
+    *(___CTOR_LIST__)                   \
+    LONG(0)                             \
+    ___end_list__ = . ;                        \
+    }                                  \
+  .bss SIZEOF(.data) + ADDR(.data) :   \
+  {                                    \
+    *(.bss)                            \
+   [COMMON]                            \
+    }                                  \
+}                                      \
+";                          
+
+static char *gld68k_script_option_r = "\
+SEARCH_DIR(/lib)                       \
+SEARCH_DIR(/usr/lib)                   \
+SEARCH_DIR(/usr/local/lib)             \
+SECTIONS                               \
+{                                      \
+  .text 0:                             \
+  {                                    \
+   CREATE_OBJECT_SYMBOLS                \
+    *(.text)                           \
+    }                                  \
+  .data SIZEOF(.text) + ADDR(.text) :  \
+  {                                    \
+    *(.data)                           \
+    }                                  \
+  .bss SIZEOF(.data) + ADDR(.data) :   \
+  {                                    \
+    *(.bss)                            \
+   [COMMON]                            \
+    }                                  \
+}                                      \
+";                          
+                            
+static char *gld68k_get_script()
+{                           
+  extern ld_config_type config;
+  if (config.relocateable_output == true &&
+      config.build_constructors == true) {
+    return gld68k_script_option_Ur;
+  }
+  if (config.relocateable_output) {
+    return gld68k_script_option_r;
+  }
+       
+  return gld68k_script;
+}
+struct ld_emulation_xfer_struct ld_gld68k_emulation = 
+{
+  gld68k_before_parse,
+  gld68k_syslib,
+  gld68k_hll,
+  gld68k_after_parse,
+  gld68k_after_allocation,
+  gld68k_set_output_arch,
+  gld68k_choose_target,
+  gld68k_before_allocation,
+  gld68k_get_script,
+};
+
diff --git a/ld/ld-gld960.c b/ld/ld-gld960.c
new file mode 100755 (executable)
index 0000000..0577fa4
--- /dev/null
@@ -0,0 +1,189 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+   $Id$ 
+
+   $Log$
+   Revision 1.2  1991/03/22 23:02:30  steve
+   Brought up to sync with Intel again.
+
+ * Revision 1.3  1991/03/16  22:27:24  rich
+ * fish
+ *
+ * Revision 1.2  1991/03/15  18:45:55  rich
+ * foo
+ *
+ * Revision 1.1  1991/03/13  00:48:12  chrisb
+ * Initial revision
+ *
+ * Revision 1.4  1991/03/10  09:31:19  rich
+ *  Modified Files:
+ *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.3  1991/02/22  17:14:57  sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/* 
+ * emulate the Intels port of  gld
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+
+#include "ld.h"
+#include "config.h"
+#include "ld-emul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+
+/* IMPORTS */
+extern char *output_filename;
+extern  boolean lang_float_flag;
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+extern bfd *output_bfd;
+
+
+
+static void gld960_before_parse()
+{
+  char *env ;
+  env =  getenv("G960LIB");
+  if (env) {
+    ldfile_add_library_path(env);
+  }
+  env = getenv("G960BASE");
+  if (env) {
+    ldfile_add_library_path(concat(env,"/lib",""));
+  }
+  ldfile_output_architecture = bfd_arch_i960;
+}
+
+
+static void 
+gld960_after_parse()
+{
+
+}
+
+static void
+gld960_after_allocation()
+{
+
+}
+
+static void
+gld960_before_allocation()
+{
+
+}
+
+
+static void
+gld960_set_output_arch()
+{
+  /* Set the output architecture and machine if possible */
+  unsigned long  machine = 0;
+  bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
+}
+
+static char *
+gld960_choose_target()
+{
+  char *from_outside = getenv(TARGET_ENVIRON);
+  output_filename = "b.out";
+
+  if (from_outside != (char *)NULL)
+    return from_outside;
+  return GLD960_TARGET;
+}
+
+static void
+gld960_syslib()
+{
+  info("%S SYSLIB ignored\n");
+}
+
+static void
+gld960_hll()
+{
+  info("%S HLL ignored\n");
+}
+
+
+static char *script = "\
+ \
+SECTIONS \
+{ \
+  .text : \
+  { \
+   CREATE_OBJECT_SYMBOLS \
+    *(.text) \
+      _etext =.;\
+    }  \
+ \
+  .data  SIZEOF(.text) + ADDR(.text):\
+  { \
+ \
+    *(.data) \
+      _edata = .; \
+    }  \
+  .bss   SIZEOF(.data) + ADDR(.data) :    \
+  { _bss_start = .;\
+      *(.bss)   \
+       [COMMON] \
+      _end = . ; \
+    } \
+} \
+";
+
+static char *
+gld960_get_script()
+{
+return script;
+}
+
+struct ld_emulation_xfer_struct ld_gld960_emulation = 
+{
+  gld960_before_parse,
+  gld960_syslib,
+  gld960_hll,
+  gld960_after_parse,
+  gld960_after_allocation,
+  gld960_set_output_arch,
+  gld960_choose_target,
+  gld960_before_allocation,
+  gld960_get_script,
+};
diff --git a/ld/ld-lnk960.c b/ld/ld-lnk960.c
new file mode 100755 (executable)
index 0000000..2e012c8
--- /dev/null
@@ -0,0 +1,322 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+   $Id$ 
+
+   $Log$
+   Revision 1.2  1991/03/22 23:02:31  steve
+   Brought up to sync with Intel again.
+
+ * Revision 1.2  1991/03/15  18:45:55  rich
+ * foo
+ *
+ * Revision 1.1  1991/03/13  00:48:13  chrisb
+ * Initial revision
+ *
+ * Revision 1.6  1991/03/10  09:31:20  rich
+ *  Modified Files:
+ *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.5  1991/03/09  03:23:47  sac
+ * Now looks in G960BASE if I960BASE isn't defined.
+ *
+ * Revision 1.4  1991/03/06  02:23:35  sac
+ * Added support for partial linking.
+ *
+ * Revision 1.3  1991/02/22  17:14:58  sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/* 
+
+   Written by Steve Chamberlain steve@cygnus.com
+
+ * intel coff loader emulation specific stuff
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+/*#include "archures.h"*/
+#include "ld.h"
+#include "config.h"
+#include "ld-emul.h"
+#include "ldmisc.h"
+#include "ldlang.h"
+#include "ldfile.h"
+
+extern  boolean lang_float_flag;
+extern bfd *output_bfd;
+
+
+
+extern enum bfd_architecture ldfile_output_architecture;
+extern unsigned long ldfile_output_machine;
+extern char *ldfile_output_machine_name;
+
+
+typedef struct lib_list {
+  char *name;
+  struct lib_list *next;
+} lib_list_type;
+
+static lib_list_type *hll_list;
+static lib_list_type **hll_list_tail = &hll_list;
+
+static lib_list_type *syslib_list;
+static lib_list_type **syslib_list_tail = &syslib_list;
+
+
+static void
+append(list, name)
+lib_list_type ***list;
+char *name;
+{
+  lib_list_type *element = 
+    (lib_list_type *)(ldmalloc(sizeof(lib_list_type)));
+
+  element->name = name;
+  element->next = (lib_list_type *)NULL;
+  **list = element;
+  *list = &element->next;
+
+}
+
+static boolean had_hll = false;
+static boolean had_hll_name = false;
+static void
+lnk960_hll(name)
+char *name;
+{
+  had_hll = true;
+  if (name != (char *)NULL) {
+    had_hll_name = true;
+    append(&hll_list_tail, name);
+  }
+}
+
+static void 
+lnk960_syslib(name)
+char *name;
+{
+  append(&syslib_list_tail,name);
+}
+
+
+
+static void 
+lnk960_before_parse()
+{
+  char *name = getenv("I960BASE");
+
+  if (name == (char *)NULL) {
+    name = getenv("G960BASE");
+    if (name == (char *)NULL) {
+      info("%P%F I960BASE and G960BASE not set\n");
+    }
+  }
+
+
+  ldfile_add_library_path(concat(name,"/lib",""));
+  ldfile_output_architecture = bfd_arch_i960;
+  ldfile_output_machine = bfd_mach_i960_core;
+}
+
+static void
+add_on(list, search)
+lib_list_type *list;
+lang_input_file_enum_type search;
+{
+  while (list) {
+    lang_add_input_file(list->name,
+                       search,
+                       (char *)NULL);
+    list = list->next;
+  }
+}
+static void lnk960_after_parse()
+{
+
+  /* If there has been no arch, default to -KB */
+  if (ldfile_output_machine_name[0] ==0) {
+    ldfile_add_arch("kb");
+  }
+
+  /* if there has been no hll list then add our own */
+
+  if(had_hll && !had_hll_name) {
+    append(&hll_list_tail,"c");
+    if (lang_float_flag == true) {
+      append(&hll_list_tail,"m");
+    }
+    else {
+      append(&hll_list_tail,"mstub");
+    }
+    if (ldfile_output_machine == bfd_mach_i960_ka_sa ||
+       ldfile_output_machine == bfd_mach_i960_ca) {
+      {
+       append(&hll_list_tail,"f");
+      }
+    }
+  }
+
+
+
+  add_on(hll_list, lang_input_file_is_l_enum);
+  add_on(syslib_list, lang_input_file_is_search_file_enum);
+
+
+}
+
+static void
+lnk960_before_allocation()
+{
+}
+static void
+lnk960_after_allocation()
+{
+  lang_abs_symbol_at_end_of(".text","_etext");
+  lang_abs_symbol_at_end_of(".data","_edata");
+  lang_abs_symbol_at_beginning_of(".bss","_bss_start");
+  lang_abs_symbol_at_end_of(".bss","_end");
+}
+
+static struct
+ {
+   unsigned  long number;
+   char *name; 
+ }
+machine_table[] = {
+       bfd_mach_i960_core      ,"CORE",
+       bfd_mach_i960_kb_sb     ,"KB",
+       bfd_mach_i960_kb_sb     ,"SB",
+       bfd_mach_i960_mc        ,"MC",
+       bfd_mach_i960_xa        ,"XA",
+       bfd_mach_i960_ca        ,"CA",
+       bfd_mach_i960_ka_sa     ,"KA",
+       bfd_mach_i960_ka_sa     ,"SA",
+
+       bfd_mach_i960_core      ,"core",
+       bfd_mach_i960_kb_sb     ,"kb",
+       bfd_mach_i960_kb_sb     ,"sb",
+       bfd_mach_i960_mc        ,"mc",
+       bfd_mach_i960_xa        ,"xa",
+       bfd_mach_i960_ca        ,"ca",
+       bfd_mach_i960_ka_sa     ,"ka",
+       bfd_mach_i960_ka_sa     ,"sa",
+       0,(char *)NULL
+};
+
+static void
+lnk960_set_output_arch()
+{
+  /* Set the output architecture and machine if possible */
+  unsigned int i;
+  ldfile_output_machine = bfd_mach_i960_core;
+  for (i= 0; machine_table[i].name != (char*)NULL; i++) {
+    if (strcmp(ldfile_output_machine_name,machine_table[i].name)==0) {
+      ldfile_output_machine = machine_table[i].number;
+      break;
+    }
+  }
+  bfd_set_arch_mach(output_bfd, ldfile_output_architecture, ldfile_output_machine);
+}
+
+static char *
+lnk960_choose_target()
+{
+  char *from_outside = getenv(TARGET_ENVIRON);
+  if (from_outside != (char *)NULL)
+    return from_outside;
+  return LNK960_TARGET;
+}
+
+/* The default script if none is offered */
+static char *lnk960_script = "\
+SECTIONS \
+{ \
+  .text : \
+  { \
+    *(.text) \
+    }  \
+_etext = .;\
+  .data  SIZEOF(.text) + ADDR(.text):\
+  { \
+    *(.data) \
+    }  \
+_edata = .; \
+  .bss   SIZEOF(.data) + ADDR(.data) :    \
+  { \
+   _bss_start = . ;\
+   *(.bss)  \
+   [COMMON] \
+    } \
+_end = . ; \
+} \
+";
+
+static char *lnk960_script_relocateable = "\
+SECTIONS \
+{ \
+  .text 0x40000000: \
+  { \
+    *(.text) \
+    }  \
+  .data  0:\
+  { \
+    *(.data) \
+    }  \
+  .bss   SIZEOF(.data) + ADDR(.data) :    \
+  { \
+   *(.bss)  \
+   [COMMON] \
+    } \
+} \
+";
+
+static char *lnk960_get_script()
+{
+extern ld_config_type config;
+if (config.relocateable_output) {
+  return lnk960_script_relocateable;
+}
+return lnk960_script;
+
+
+}
+struct ld_emulation_xfer_struct ld_lnk960_emulation = 
+{
+  lnk960_before_parse,
+  lnk960_syslib,
+  lnk960_hll,
+  lnk960_after_parse,
+  lnk960_after_allocation,
+  lnk960_set_output_arch,
+  lnk960_choose_target,
+  lnk960_before_allocation,
+  lnk960_get_script,
+};
diff --git a/ld/ld.tex b/ld/ld.tex
new file mode 100755 (executable)
index 0000000..1764ad5
--- /dev/null
+++ b/ld/ld.tex
@@ -0,0 +1,1014 @@
+\input texinfo
+@parindent=0pt
+@setfilename gld
+@c @@setchapternewpage odd
+@settitle GLD, The GNU linker
+@titlepage
+@title{gld}
+@subtitle{The gnu loader}
+@sp 1
+@subtitle Second Edition---gld version 2.0
+@subtitle January 1991
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991 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.
+
+@author {Steve Chamberlain}
+@author {Cygnus Support}
+@author {steve@@cygnus.com}
+@end titlepage
+
+@node Top,,,
+@comment  node-name,  next,  previous,  up
+@ifinfo
+This file documents the GNU linker gld.
+@end ifinfo
+
+@c chapter What does a linker do ?
+@c chapter Command Language
+@noindent
+@chapter Overview
+
+
+The @code{gld} command combines a number of object and archive files,
+relocates their data and ties up symbol references. Often the last
+step in building a new compiled program to run is a call to @code{gld}.
+
+The @code{gld} command accepts Linker Command Language files in
+a superset of AT+T's Link Editor Command Language syntax,
+to provide explict and total control over the linking process.
+
+This version of @code{gld} uses the general purpose @code{bfd} libraries
+to operate on object files. This allows @code{gld} to read and
+write any of the formats supported by @code{bfd}, different
+formats may be linked together producing any available object file. 
+
+Supported formats:
+@itemize @bullet
+@item
+Sun3 68k a.out
+@item 
+IEEE-695 68k Object Module Format
+@item 
+Oasys 68k Binary Relocatable Object File Format
+@item 
+Sun4 sparc a.out
+@item 
+88k bcs coff
+@item 
+i960 coff little endian
+@item 
+i960 coff big endian
+@item 
+i960 b.out little endian
+@item 
+i960 b.out big endian
+@item
+s-records
+@end itemize
+When linking similar formats, @code{gld} maintains all debugging
+information. 
+
+@chapter Command line options
+
+@example
+  gld [ -Bstatic ]  [ -D @var{datasize} ] 
+      [ -c @var{filename} ]
+      [ -d ]  | [ -dc ] | [ -dp ]
+      [ -i ]
+      [ -e @var{entry} ]  [ -l @var{arch} ]  [ -L @var{searchdir} ]  [ -M ]  
+      [ -N | -n | -z ]  [ -noinhibit-exec ]  [ -r ]  [ -S ]  [ -s ]  
+      [ -f @var{fill} ]
+      [ -T @var{textorg} ]  [ -Tdata @var{dataorg} ]  [ -t ]  [ -u @var{sym}]
+      [ -X ]  [ -x ] 
+      [-o @var{output} ] @var{objfiles}@dots{}
+@end example
+
+Command-line options to GNU @code{gld} may be specified in any order, and
+may be repeated at will.  For the most part, repeating an option with a
+different argument will either have no further effect, or override prior
+occurrences (those further to the left on the command line) of an
+option.  
+
+The exceptions which may meaningfully be present several times
+are @code{-L}, @code{-l}, and @code{-u}.
+
+@var{objfiles} may follow, precede, or be mixed in with
+command-line options; save that an @var{objfiles} argument may not be
+placed between an option flag and its argument.
+
+Option arguments must follow the option letter without intervening
+whitespace, or be given as separate arguments immediately following the
+option that requires them.
+
+@table @code
+@item @var{objfiles}@dots{}
+The object files @var{objfiles} to be linked; at least one must be specified.
+
+@item -Bstatic 
+This flag is accepted for command-line compatibility with the SunOS linker,
+but has no effect on @code{gld}.
+
+@item -c @var{commandfile}
+Directs @code{gld} to read linkage commands from the file @var{commandfile}.
+
+@item -D @var{datasize}
+Use this option to specify a target size for the @code{data} segment of
+your linked program.  The option is only obeyed if @var{datasize} is
+larger than the natural size of the program's @code{data} segment.
+
+@var{datasize} must be an integer specified in hexadecimal.
+
+@code{ld} will simply increase the size of the @code{data} segment,
+padding the created gap with zeros, and reduce the size of the
+@code{bss} segment to match.
+
+@item -d
+Force @code{ld} to assign space to common symbols
+even if a relocatable output file is specified (@code{-r}).
+
+@item -dc | -dp
+This flags is accepted for command-line compatibility with the SunOS linker,
+but has no effect on @code{gld}.
+
+@item -e @var{entry} 
+Use @var{entry} as the explicit symbol for beginning execution of your
+program, rather than the default entry point. If this symbol is
+not specified, the symbol @code{start} is used as the entry address.
+If there is no symbol called @code{start}, then the entry address
+is set to the first address in the first output section 
+(usually the @samp{text} section).
+
+@item -f @var{fill}
+Sets the default fill pattern for ``holes'' in the output file to
+the lowest two bytes of the expression specified.
+
+@item -i
+Produce an incremental link (same as option @code{-r}).
+
+@item -l @var{arch} 
+Add an archive file @var{arch} to the list of files to link.  This 
+option may be used any number of times.  @code{ld} will search its
+path-list for occurrences of @code{lib@var{arch}.a} for every @var{arch}
+specified.
+
+@c This also has a side effect of using the "c++ demangler" if we happen
+@c to specify -llibg++.  Document?  pesch@@cygnus.com, 24jan91
+
+@item -L @var{searchdir} 
+This command adds path @var{searchdir} to the
+list of paths that @code{gld} will search for archive libraries.  You
+may use this option any number of times.
+
+@c Should we make any attempt to list the standard paths searched
+@c without listing?  When hacking on a new system I often want to know
+@c this, but this may not be the place... it's not constant across
+@c systems, of course, which is what makes it interesting.
+@c pesch@@cygnus.com, 24jan91.
+
+@item -M 
+@itemx -m
+Print (to the standard output file) a link map---diagnostic information
+about where symbols are mapped by @code{ld}, and information on global
+common storage allocation.
+
+@item -N 
+specifies read and writable @code{text} and @code{data} sections. If
+the output format supports Unix style magic numbers, then OMAGIC is set.
+
+@item -n 
+sets the text segment to be read only, and @code{NMAGIC} is written
+if possible.
+
+@item -o @var{output}
+@var{output} is a name for the program produced by @code{ld}; if this
+option is not specified, the name @samp{a.out} is used by default.
+
+@item -r 
+Generates relocatable output---i.e., generate an output file that can in
+turn serve as input to @code{gld}.  As a side effect, this option also
+sets the output file's magic number to @code{OMAGIC}; see @samp{-N}. If this
+option is not specified, an absolute file is produced.
+
+@item -S 
+Omits debugger symbol information (but not all symbols) from the output file.
+
+@item -s 
+Omits all symbol information from the output file.
+
+@item -T @var{textorg} 
+@itemx -Ttext @var{textorg}
+Use @var{textorg} as the starting address for the @code{text} segment of the
+output file.  Both forms of this option are equivalent.  The option
+argument must be a hexadecimal integer.
+
+@item -Tdata @var{dataorg} 
+Use @var{dataorg} as the starting address for the @code{data} segment of
+the output file.  The option argument must be a hexadecimal integer.
+
+@item -t 
+Prints names of input files as @code{ld} processes them.
+
+@item -u @var{sym}
+Forces @var{sym} to be entered in the output file as an undefined symbol.
+This may, for example, trigger linking of additional modules from
+standard libraries.  @code{-u} may be repeated with different option
+arguments to enter additional undefined symbols. This option is equivalent
+to the @code{EXTERN} linker command.
+
+@item -X 
+If @code{-s} or @code{-S} is also specified, delete only local symbols
+beginning with @samp{L}.
+
+@item -z
+@code{-z} sets @code{ZMAGIC}, the default: the @code{text} segment is
+read-only, demand pageable, and shared.  
+
+Specifying a relocatable output file (@code{-r}) will also set the magic
+number to @code{OMAGIC}.
+
+See description of @samp{-N}.
+
+
+@end table
+@chapter Command Language
+
+
+The command language allows explicit control over the linkage process, allowing
+specification of:
+@table @bullet
+@item input files 
+@item file formats
+@item output file format
+@item addresses of sections
+@item placement of common blocks
+@item and more
+@end table
+
+A command file may be supplied to the linker, either explicitly through the
+@code{-c} option, or implicitly as an ordinary file. If the linker opens
+a file which does not have a reasonable object or archive format, it tries
+to read the file as if it were a command file.
+@section Structure
+To be added
+
+@section Expressions
+The syntax for expressions in the command language is identical to that of
+C expressions, with the following features:
+@table @bullet
+@item All expressions evaluated as integers and
+are of ``long'' or ``unsigned long'' type.
+@item All constants are integers.
+@item All of the C arithmetic operators are provided.
+@item Global variables may be referenced, defined and created.
+@item Build in functions may be called.
+@end table
+
+@section Expressions
+
+The linker has a practice of ``lazy evaluation'' for expressions; it only
+calculates an expression when absolutely necessary. For instance, 
+when the linker reads in the command file it has to know the values
+of the start address and the length of the memory regions for linkage to continue, so these
+values are worked out, but other values (such as symbol values) are not
+known or needed until after storage allocation.
+They are evaluated later, when the other
+information, such as the sizes of output sections are available for use in
+the symbol assignment expression.
+
+When a linker expression is evaluated and assigned to a variable it is given
+either an absolute or a relocatable type. An absolute expression type
+is one in which the symbol contains the value that it will have in the
+output file, a relocateable expression type is one in which the value
+is expressed as a fixed offset from the base of a section.
+
+The type of the expression is controlled by its position in the script
+file. A symbol assigned within a @code{SECTION} specification is
+created relative to the base of the section, a symbol assigned in any
+other place is created as an absolute symbol. Since a symbol created
+within a @code{SECTION} specification is relative to the base of the
+section it will remain relocatable if relocatable output is requested.
+A symbol may be created with an absolute value even when assigned to
+within a @code{SECTION} specification by using the absolute assignment
+function @code{ABSOLUTE} For example, to create an absolute symbol
+whose address is the last byte of the output section @code{.data}:
+@example
+.data : 
+        @{
+                *(.data)
+                _edata = ABSOLUTE(.) ;
+        @} 
+@end example
+
+Unless quoted, symbol names start with a letter, underscore, point or
+minus sign and may include any letters, underscores, digits, points,
+and minus signs.  Unquoted symbol names must not conflict with any
+keywords.  To specify a symbol which contains odd characters or has
+the same name as a keyword surround it in double quotes:
+@example
+        ``SECTION'' = 9;
+        ``with a space'' = ``also with a space'' + 10;
+@end example
+
+@subsection Integers
+An octal integer is @samp{0} followed by zero or more of the octal
+digits (@samp{01234567}).
+
+A decimal integer starts with a non-zero digit followed by zero or
+more digits (@samp{0123456789}).
+
+A hexadecimal integer is @samp{0x} or @samp{0X} followed by one or
+more hexadecimal digits chosen from @samp{0123456789abcdefABCDEF}.
+
+Integers have the usual values.  To denote a negative integer, use
+the unary operator @samp{-} discussed under expressions.
+
+Additionally the suffixes @code{K} and @code{M} may be used to multiply the
+previous constant by 1024 or 
+@tex
+$1024^2$
+@end tex
+respectively.
+
+@example
+        _as_decimal = 57005;
+        _as_hex = 0xdead;
+        _as_octal = 0157255;
+
+        _4k_1 = 4K;
+        _4k_2 = 4096;
+        _4k_3 = 0x1000;
+@end example
+@subsection Operators
+The linker provides the standard C set of arithmetic operators, with
+the standard bindings and precedence levels:
+@example
+
+@end example
+@tex
+
+\vbox{\offinterlineskip
+\hrule
+\halign
+{\vrule#&\hfil#\hfil&\vrule#&\hfil#\hfil&\vrule#&\hfil#\hfil&\vrule#\cr
+height2pt&&&&&\cr
+&Level&&  associativity  &&Operators&\cr
+height2pt&&&&&\cr
+\noalign{\hrule}
+height2pt&&&&&\cr
+&highest&&&&&&\cr
+&1&&left&&$ ! -         ~$&\cr
+height2pt&&&&&\cr
+&2&&left&&*        /        \%&\cr
+height2pt&&&&&\cr
+&3&&left&&+        -&\cr
+height2pt&&&&&\cr
+&4&&left&&$>> <<$&\cr
+height2pt&&&&&\cr
+&5&&left&&$==        !=        > < <= >=$&\cr
+height2pt&&&&&\cr
+&6&&left&&\&&\cr
+height2pt&&&&&\cr
+&7&&left&&|&\cr
+height2pt&&&&&\cr
+&8&&left&&{\&\&}&\cr
+height2pt&&&&&\cr
+&9&&left&&||&\cr
+height2pt&&&&&\cr
+&10&&right&&? :&\cr
+height2pt&&&&&\cr
+&11&&right&&$${\&=        +=        -=        *=        /=}&\cr
+&lowest&&&&&&\cr
+height2pt&&&&&\cr}
+\hrule}
+@end tex
+
+@section Built in Functions
+The command language provides built in functions for use in
+expressions in linkage scripts.
+@table @bullet 
+@item @code{ALIGN(@var{exp})}
+returns the result of the current location counter (@code{dot})
+aligned to the next @var{exp} boundary, where @var{exp} is a power of
+two.  This is equivalent to @code{(. + @var{exp} -1) & ~(@var{exp}-1)}.
+As an example, to align the output @code{.data} section to the
+next 0x2000 byte boundary after the preceding section and to set a
+variable within the section to the next 0x8000 boundary after the
+input sections:
+@example
+        .data ALIGN(0x2000) :@{
+                *(.data)
+                variable = ALIGN(0x8000);
+        @}
+@end example
+
+@item @code{ADDR(@var{section name})}
+returns the absolute address of the named section if the section has
+already been bound. In the following examples the @code{symbol_1} and
+@code{symbol_2} are assigned identical values:
+@example
+        .output1:
+                @{ 
+                start_of_output_1 $= .;
+                ... 
+                @}
+        .output:
+                @{
+                symbol_1 = ADDR(.output1);
+                symbol_2 = start_of_output_1;
+                @}
+@end example
+
+@item @code{SIZEOF(@var{section name})}
+returns the size in bytes of the named section, if the section has
+been allocated.  In the following example the @code{symbol_1} and
+@code{symbol_2} are assigned identical values:
+@example
+        .output @{
+                .start = . ;
+                ...
+                .end = .;
+                @}
+        symbol_1 = .end - .start;
+        symbol_2 = SIZEOF(.output);
+@end example
+
+@item @code{DEFINED(@var{symbol name})}
+Returns 1 if the symbol is in the linker global symbol table and is
+defined, otherwise it returns 0. This example shows the setting of a
+global symbol @code{begin} to the first location in the @code{.text}
+section, only if there is no other symbol
+called @code{begin} already:
+@example
+        .text: @{
+                begin = DEFINED(begin) ? begin : . ;
+                ...
+        @}
+@end example
+@end table 
+@page
+@section MEMORY Directive
+The linker's default configuration is for all memory to be
+allocatable.  This state may be overridden by using the @code{MEMORY}
+directive.  The @code{MEMORY} directive describes the location and
+size of blocks of memory in the target.  Careful use can describe
+memory regions which may or may not be used by the linker. The linker
+does not shuffle sections to fit into the available regions, but does
+move the requested sections into the correct regions and issue errors
+when the regions become too full.  The syntax is:
+       
+@example
+        MEMORY 
+                @{
+@tex
+                 $\bigl\lbrace {\it name_1} ({\it attr_1}):$ ORIGIN = ${\it origin_1},$ LENGTH $= {\it len_1} \bigr\rbrace $
+@end tex
+
+                @}
+@end example
+@table @code
+@item @var{name}
+is a name used internally by the linker to refer to the region. Any
+symbol name may be used.  The region names are stored in a separate
+name space, and will not conflict with symbols, filenames or section
+names.
+@item @var{attr}
+is an optional list of attributes, parsed for compatibility with the
+AT+T linker
+but ignored by the both the AT+T and the gnu linker.
+@item @var{origin}
+is the start address of the region in physical memory expressed as
+standard linker expression which must evaluate to a constant before
+memory allocation is performed. The keyword @code{ORIGIN} may be
+abbreviated to @code{org} or @code{o}.
+@item @var{len}
+is the size in bytes of the region as a standard linker expression.
+The keyword @code{LENGTH} may be abbreviated to @code{len} or @code{l}
+@end table 
+
+For example, to specify that memory has two regions available for
+allocation; one starting at 0 for 256k, and the other starting at
+0x40000000 for four megabytes:
+
+@example
+        MEMORY 
+                @{
+                rom : ORIGIN= 0, LENGTH = 256K
+                ram : ORIGIN= 0x40000000, LENGTH = 4M
+                @}
+
+@end example
+
+If the combined output sections directed to a region are too big for
+the region the linker will emit an error message.
+@page
+@section SECTIONS Directive
+The @code{SECTIONS} directive 
+controls exactly where input sections are placed into output sections, their
+order and to which output sections they are allocated.
+
+When no @code{SECTIONS} directives are specified, the default action
+of the linker is to place each input section into an identically named
+output section in the order that the sections appear in the first
+file, and then the order of the files.
+
+The syntax of the @code{SECTIONS} directive is:
+
+@example
+   SECTIONS
+   @{
+@tex
+    $\bigl\lbrace {\it name_n}\bigl[options\bigr]\colon$ $\bigl\lbrace {\it statements_n} \bigr\rbrace \bigl[ = {\it fill expression } \bigr] \bigl[ > mem spec \bigr] \bigr\rbrace $
+@end tex
+   @}
+@end example
+
+@table @code
+@item @var{name}
+controls the name of the output section. In formats which only support
+a limited number of sections, such as @code{a.out}, the name must be
+one of the names supported by the format (in the case of a.out,
+@code{.text}, @code{.data} or @code{.bss}). If the output format
+supports any number of sections, but with numbers and not names (in
+the case of IEEE), the name should be supplied as a quoted numeric
+string.  A section name may consist of any sequence characters, but
+any name which does not conform to the standard @code{gld} symbol name
+syntax must be quoted. To copy sections 1 through 4 from a Oasys file
+into the @code{.text} section of an @code{a.out} file, and sections 13
+and 14 into the @code{data} section:
+@example
+
+        SECTION @{
+                .text :@{
+                        *(``1'' ``2'' ``3'' ``4'')
+                @}
+
+                .data :@{
+                        *(``13'' ``14'')
+                @}
+        @}
+@end example
+
+@item @var{fill expression}
+If present this
+expression sets the fill value. Any unallocated holes in the current output
+section when written to the output file will 
+be filled with the two least significant bytes of the value, repeated as
+necessary.
+@page
+@item @var{options}
+the @var{options} parameter is a list of optional arguments specifying
+attributes of the output section, they may be taken from the following
+list:
+@table @bullet{}
+@item @var{addr expression} 
+forces the output section to be loaded at a specified address. The
+address is specified as a standard linker expression. The following
+example generates section @var{output} at location
+@code{0x40000000}:
+@example
+         SECTIONS @{
+                 output 0x40000000: @{
+                        ...
+                   @}
+         @}
+@end example
+Since the built in function @code{ALIGN} references the location
+counter implicitly, a section may be located on a certain boundary by
+using the @code{ALIGN} function in the expression. For example, to
+locate the @code{.data} section on the next 8k boundary after the end
+of the @code{.text} section:
+@example        
+        SECTIONS @{
+                .text @{
+                        ...
+                @}
+                .data ALIGN(4K) @{
+                        ...
+                @}
+        @}
+@end example
+@end table
+@item @var{statements}
+is a list of file names, input sections and assignments. These statements control what is placed into the
+output section.
+The syntax of a single @var{statement} is one of:
+@table @bullet 
+
+@item @var{symbol}  [ $= | += | -= | *= | /= ] @var{ expression} @code{;}
+
+Global symbols may be created and have their values (addresses)
+altered using the assignment statement. The linker tries to put off
+the evaluation of an assignment until all the terms in the source
+expression are known; for instance the sizes of sections cannot be
+known until after allocation, so assignments dependent upon these are
+not performed until after allocation. Some expressions, such as those
+depending upon the location counter @code{dot}, @samp{.} must be
+evaluated during allocation. If the result of an expression is
+required, but the value is not available, then an error results: eg
+@example
+        SECTIONS @{
+              text 9+this_isnt_constant: 
+                        @{
+                        @}
+                @}
+        testscript:21: Non constant expression for initial address
+@end example
+
+@item @code{CREATE_OBJECT_SYMBOLS}
+causes the linker to create a symbol for each input file and place it
+into the specified section set with the value of the first byte of
+data written from the input file.  For instance, with @code{a.out}
+files it is conventional to have a symbol for each input file.
+@example
+        SECTIONS @{
+                .text 0x2020 :
+                         @{
+                        CREATE_OBJECT_SYMBOLS
+                        *(.text)
+                        _etext = ALIGN(0x2000);
+                        @}
+                @}
+@end example
+Supplied with four object files, @code{a.o}, @code{b.o}, @code{c.o},
+and @code{d.o} a run of
+@code{gld} could create a map:
+@example
+From functions like :
+a.c:
+        afunction() { }
+        int adata=1;
+        int abss;
+
+00000000 A __DYNAMIC
+00004020 B _abss
+00004000 D _adata
+00002020 T _afunction
+00004024 B _bbss
+00004008 D _bdata
+00002038 T _bfunction
+00004028 B _cbss
+00004010 D _cdata
+00002050 T _cfunction
+0000402c B _dbss
+00004018 D _ddata
+00002068 T _dfunction
+00004020 D _edata
+00004030 B _end
+00004000 T _etext
+00002020 t a.o
+00002038 t b.o
+00002050 t c.o
+00002068 t d.o
+
+@end example
+
+@item @var{filename} @code{(} @var{section name list} @code{)}
+This command allocates all the named sections from the input object
+file supplied into the output section at the current point. Sections
+are written in the order they appear in the list so:
+@example
+        SECTIONS @{
+                .text 0x2020 :                
+                        @{
+                        a.o(.data)
+                        b.o(.data)
+                        *(.text)
+                        @}
+                .data :
+                        @{
+                        *(.data)
+                        @}
+                .bss :
+                        @{
+                        *(.bss)
+                        COMMON
+                        @}
+        @}
+@end example
+will produce a map:
+@example
+
+        insert here 
+@end example
+@item @code{* (} @var{section name list} @code{)}
+This command causes all sections from all input files which have not
+yet been assigned output sections to be assigned the current output
+section.
+
+@item @var{filename} @code{[COMMON]}
+This allocates all the common symbols from the specified file and places
+them into the current output section.
+
+@item @code{* [COMMON]}
+This allocates all the common symbols from the files which have not
+yet had their common symbols allocated and places them into the current
+output section.
+
+@item @var{filename}
+A filename alone within a @code{SECTIONS} statement will cause all the
+input sections from the file to be placed into the current output
+section at the current location. If the file name has been mentioned
+before with a section name list then only those
+sections which have not yet been allocated are noted. 
+
+The following example reads all of the sections from file all.o and
+places them at the start of output section @code{outputa} which starts
+at location @code{0x10000}. All of the data from section @code{.input1} from
+file foo.o is placed next into the same output section.  All of
+section @code{.input2} is read from foo.o and placed into output
+section @code{outputb}.  Next all of section @code{.input1} is read
+from foo1.o. All of the remaining @code{.input1} and @code{.input2}
+sections from any files are written to output section @code{output3}.
+
+@example
+       SECTIONS        
+              @{
+                outputa 0x10000 :
+                        @{
+                        all.o
+                        foo.o (.input1)
+                        @}
+                outputb :
+                        @{
+                        foo.o (.input2)
+                        foo1.o (.input1)
+                        @}
+                outputc :
+                        @{
+                        *(.input1)
+                        *(.input2)
+                        @}
+                @}
+
+@end example        
+@end table
+@end table
+@section Using the Location Counter
+The special linker variable @code{dot}, @samp{.} always contains the
+current output location counter. Since the @code{dot} always refers to
+a location in an output section, it must always appear in an
+expression within a @code{SECTIONS} directive. The @code{dot} symbol
+may appear anywhere that an ordinary symbol may appear in an
+expression, but its assignments have a side effect. Assigning a value
+to the @code{dot} symbol will cause the location counter to be moved.
+This may be used to create holes in the output section.  The location
+counter may never be moved backwards.
+@example
+        SECTIONS
+        @{
+                output :
+                @{
+                file1(.text)
+                . = . + 1000;
+                file2(.text)
+                . += 1000;
+                file3(.text)
+                . -= 32;
+                file4(.text)
+                @} = 0x1234;
+        @}
+@end example
+In the previous example, @code{file1} is located at the beginning of
+the output section, then there is a 1000 byte gap, filled with 0x1234.
+Then @code{file2} appears, also with a 1000 byte gap following before
+@code{file3} is loaded. Then the first 32 bytes of @code{file4} are
+placed over the last 32 bytes of @code{file3}.
+@section Command Language Syntax
+@section The Entry Point
+The linker chooses the first executable instruction in an output file from a list
+of possibilities, in order:
+@itemize @bullet
+@item 
+The value of the symbol provided to the command line with the @code{-e} option, when
+present.
+@item 
+The value of the symbol provided in the @code{ENTRY} directive,
+if present.
+@item 
+The value of the symbol @code{start}, if present.
+@item 
+The value of the symbol @code{_main}, if present.
+@item 
+The address of the first byte of the @code{.text} section, if present.
+@item 
+The value 0.
+@end itemize
+If the symbol @code{start} is not defined within the set of input
+files to a link, it may be generated by a simple assignment
+expression. eg.
+@example
+        start = 0x2020;
+@end example
+@section Section Attributes
+@section Allocation of Sections into Memory
+@section Defining Symbols
+@chapter Examples of operation
+The simplest case is linking standard Unix object files on a standard
+Unix system supported by the linker. To link a file hello.o:
+@example
+$ gld -o output /lib/crt0.o hello.o -lc
+@end example
+This tells gld to produce a file called @code{output} after linking
+the file @code{/lib/crt0.o} with @code{hello.o} and the library
+@code{libc.a} which will come from the standard search directories.
+@chapter Partial Linking
+Specifying the @code{-r} on the command line causes @code{gld} to
+perform a partial link.
+
+
+@chapter BFD
+
+The linker accesses object and archive files using the @code{bfd}
+libraries. These libraries allow the linker to use the same routines
+to operate on object files whatever the object file format.
+
+A different object file format can be supported simply by creating a
+new @code{bfd} back end and adding it to the library.
+
+Formats currently supported:
+@itemize @bullet
+@item 
+Sun3 68k a.out
+@item 
+IEEE-695 68k Object Module Format
+@item 
+Oasys 68k Binary Relocatable Object File Format
+@item 
+Sun4 sparc a.out
+@item 
+88k bcs coff
+@item 
+i960 coff little endian
+@item 
+i960 coff big endian
+@item 
+i960 b.out little endian
+@item 
+i960 b.out big endian
+@end itemize
+
+As with most implementations, @code{bfd} is a compromise between
+several conflicting requirements. The major factor influencing
+@code{bfd} design was efficiency, any time used converting between
+formats is time which would not have been spent had @code{bfd} not
+been involved. This is partly offset by abstraction payback; since
+@code{bfd} simplifies applications and back ends, more time and care
+may be spent optimizing algorithms for a greater speed.
+
+One minor artifact of the @code{bfd} solution which the
+user should be aware of is information lossage.
+There are two places where useful information can be lost using the 
+@code{bfd} mechanism; during conversion and during output. 
+
+@section How it works
+When an object file is opened, @code{bfd}
+tries to automatically determine the format of the input object file, a
+descriptor is built in memory with pointers to routines to access
+elements of the object file's data structures.
+
+As different information from the the object files is required
+@code{bfd} reads from different sections of the file and processes
+them. For example a very common operation for the linker is processing
+symbol tables.  Each @code{bfd} back end provides a routine for
+converting between the object file's representation of symbols and an
+internal canonical format. When the linker asks for the symbol table
+of an object file, it calls through the memory pointer to the relevant
+@code{bfd} back end routine which reads and converts the table into
+the canonical form.  Linker then operates upon the common form. When
+the link is finished and the linker writes the symbol table of the
+output file, another @code{bfd} back end routine is called which takes
+the newly created symbol table and converts it into the output format.
+
+@section Information Leaks
+@table @bullet{}
+@item Information lost during output.
+The output formats supported by @code{bfd} do not provide identical 
+facilities, and information which may be described in one form 
+has no where to go in another format. One example of this would be
+alignment information in @code{b.out}. There is no where in an @code{a.out}
+format file to store alignment information on the contained data, so when
+a file is linked from @code{b.out} and an @code{a.out} image is produced,
+alignment information is lost. (Note that in this case the linker has the
+alignment information internally, so the link is performed correctly). 
+
+Another example is COFF section names. COFF files may contain an
+unlimited number of sections, each one with a textual section name. If
+the target of the link is a format which does not have many sections
+(eg @code{a.out}) or has sections without names (eg the Oasys format)
+the link cannot be done simply. It is possible to circumvent this
+problem by describing the desired input section to output section
+mapping with the command language.
+
+@item Information lost during canonicalization.  
+The @code{bfd}
+internal canonical form of the external formats is not exhaustive,
+there are structures in input formats for which there is no direct
+representation internally.  This means that the @code{bfd} back ends
+cannot maintain all the data richness through the transformation
+between external to internal and back to external formats.
+
+This limitation is only a problem when using the linker to read one
+format and write another. Each @code{bfd} back end is responsible for
+maintaining as much data as possible, and the internal @code{bfd}
+canonical form has structures which are opaque to the @code{bfd} core,
+and exported only to the back ends. When a file is read in one format,
+the canonical form is generated for @code{bfd} and the linker. At the
+same time, the back end saves away any information which may otherwise
+be lost. If the data is then written back to the same back end, the
+back end routine will be able to use the canonical form provided by
+the @code{bfd} core as well as the information it prepared earlier.
+Since there is a great deal of commonality between back ends, this
+mechanism is very useful. There is no information lost when linking
+big endian COFF to little endian COFF, or from a.out to b.out. When a
+mixture of formats are linked, the information is only lost from the
+files with a different format to the destination.  
+@end table 
+@section Mechanism 
+The smallest amount of information is preserved when there
+is a small union between the information provided by the source
+format, that stored by the canonical format and the information needed
+by the destination format. A brief description of the canonical form
+will help the user appreciate what is possible to be maintained
+between conversions.
+
+@table @bullet 
+@item file level Information on target machine
+architecture, particular implementation and format type are stored on
+a per file basis. Other information includes a demand pageable bit and
+a write protected bit.  Note that information like Unix magic numbers
+is not stored here, only the magic numbers meaning, so a ZMAGIC file
+would have both the demand pageable bit and the write protected text
+bit set.
+
+The byte order of the target is stored on a per file basis, so that
+both big and little endian object files may be linked together at the
+same time.
+@item section level
+Each section in the input file contains the name of the section, the
+original address in the object file, various flags, size and alignment
+information and pointers into other @code{bfd} data structures.
+@item symbol level
+Each symbol contains a pointer to the object file which originally
+defined it, its name, value and various flags bits. When a symbol
+table is read in all symbols are relocated to make them relative to
+the base of the section they were defined in, so each symbol points to
+the containing section. Each symbol also has a varying amount of
+hidden data to contain private data for the back end. Since the symbol
+points to the original file, the symbol private data format is
+accessible. Operations may be done to a list of symbols of wildly
+different formats without problems.
+
+Normal global and simple local symbols are maintained on output, so an
+output file, no matter the format will retain symbols pointing to
+functions, globals, statics and commons.  Some symbol information is
+not worth retaining; in @code{a.out} type information is stored in the
+symbol table as long symbol names. This information would be useless
+to most coff debuggers and may be thrown away with appropriate command
+line switches. (Note that gdb does support stabs in coff).
+
+There is one word of type information within the symbol, so if the
+format supports symbol type information within symbols - (eg COFF,
+IEEE, Oasys) and the type is simple enough to fit within one word
+(nearly everything but aggregates) the information will be preserved.
+
+@item relocation level
+Each canonical relocation record contains a pointer to the symbol to
+relocate to, the offset of the data to relocate, the section the data
+is in and a pointer to a relocation type descriptor. Relocation is
+performed effectively by message passing through the relocation type
+descriptor and symbol pointer. It allows relocations to be performed
+on output data using a relocation method only available in one of the
+input formats. For instance, Oasys provides a byte relocation format.
+A relocation record requesting this relocation type would point
+indirectly to a routine to perform this, so the relocation may be
+performed on a byte being written to a COFF file, even though 68k COFF
+has no such relocation type.
+
+@item line numbers
+Line numbers have to be relocated along with the symbol information.
+Each symbol with an associated list of line number records points to
+the first record of the list.  The head of a line number list consists
+of a pointer to the symbol, which allows divination of the address of
+the function who's line number is being described. The rest of the
+list is tuples offsets into the section and line indexes. Any format
+which can simply derive this information can pass it without lossage
+between formats (COFF, IEEE and Oasys).
+@end table
+
+
+@bye
+
+
index f7e132124c88d509e816744f4f7e5b72676cb0a3..8211f44c17b14bac46b9e0f47ecae8b81ba7f55f 100644 (file)
@@ -97,3 +97,31 @@ PROTO(etree_type *,exp_assop,(int, char *, etree_type *));
 PROTO(void, exp_print_tree,(struct _iobuf *, etree_type *));
 PROTO(bfd_vma, exp_get_vma,(etree_type *, bfd_vma, char *, enum boolean));
 PROTO(int, exp_get_value_int,(etree_type *, int, char *, enum boolean));
+#if 0
+#define LONG 1000
+#define SHORT 1001
+#define BYTE 1002
+#define NAME 1003
+#define NEXT 1004
+#define DEFINED 1005
+#define SIZEOF 1006
+#define ADDR 1007
+#define ALIGN_K 1008
+#define BLOCK 1009
+#define SECTIONS 1010
+#define SIZEOF_HEADERS 1011
+#define MEMORY 1012
+#define DSECT 1013
+#define COPY 1014
+#define INFO 1015
+#define OVERLAY 1016
+#define TARGET_K 1017
+#define MAP 1018
+#define ENTRY 1019
+#define ORIGIN 1020
+#define LENGTH 1021
+#define NOLOAD 1022
+#define SEARCH_DIR 1023
+#define ALIGNMENT 1024
+
+#endif
index aa0f325df73fc1e1cba22c68a3300a00cdf8f30a..c42a3e53b592c64f92f04da6b4519248ac4c56d0 100644 (file)
@@ -20,37 +20,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /*
  * $Id$ 
  *
- * $Log$
- * Revision 1.1  1991/03/21 21:28:41  gumby
- * Initial revision
- *
- * Revision 1.2  1991/03/16  22:27:24  rich
- * fish
- *
- * Revision 1.1  1991/03/13  00:48:21  chrisb
- * Initial revision
- *
- * Revision 1.6  1991/03/10  09:31:26  rich
- *  Modified Files:
- *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
- *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
- *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
- *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
- *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
- *
- * As of this round of changes, ld now builds on all hosts of (Intel960)
- * interest and copy passes my copy test on big endian hosts again.
- *
- * Revision 1.5  1991/03/09  03:25:48  sac
- * Can now parse the -Ur flag
- *
- * Revision 1.4  1991/03/06  02:26:01  sac
- * Added support for constructor sections.
- * Remove parsing ambiguity.
- * Lint
- *
- * Revision 1.3  1991/02/22  17:15:13  sac
- * Added RCS keywords and copyrights
  *
 */
 
@@ -113,10 +82,11 @@ char *current_file;
 boolean ldgram_want_filename = true;
 boolean had_script = false;
 boolean force_make_executable = false;
-boolean ldgram_mustbe_filename = false;
-boolean ldgram_mustbe_symbolname = false;
 boolean ldgram_has_inputfile = false;
 
+boolean ldgram_in_expression = false;
+
+boolean ldgram_in_defsym = false;
 /* LOCALS */
 
 
@@ -171,7 +141,9 @@ boolean ldgram_has_inputfile = false;
 %token MEMORY 
 %token DSECT NOLOAD COPY INFO OVERLAY 
 %token NAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY 
-%token OPTION_e OPTION_c OPTION_noinhibit_exec OPTION_s OPTION_S OPTION_format
+%token OPTION_e OPTION_c OPTION_noinhibit_exec OPTION_s OPTION_S
+%token OPTION_format  OPTION_F
+
 %token OPTION_d OPTION_dc OPTION_dp OPTION_x OPTION_X
 %token OPTION_v OPTION_M OPTION_t STARTUP HLL SYSLIB FLOAT NOFLOAT OPTION_defsym
 %token OPTION_n OPTION_r OPTION_o OPTION_b  OPTION_A
@@ -195,14 +167,7 @@ file:      command_line  { lang_final(); };
 
 
 filename:
-       {
-       ldgram_mustbe_filename =true;
-       }
-       NAME
-       {
-       ldgram_mustbe_filename = false;
-       $$ = $2;
-       }
+  NAME;
 
 command_line:
                command_line command_line_option
@@ -271,23 +236,23 @@ command_line_option:
                        {
                        /* Ignored */
                        }
-        |      OPTION_dp
+        |              OPTION_dp
                         {
                          command_line.force_common_definition = true;
                        }
-        | OPTION_format NAME
-           {
-            lang_add_target($2);
-           }
+        |      OPTION_format NAME
+                  {
+                         lang_add_target($2);
+                          }
 
-       | OPTION_Texp { hex_mode  =true; } 
-                 exp_head
+       |       OPTION_Texp { hex_mode  =true; } 
+                 exp
                { lang_section_start($1, $3);
                  hex_mode = false; }
        
-       | OPTION_Aarch 
+       |       OPTION_Aarch 
                { ldfile_add_arch($1); }
-       | OPTION_b NAME
+       |        OPTION_b NAME
                        {
                        lang_add_target($2);
                        }
@@ -295,6 +260,11 @@ command_line_option:
                        {
                        ldfile_add_library_path($1);
                }
+       |       OPTION_F
+               {
+               /* Ignore */
+               }
+
        |       ifile_p1
        |       input_list
        |       OPTION_c filename
@@ -317,7 +287,15 @@ command_line_option:
                                lang_input_file_is_symbols_only_enum,
                                (char *)NULL);
                        }
-       |       OPTION_defsym assignment_with_nospaces
+       |       OPTION_defsym 
+                       {
+                       ldgram_in_defsym = true;
+                       }
+                        assignment
+                       {
+                       ldgram_in_defsym = false;
+                       }       
+
        ;
 
 
@@ -468,11 +446,6 @@ assign_op:
 end:   ';' | ','
        ;
 
-assignment_with_nospaces:
-       { ldgram_want_filename = false; }
-               assignment
-       { ldgram_want_filename = true; }
-       ;
 
 assignment:
        
@@ -663,14 +636,18 @@ opt_things:
        ;
 
 exp_head:
-       { ldgram_mustbe_symbolname = true; }
+               { 
+               ldgram_in_expression = true; 
+               }
        exp
-       { ldgram_mustbe_symbolname = false; 
-       $$ = $2;
-       }
+               {
+               ldgram_in_expression = false; 
+               $$ = $2;
+               }
+       ;
 
 opt_exp:
-               exp
+               exp_head
                        { $$ = $1; }
        |               { $$= (etree_type *)NULL; }
        ;
index 1fccbc29f0e327fa09b29b1f0166d48c42a064df..173d1818bb34d6a259a27886a198ed97e9bfccb8 100644 (file)
@@ -19,8 +19,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* $Id$ 
  *
  * $Log$
- * Revision 1.1  1991/03/21 21:28:45  gumby
- * Initial revision
+ * Revision 1.4  1991/03/27 02:29:22  steve
+ * *** empty log message ***
+ *
+ * Revision 1.3  1991/03/27  00:52:49  steve
+ * *** empty log message ***
+ *
+ * Revision 1.2  1991/03/22  23:02:34  steve
+ * Brought up to sync with Intel again.
  *
  * Revision 1.3  1991/03/16  22:19:21  rich
  * pop
@@ -731,8 +737,13 @@ char *target;
 static void
 lang_reasonable_defaults()
 {
+
+      lang_output_section_statement_lookup(".text");
+      lang_output_section_statement_lookup(".data");
+
   default_common_section = 
     lang_output_section_statement_lookup(".bss");
+
   if (placed_commons == false) {
     lang_wild_statement_type *new =
       new_stat(lang_wild_statement,
@@ -741,6 +752,7 @@ lang_reasonable_defaults()
     new->filename = (char *)NULL;
     lang_list_init(&new->children);
   }
+
 }
 
 static void lang()
@@ -2150,25 +2162,60 @@ char *memspec;
   current_section->region = lang_memory_region_lookup(memspec);
   stat_ptr = &statement_list;
 }
+/*
+ Create an absolute symbol with the given name with the value of the
+ address of first byte of the section named.
 
+ If the symbol already exists, then do nothing.
+*/
 void
-lang_abs_symbol_at_end_of(section, name)
+lang_abs_symbol_at_beginning_of(section, name)
 char *section;
 char *name;
 {
-  extern bfd *output_bfd;
-  extern asymbol *create_symbol();
-  asection *s = bfd_get_section_by_name(output_bfd, section);
-  /* Add a symbol called _end */
-  asymbol *def = create_symbol(name,
-                              BSF_GLOBAL | BSF_EXPORT |
-                              BSF_ABSOLUTE,
-                              (asection *)NULL);
-  if (s != (asection *)NULL) {
-    def->value = s->vma + s->size;
+  if (ldsym_undefined(name)) {
+    extern bfd *output_bfd;
+    extern asymbol *create_symbol();
+    asection *s = bfd_get_section_by_name(output_bfd, section);
+    asymbol *def = create_symbol(name,
+                                BSF_GLOBAL | BSF_EXPORT |
+                                BSF_ABSOLUTE,
+                                (asection *)NULL);
+    if (s != (asection *)NULL) {
+      def->value = s->vma;
+    }
+    else {
+      def->value = 0;
+    }
   }
-  else {
-    def->value = 0;
+}
+
+/*
+ Create an absolute symbol with the given name with the value of the
+ address of the first byte after the end of the section named.
+
+ If the symbol already exists, then do nothing.
+*/
+void
+lang_abs_symbol_at_end_of(section, name)
+char *section;
+char *name;
+{
+  if (ldsym_undefined(name)){
+    extern bfd *output_bfd;
+    extern asymbol *create_symbol();
+    asection *s = bfd_get_section_by_name(output_bfd, section);
+    /* Add a symbol called _end */
+    asymbol *def = create_symbol(name,
+                                BSF_GLOBAL | BSF_EXPORT |
+                                BSF_ABSOLUTE,
+                                (asection *)NULL);
+    if (s != (asection *)NULL) {
+      def->value = s->vma + s->size;
+    }
+    else {
+      def->value = 0;
+    }
   }
 }
 
index 67af46bc6b2ed7cd566c646b4f94b02bbe957d24..4710260bd09a0d76c9238da884e7fd070a109c89 100644 (file)
@@ -19,41 +19,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
  *  $Id$ 
- *
- * $Log$
- * Revision 1.1  1991/03/21 21:28:50  gumby
- * Initial revision
- *
- * Revision 1.3  1991/03/16  22:27:24  rich
- * fish
- *
- * Revision 1.2  1991/03/15  18:45:55  rich
- * foo
- *
- * Revision 1.1  1991/03/13  00:48:27  chrisb
- * Initial revision
- *
- * Revision 1.6  1991/03/10  09:31:32  rich
- *  Modified Files:
- *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
- *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
- *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
- *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
- *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
- *
- * As of this round of changes, ld now builds on all hosts of (Intel960)
- * interest and copy passes my copy test on big endian hosts again.
- *
- * Revision 1.5  1991/03/09  03:25:49  sac
- * Can now parse the -Ur flag
- *
- * Revision 1.4  1991/03/06  02:26:04  sac
- * Added support for constructor sections.
- * Remove parsing ambiguity.
- * Lint
- *
- * Revision 1.3  1991/02/22  17:15:14  sac
- * Added RCS keywords and copyrights
+
  *
 */
 
@@ -79,9 +45,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define input lex_input
 #define unput lex_unput
 int debug;
-extern boolean ldgram_want_filename;
-extern boolean ldgram_mustbe_filename;
-extern boolean ldgram_mustbe_symbolname;
+
+extern boolean ldgram_in_expression;
+extern boolean ldgram_in_defsym;
+
 static char *command_line;
 
 extern int fgetc();
@@ -138,16 +105,7 @@ extern char *ldfile_input_filename;
 int
 lex_input()
 {
-  /*
-     When we know that the next token must be a filename we force the 
-     input routine to return a '#' character, which will cause the special
-     filname regexp to match the following chars even if they don't look
-     much like a filename to any sane person.
-     */
-  if (ldgram_mustbe_filename) {
-    ldgram_mustbe_filename = false;
-    return '#';
-  }
+
 
   if (have_pushback > 0) 
     {
@@ -170,6 +128,7 @@ lex_input()
   }
   else thischar = 0;
   if(thischar == '\t') thischar = ' ';
+  if (thischar == '\n') { thischar = ' '; lineno++; }
   return thischar ;
 }
 
@@ -289,7 +248,6 @@ FILENAME    {FILENAMECHAR}+
 WHITE          [ \t]+
 
 %%
-"\n"           { lineno++; }
 
 
 "\ -defsym" { return OPTION_defsym; }
@@ -343,6 +301,13 @@ WHITE              [ \t]+
                 return OPTION_T;
               }
 
+"\ -F"{FILENAME}  {
+                return OPTION_F;
+              }
+"\ -F"          {
+                return OPTION_F;
+              }
+
 "\ -A"{FILENAME} {
                  yylval.name = buystring(yytext+3);
                 return OPTION_Aarch;
@@ -394,7 +359,6 @@ WHITE               [ \t]+
     int ch;
     ch = input();
     while (ch != '*') {
-      if (ch == '\n') {lineno++; }
       ch = input();
     }
 
@@ -441,34 +405,46 @@ WHITE             [ \t]+
   yylval.name = buystring(p);
   return NAME;
 }
+{FILENAMECHAR} {
 
-
-{FILENAMECHAR}         {
-
-int ch;
+  boolean loop = false;
+  /*
+    Tokenize a name, this is really pain, since a name can be a
+    filename or a symbol name. filenames have slashes and stuff whist
+    in an expression those things are seperate tokens. We hack this by
+    setting lang_in_expression when we are expecting a symbol, so that
+    [/+-] get taken to be seperate tokens. An extra gotcha is
+    expressions after defsyms, we only allow +s and -s in a defsym
+    expression, so -defsym foo=bar+9 /file.o is parsed ok.
+    
+    */
+  int ch;
   keyword_type *k;
-  if (yytext[0] == '/' && ldgram_mustbe_symbolname) 
-    { RTOKEN('/');}
-   ch = input();
-  while (true) {
-    if (isalpha(ch) || isdigit(ch) || ch == '.'  || ch == '_') {
-      yytext[yyleng++] = ch;
-    }
-    else if (ch == '-' && ldgram_want_filename == true) {
-      yytext[yyleng++] = ch;
-    }
-    else if (ch == '+' && ldgram_want_filename == true) {
-      yytext[yyleng++] = ch;
-    }
-
-    else if (ch == '/' && ldgram_want_filename == true) {
-      yytext[yyleng++] = ch;
+  if (ldgram_in_expression) {
+    if (yytext[0] != '/' ||  ldgram_in_defsym == false)  {
+      switch (yytext[0]) {
+      case '/': RTOKEN('/');
+      case '+': RTOKEN('+');
+      case '-': RTOKEN('-');
+      }
     }
-
-    else break;
-    ch = input();
   }
 
+  ch = input();
+  while (true)
+      {
+       if (isalpha(ch) || isdigit(ch) || ch == '.'  || ch == '_') {
+         yytext[yyleng++] = ch;
+       }
+       else if (ch == '+' || ch == '-' || ch == '/') {
+         if (ldgram_in_expression) break;
+         yytext[yyleng++] = ch;
+       }
+       else 
+         break;
+       ch = input();
+      }
+
   yytext[yyleng] = 0;
   unput(ch);
 
index 3f9db087df995ce898659477d7107285f7345b88..545dcf2ecbc1080af349d420ba96e8b6808f9915 100644 (file)
@@ -22,8 +22,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  * $Id$ 
  *
  * $Log$
- * Revision 1.1  1991/03/21 21:28:52  gumby
- * Initial revision
+ * Revision 1.2  1991/03/22 23:02:36  steve
+ * Brought up to sync with Intel again.
  *
  * Revision 1.1  1991/03/13  00:48:27  chrisb
  * Initial revision
@@ -181,7 +181,7 @@ main (argc, argv)
   command_line.force_common_definition = false;
 
   ldfile_add_arch("");
-
+  ldfile_add_library_path("./");
   config.make_executable = true;
   force_make_executable = false;
 
index 2f73066f4ddb2b0392b9d192c12e2fe92869c4f3..d3671c85db9df2635ec485e7caf0b3dee8b9eeae 100644 (file)
@@ -18,40 +18,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
  * $Id$ 
- *
- * $Log$
- * Revision 1.1  1991/03/21 21:28:55  gumby
- * Initial revision
- *
- * Revision 1.2  1991/03/15  18:45:55  rich
- * foo
- *
- * Revision 1.1  1991/03/13  00:48:30  chrisb
- * Initial revision
- *
- * Revision 1.7  1991/03/10  09:31:34  rich
- *  Modified Files:
- *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
- *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
- *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
- *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
- *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
- *
- * As of this round of changes, ld now builds on all hosts of (Intel960)
- * interest and copy passes my copy test on big endian hosts again.
- *
- * Revision 1.6  1991/03/09  03:31:01  sac
- * After a fatal info message, the output file is deleted.
- *
- * Revision 1.5  1991/03/06  21:59:54  sac
- * Made %C print function name if available
- *
- * Revision 1.4  1991/03/06  02:27:45  sac
- * Added support for linenumber printing via %C
- *
- * Revision 1.3  1991/02/22  17:15:03  sac
- * Added RCS keywords and copyrights
- *
  */
 
 /*
@@ -184,11 +150,21 @@ va_dcl
            fprintf(stderr,"command line");
          }
          else {
-           fprintf(stderr,"%s:%u", ldfile_input_filename, lineno + 1);
+           fprintf(stderr,"%s:%u", ldfile_input_filename, lineno );
          }
        }
        else {
-         fprintf(stderr,"command line ");
+         int ch;
+         int n = 0;
+         fprintf(stderr,"command (before <");
+         ch = lex_input();
+         while (ch != 0 && n < 10) {
+           fprintf(stderr, "%c", ch);
+           ch = lex_input();
+           n++;
+         }
+         fprintf(stderr,")");
+           
        }
        break;
       case 'C':
diff --git a/ld/ldsym.c b/ld/ldsym.c
new file mode 100644 (file)
index 0000000..986259f
--- /dev/null
@@ -0,0 +1,470 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ *  $Id$ 
+ *
+ *  $Log$
+ *  Revision 1.3  1991/03/27 02:29:21  steve
+ *  *** empty log message ***
+ *
+ * Revision 1.2  1991/03/22  23:02:38  steve
+ * Brought up to sync with Intel again.
+ *
+ * Revision 1.1  1991/03/13  00:48:32  chrisb
+ * Initial revision
+ *
+ * Revision 1.4  1991/03/10  09:31:36  rich
+ *  Modified Files:
+ *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
+ *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
+ *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
+ *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
+ *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
+ *
+ * As of this round of changes, ld now builds on all hosts of (Intel960)
+ * interest and copy passes my copy test on big endian hosts again.
+ *
+ * Revision 1.3  1991/03/06  02:28:56  sac
+ * Cleaned up
+ *
+ * Revision 1.2  1991/02/22  17:15:06  sac
+ * Added RCS keywords and copyrights
+ *
+*/
+
+/* 
+   Written by Steve Chamberlain steve@cygnus.com
+   All symbol handling for the linker
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "ld.h"
+#include "ldsym.h"
+#include "ldmisc.h"
+#include "ldlang.h"
+/* IMPORT */
+
+extern bfd *output_bfd;
+/* Head and tail of global symbol table chronological list */
+
+ldsym_type *symbol_head = (ldsym_type *)NULL;
+ldsym_type **symbol_tail_ptr = &symbol_head;
+
+/*
+  incremented for each symbol in the ldsym_type table
+  no matter what flavour it is 
+*/
+unsigned int global_symbol_count;
+
+/* IMPORTS */
+
+extern boolean option_longmap ;
+
+/* LOCALS */
+#define        TABSIZE 1009
+static ldsym_type *global_symbol_hash_table[TABSIZE];
+
+/* Compute the hash code for symbol name KEY.  */
+
+int
+hash_string (key)
+     char *key;
+{
+  register char *cp;
+  register int k;
+
+  cp = key;
+  k = 0;
+  while (*cp)
+    k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
+
+  return k;
+}
+
+/* Get the symbol table entry for the global symbol named KEY.
+   Create one if there is none.  */
+ldsym_type *
+ldsym_get (key)
+     char *key;
+{
+  register int hashval;
+  register ldsym_type *bp;
+
+  /* Determine the proper bucket.  */
+
+  hashval = hash_string (key) % TABSIZE;
+
+  /* Search the bucket.  */
+
+  for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
+    if (! strcmp (key, bp->name))
+      return bp;
+
+  /* Nothing was found; create a new symbol table entry.  */
+
+  bp = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
+  bp->srefs_chain = (asymbol **)NULL;
+  bp->sdefs_chain = (asymbol **)NULL;
+  bp->scoms_chain = (asymbol **)NULL;
+  bp->name = (char *) ldmalloc (strlen (key) + 1);
+  strcpy (bp->name, key);
+
+
+
+
+  /* Add the entry to the bucket.  */
+
+  bp->link = global_symbol_hash_table[hashval];
+  global_symbol_hash_table[hashval] = bp;
+
+  /* Keep the chronological list up to date too */
+  *symbol_tail_ptr = bp;
+  symbol_tail_ptr = &bp->next;
+  bp->next = 0;
+  global_symbol_count++;
+
+  return bp;
+}
+
+/* Like `ldsym_get' but return 0 if the symbol is not already known.  */
+
+ldsym_type *
+ldsym_get_soft (key)
+     char *key;
+{
+  register int hashval;
+  register ldsym_type *bp;
+
+  /* Determine which bucket.  */
+
+  hashval = hash_string (key) % TABSIZE;
+
+  /* Search the bucket.  */
+
+  for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
+    if (! strcmp (key, bp->name))
+      return bp;
+
+  return 0;
+}
+
+
+
+
+
+static void
+list_file_locals (entry)
+lang_input_statement_type *entry;
+{
+  asymbol **q;
+  fprintf (stderr, "\nLocal symbols of ");
+  info("%I", entry);
+  fprintf (stderr, ":\n\n");
+  if (entry->asymbols) {
+    for (q = entry->asymbols; *q; q++) 
+      {
+       asymbol *p = *q;
+       /* If this is a definition,
+          update it if necessary by this file's start address.  */
+       if (p->flags & BSF_LOCAL)
+        info("  %V %s\n",p->value, p->name);
+      }
+  }
+}
+
+
+static void
+print_file_stuff(f)
+lang_input_statement_type *f;
+{
+  fprintf (stderr, "  %s", f->filename);
+  fprintf (stderr, " ");
+  if (f->just_syms_flag) 
+    {
+      fprintf (stderr, " symbols only\n");
+    }
+  else 
+    {
+      asection *s;
+      if (option_longmap) {
+       for (s = f->the_bfd->sections;
+            s != (asection *)NULL;
+            s = s->next) {
+         fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
+                  s->output_offset,
+                  (unsigned)s->size, s->alignment_power, s->name);
+       }
+      }
+      else {         
+       for (s = f->the_bfd->sections;
+            s != (asection *)NULL;
+            s = s->next) {
+         fprintf (stderr, "%s %lx(%x) ",
+                  s->name,
+                  s->output_offset,
+                  (unsigned)   s->size);
+       }
+       fprintf (stderr, "hex \n");
+      }
+    }
+}
+
+void
+ldsym_print_symbol_table ()
+{
+  fprintf (stderr, "\nFiles:\n\n");
+
+  lang_for_each_file(print_file_stuff);
+
+  fprintf (stderr, "\nGlobal symbols:\n\n");
+  {
+    register ldsym_type *sp;
+
+    for (sp = symbol_head; sp; sp = sp->next)
+      {
+       if (sp->sdefs_chain) 
+         {
+           asymbol *defsym = *(sp->sdefs_chain);
+           asection *defsec = bfd_get_section(defsym);
+           fprintf(stderr,"%08lx ",defsym->value);
+           if (defsec)
+             {
+               fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
+               fprintf(stderr,
+                       "%7s",
+                       bfd_section_name(output_bfd,
+                                        defsec));
+
+             }
+           else 
+             {
+               fprintf(stderr,"         .......");
+             }
+
+         }     
+       else {
+         fprintf(stderr,"undefined");
+       }
+
+
+       if (sp->scoms_chain) {
+         fprintf(stderr, " common size %5lu    %s",
+                 (*(sp->scoms_chain))->value, sp->name);
+       }
+       if (sp->sdefs_chain) {
+         fprintf(stderr, " symbol def %08lx    %s",
+                 (*(sp->sdefs_chain))->value,
+                 sp->name);
+       }
+       else {
+         fprintf(stderr, " undefined    %s",
+                 sp->name);
+       }
+       fprintf(stderr, "\n");
+
+      }
+  }
+  lang_for_each_file(list_file_locals);
+}
+
+extern lang_output_section_statement_type *create_object_symbols;
+extern char lprefix;
+static asymbol **
+write_file_locals(output_buffer)
+asymbol **output_buffer;
+{
+LANG_FOR_EACH_INPUT_STATEMENT(entry)
+    {
+      /* Run trough the symbols and work out what to do with them */
+      unsigned int i;
+
+      /* Add one for the filename symbol if needed */
+      if (create_object_symbols 
+         != (lang_output_section_statement_type *)NULL) {
+       asection *s;
+       for (s = entry->the_bfd->sections;
+            s != (asection *)NULL;
+            s = s->next) {
+         if (s->output_section == create_object_symbols->bfd_section) {
+           /* Add symbol to this section */
+           asymbol * newsym  =
+             (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
+           newsym->name = entry->local_sym_name;
+           /* The symbol belongs to the output file's text section */
+
+           /* The value is the start of this section in the output file*/
+           newsym->value  = 0;
+           newsym->flags = BSF_LOCAL;
+           newsym->section = s;
+           *output_buffer++ = newsym;
+           break;
+         }
+       }
+      }
+      for (i = 0; i < entry->symbol_count; i++) 
+       {
+         asymbol *p = entry->asymbols[i];
+
+         if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
+           {
+             /* We are only interested in outputting 
+                globals at this stage in special circumstances */
+             if (p->the_bfd == entry->the_bfd 
+                 && flag_is_not_at_end(p->flags)) {
+               /* And this is one of them */
+               *(output_buffer++) = p;
+               p->flags |= BSF_KEEP;
+             }
+           }
+         else {
+           if (flag_is_ordinary_local(p->flags)) 
+             {
+               if (discard_locals == DISCARD_ALL)
+                 {  }
+               else if (discard_locals == DISCARD_L &&
+                        (p->name[0] == lprefix)) 
+                 {  }
+               else if (p->flags ==  BSF_WARNING) 
+                 {  }
+               else 
+                 { *output_buffer++ = p; }
+             }
+           else if (flag_is_debugger(p->flags)) 
+             {
+               /* Only keep the debugger symbols if no stripping required */
+               if (strip_symbols == STRIP_NONE) {
+                 *output_buffer++ = p;
+               }
+             }
+           else if (flag_is_undefined(p->flags)) 
+             { /* This must be global */
+             }
+           else if (flag_is_common(p->flags)) {
+          /* And so must this */
+           } 
+           else if (p->flags & BSF_CTOR) {
+             /* Throw it away */
+           }
+else
+             {
+               FAIL();
+             }
+         }
+       }
+
+
+    }
+  return output_buffer;
+}
+
+
+static asymbol **
+write_file_globals(symbol_table)
+asymbol **symbol_table;
+{
+  FOR_EACH_LDSYM(sp)
+    {
+      if (sp->sdefs_chain != (asymbol **)NULL) {
+       asymbol *bufp = (*(sp->sdefs_chain));
+
+       if ((bufp->flags & BSF_KEEP) ==0) {
+         ASSERT(bufp != (asymbol *)NULL);
+
+         bufp->name = sp->name;
+
+         if (sp->scoms_chain != (asymbol **)NULL)      
+
+           {
+             /* 
+                defined as common but not allocated, this happens
+                only with -r and not -d, write out a common
+                definition
+                */
+             bufp = *(sp->scoms_chain);
+           }
+         *symbol_table++ = bufp;
+       }
+      }
+      else if (sp->scoms_chain != (asymbol **)NULL) {
+       /* This symbol is a common - just output */
+       asymbol *bufp = (*(sp->scoms_chain));
+       *symbol_table++ = bufp;
+      }
+      else if (sp->srefs_chain != (asymbol **)NULL) {
+       /* This symbol is undefined but has a reference */
+       asymbol *bufp = (*(sp->srefs_chain));
+       *symbol_table++ = bufp;
+      }
+      else {
+       /*
+          This symbol has neither defs nor refs, it must have come
+          from the command line, since noone has used it it has no
+          data attatched, so we'll ignore it 
+          */
+      }
+    }
+  return symbol_table;
+}
+
+
+
+void
+ldsym_write()
+{
+  if (strip_symbols != STRIP_ALL) {
+    /* We know the maximum size of the symbol table -
+       it's the size of all the global symbols ever seen +
+       the size of all the symbols from all the files +
+       the number of files (for the per file symbols)
+       +1 (for the null at the end)
+       */
+    extern unsigned int total_files_seen;
+    extern unsigned int total_symbols_seen;
+
+    asymbol **  symbol_table =  (asymbol **) 
+      ldmalloc ((size_t)(global_symbol_count +
+                        total_files_seen +
+                        total_symbols_seen + 1) *     sizeof (asymbol *));
+    asymbol ** tablep = write_file_locals(symbol_table);
+
+    tablep = write_file_globals(tablep);
+
+    *tablep =  (asymbol *)NULL;
+    bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
+  }
+}
+
+/*
+return true if the supplied symbol name is not in the 
+linker symbol table
+*/
+boolean 
+ldsym_undefined(sym)
+char *sym;
+{
+  ldsym_type *from_table = ldsym_get_soft(sym);
+  if (from_table != (ldsym_type *)NULL) {
+    if (from_table->sdefs_chain != (asymbol **)NULL) return false;
+  }
+  return true;
+}
diff --git a/ld/ldsym.h b/ld/ldsym.h
new file mode 100644 (file)
index 0000000..67daed7
--- /dev/null
@@ -0,0 +1,60 @@
+/* ldsym.h -
+
+   Copyright (C) 1991 Free Software Foundation, Inc.
+
+   This file is part of GLD, the Gnu Linker.
+
+   GLD 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 1, or (at your option)
+   any later version.
+
+   GLD 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 GLD; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+typedef struct user_symbol_struct
+{
+  /* Point to next symbol in this hash chain */
+  struct user_symbol_struct *link;
+
+  /* Name of this symbol.  */
+  char *name;                  
+
+  /* Pointer to next symbol in order of symbol creation */
+  struct user_symbol_struct *next; 
+
+  /* Chain of asymbols we see from input files 
+     note that we point to the entry in the canonical table of 
+     the pointer to the asymbol, *not* the asymbol. This means
+     that we can run back and fix all refs to point to the
+     defs nearly for free.
+     */
+  asymbol **srefs_chain;
+  asymbol **sdefs_chain;
+
+  /* only ever point to the largest ever common definition -
+   * all the rest are turned into refs 
+   * scoms and sdefs are never != NULL at same time
+   */
+  asymbol **scoms_chain;
+
+} ldsym_type;
+
+
+PROTO(ldsym_type *, ldsym_get, (char *));
+PROTO(ldsym_type *, ldsym_get_soft, (char *));
+PROTO(void, ldsym_print_symbol_table,(void));
+PROTO(void, ldsym_write, (void));
+PROTO(boolean, ldsym_undefined, (char *));
+#define FOR_EACH_LDSYM(x)                                              \
+       extern ldsym_type *symbol_head;                                 \
+       ldsym_type *x;                                                  \
+       for (x = symbol_head; x != (ldsym_type *)NULL; x = x->next)     
+
+
diff --git a/ld/ldwarn.h b/ld/ldwarn.h
new file mode 100644 (file)
index 0000000..be0d107
--- /dev/null
@@ -0,0 +1,22 @@
+/* ldwarn.h -
+
+   Copyright (C) 1991 Free Software Foundation, Inc.
+
+   This file is part of GLD, the Gnu Linker.
+
+   GLD 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 1, or (at your option)
+   any later version.
+
+   GLD 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 GLD; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+PROTOX(void, ldwarn,(void));
index a4282b31b5b463dcddf51ead01a722e9e6bbc4a8..93af48c26b678ac0b125e24e448a87eb7b3b1a2f 100644 (file)
@@ -20,8 +20,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  * $Id$ 
  *
  *  $Log$
- *  Revision 1.1  1991/03/21 21:29:04  gumby
- *  Initial revision
+ *  Revision 1.3  1991/03/22 22:32:22  steve
+ *  *** empty log message ***
+ *
+ * Revision 1.2  1991/03/22  22:31:37  steve
+ * *** empty log message ***
+ *
+ * Revision 1.1.1.1  1991/03/21  21:29:05  gumby
+ * Back from Intel with Steve
+ *
+ * Revision 1.1  1991/03/21  21:29:04  gumby
+ * Initial revision
  *
  * Revision 1.2  1991/03/15  18:45:55  rich
  * foo
diff --git a/readline/COPYING b/readline/COPYING
new file mode 100644 (file)
index 0000000..9a17037
--- /dev/null
@@ -0,0 +1,249 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/readline/ChangeLog b/readline/ChangeLog
new file mode 100644 (file)
index 0000000..5136177
--- /dev/null
@@ -0,0 +1,82 @@
+Sun Mar 11 04:32:03 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * Signals are now supposedly handled inside of SYSV compilation.
+
+Wed Jan 17 19:24:09 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+       * history.c: history_expand (); fixed overwriting memory error,
+       added needed argument to call to get_history_event ().
+
+Thu Jan 11 10:54:04 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+       * readline.c, readline.h: added rl_show_star to control the
+       display of an asterisk on modified history lines.
+
+Thu Jan  4 10:38:05 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+       * readline.c: start_insert ().  Only use IC if we don't have an im
+       capability.
+
+Fri Sep  8 09:00:45 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: rl_prep_terminal ().  Only turn on 8th bit
+         as meta-bit iff the terminal is not using parity.
+
+Sun Sep  3 08:57:40 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: start_insert ().  Uses multiple
+         insertion call in cases where that makes sense.
+
+         rl_insert ().  Read type-ahead buffer for additional
+         keys that are bound to rl_insert, and insert them
+         all at once.  Make insertion of single keys given
+         with an argument much more efficient.
+
+Tue Aug  8 18:13:57 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: Changed handling of EOF.  readline () returns
+        (char *)EOF or consed string.  The EOF character is read from the
+        tty, or if the tty doesn't have one, defaults to C-d.
+
+       * readline.c: Added support for event driven programs.
+         rl_event_hook is the address of a function you want called
+         while Readline is waiting for input.
+
+       * readline.c: Cleanup time.  Functions without type declarations
+         do not use return with a value.
+
+       * history.c: history_expand () has new variable which is the
+         characters to ignore immediately following history_expansion_char.
+
+Sun Jul 16 08:14:00 1989  Brian Fox  (bfox at aurel)
+
+       * rl_prep_terminal ()
+         BSD version turns off C-s, C-q, C-y, C-v.
+
+       * readline.c -- rl_prep_terminal ()
+         SYSV version hacks readline_echoing_p.
+         BSD version turns on passing of the 8th bit for the duration
+         of reading the line.
+
+Tue Jul 11 06:25:01 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: new variable rl_tilde_expander.
+         If non-null, this contains the address of a function to call if
+         the standard meaning for expanding a tilde fails.  The function is
+         called with the text sans tilde (as in "foo"), and returns a
+         malloc()'ed string which is the expansion, or a NULL pointer if
+         there is no expansion. 
+
+       * readline.h - new file chardefs.h
+         Separates things that only readline.c needs from the standard
+         header file publishing interesting things about readline.
+
+       * readline.c:
+         readline_default_bindings () now looks at terminal chararacters
+         and binds those as well.
+
+Wed Jun 28 20:20:51 1989  Brian Fox  (bfox at aurel)
+
+       * Made readline and history into independent libraries.
+
+
diff --git a/readline/Makefile.in b/readline/Makefile.in
new file mode 100644 (file)
index 0000000..4fb6ceb
--- /dev/null
@@ -0,0 +1,103 @@
+## -*- text -*- ####################################################
+#                                                                 #
+# Makefile for readline and history libraries.                    #
+#                                                                 #
+####################################################################
+
+# Here is a rule for making .o files from .c files that doesn't force
+# the type of the machine (like -sun3) into the flags.
+.c.o:
+       $(CC) -c $(CFLAGS) $(LOCAL_INCLUDES) $(CPPFLAGS) $(READLINE_DEFINES) $<
+
+# Destination installation directory.  The libraries are copied to DESTDIR
+# when you do a `make install', and the header files to INCDIR/readline/*.h.
+DESTDIR = /usr/local/lib
+INCDIR = /usr/local/include
+
+# Define TYPES as -DVOID_SIGHANDLER if your operating system uses
+# a return type of "void" for signal handlers.
+TYPES = -DVOID_SIGHANDLER
+
+# Define SYSV as -DSYSV if you are using a System V operating system.
+#SYSV = -DSYSV
+
+# HP-UX compilation requires the BSD library.
+#LOCAL_LIBS = -lBSD
+
+# Xenix compilation requires -ldir -lx
+#LOCAL_LIBS = -ldir -lx
+
+# Comment out "-DVI_MODE" if you don't think that anyone will ever desire
+# the vi line editing mode and features.
+READLINE_DEFINES = $(TYPES) -DVI_MODE
+
+DEBUG_FLAGS = -g
+LDFLAGS = $(DEBUG_FLAGS) 
+CFLAGS = $(DEBUG_FLAGS) $(SYSV) -I.
+
+# A good alternative is gcc -traditional.
+#CC = gcc -traditional
+CC = cc
+RANLIB = /usr/bin/ranlib
+AR = ar
+RM = rm
+CP = cp
+
+LOCAL_INCLUDES = -I../
+
+CSOURCES = readline.c history.c funmap.c keymaps.c vi_mode.c \
+          emacs_keymap.c vi_keymap.c
+
+HSOURCES = readline.h chardefs.h history.h keymaps.h
+SOURCES  = $(CSOURCES) $(HSOURCES)
+
+DOCUMENTATION = readline.texinfo inc-readline.texinfo \
+               history.texinfo inc-history.texinfo
+
+SUPPORT = COPYING Makefile $(DOCUMENTATION) ChangeLog
+
+THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
+
+##########################################################################
+
+all: libreadline.a
+
+libreadline.a: readline.o history.o funmap.o keymaps.o
+               $(RM) -f libreadline.a
+               $(AR) clq libreadline.a readline.o history.o funmap.o keymaps.o
+               -if [ -f $(RANLIB) ]; then $(RANLIB) libreadline.a; fi
+
+readline.o:    readline.h chardefs.h  keymaps.h history.h readline.c vi_mode.c
+history.o:     history.c history.h
+funmap.o:      readline.h
+keymaps.o:     emacs_keymap.c vi_keymap.c keymaps.h chardefs.h keymaps.c
+
+libtest:       libreadline.a libtest.c
+               $(CC) -o libtest $(CFLAGS) $(CPPFLAGS) -L. libtest.c -lreadline -ltermcap
+
+readline: readline.c history.o keymaps.o funmap.o readline.h chardefs.h
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
+               $(LOCAL_INCLUDES) -DTEST -o readline readline.c funmap.o \
+                keymaps.o history.o -L. -ltermcap
+
+readline.tar:  $(THINGS_TO_TAR)
+               tar -cf readline.tar $(THINGS_TO_TAR)
+
+readline.tar.Z:        readline.tar
+               compress -f readline.tar
+
+install:       $(DESTDIR)/libreadline.a includes
+
+includes:
+               if [ ! -r $(INCDIR)/readline ]; then\
+                mkdir $(INCDIR)/readline;\
+                chmod a+r $(INCDIR)/readline;\
+               fi
+               $(CP) readline.h keymaps.h chardefs.h $(INCDIR)/readline/
+clean:
+               rm -f *.o *.a *.log *.cp *.tp *.vr *.fn *.aux *.pg *.toc
+
+$(DESTDIR)/libreadline.a: libreadline.a
+               -mv $(DESTDIR)/libreadline.a $(DESTDIR)/libreadline.old
+               cp libreadline.a $(DESTDIR)/libreadline.a
+               $(RANLIB) -t $(DESTDIR)/libreadline.a
diff --git a/readline/chardefs.h b/readline/chardefs.h
new file mode 100644 (file)
index 0000000..9749ae4
--- /dev/null
@@ -0,0 +1,50 @@
+/* chardefs.h -- Character definitions for readline. */
+#ifndef _CHARDEFS_
+
+#ifndef savestring
+#define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifdef CTRL
+#undef CTRL
+#endif
+
+/* Some character stuff. */
+#define control_character_threshold 0x020   /* smaller than this is control */
+#define meta_character_threshold 0x07f     /* larger than this is Meta. */
+#define control_character_bit 0x40         /* 0x000000, must be off. */
+#define meta_character_bit 0x080           /* x0000000, must be on. */
+
+#define CTRL(c) ((c) & (~control_character_bit))
+#define META(c) ((c) | meta_character_bit)
+
+#define UNMETA(c) ((c) & (~meta_character_bit))
+#define UNCTRL(c) to_upper(((c)|control_character_bit))
+
+#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
+#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
+
+#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
+
+#ifndef to_upper
+#define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
+#define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
+#endif
+
+#define CTRL_P(c) ((c) < control_character_threshold)
+#define META_P(c) ((c) > meta_character_threshold)
+
+#define NEWLINE '\n'
+#define RETURN CTRL('M')
+#define RUBOUT 0x07f
+#define TAB '\t'
+#define ABORT_CHAR CTRL('G')
+#define PAGE CTRL('L')
+#define SPACE 0x020
+#define ESC CTRL('[')
+
+#endif  /* _CHARDEFS_ */
diff --git a/readline/emacs_keymap.c b/readline/emacs_keymap.c
new file mode 100644 (file)
index 0000000..24961de
--- /dev/null
@@ -0,0 +1,472 @@
+/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline 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 1, or (at your option) any
+   later version.
+
+   Readline 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 Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef BUFSIZ
+#include <stdio.h>
+#endif /* BUFSIZ */
+
+#include "readline.h"
+
+/* An array of function pointers, one for each possible key.
+   If the type byte is ISKMAP, then the pointer is the address of
+   a keymap. */
+
+KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
+
+  /* Control keys. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, rl_beg_of_line },          /* Control-a */
+  { ISFUNC, rl_backward },             /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, rl_delete },               /* Control-d */
+  { ISFUNC, rl_end_of_line },          /* Control-e */
+  { ISFUNC, rl_forward },              /* Control-f */
+  { ISFUNC, rl_abort },                        /* Control-g */
+  { ISFUNC, rl_backward },             /* Control-h */
+  { ISFUNC, rl_complete },             /* Control-i */
+  { ISFUNC, rl_newline },              /* Control-j */
+  { ISFUNC, rl_kill_line },            /* Control-k */
+  { ISFUNC, rl_clear_screen },         /* Control-l */
+  { ISFUNC, rl_newline },              /* Control-m */
+  { ISFUNC, rl_get_next_history },     /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, rl_get_previous_history }, /* Control-p */
+  { ISFUNC, rl_quoted_insert },                /* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },      /* Control-t */
+  { ISFUNC, rl_unix_line_discard },    /* Control-u */
+  { ISFUNC, rl_quoted_insert },                /* Control-v */
+  { ISFUNC, rl_unix_word_rubout },     /* Control-w */
+  { ISKMAP, (Function *)emacs_ctlx_keymap },   /* Control-x */
+  { ISFUNC, rl_yank },                 /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+  { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_insert },       /* SPACE */
+  { ISFUNC, rl_insert },       /* ! */
+  { ISFUNC, rl_insert },       /* " */
+  { ISFUNC, rl_insert },       /* # */
+  { ISFUNC, rl_insert },       /* $ */
+  { ISFUNC, rl_insert },       /* % */
+  { ISFUNC, rl_insert },       /* & */
+  { ISFUNC, rl_insert },       /* ' */
+  { ISFUNC, rl_insert },       /* ( */
+  { ISFUNC, rl_insert },       /* ) */
+  { ISFUNC, rl_insert },       /* * */
+  { ISFUNC, rl_insert },       /* + */
+  { ISFUNC, rl_insert },       /* , */
+  { ISFUNC, rl_insert },       /* - */
+  { ISFUNC, rl_insert },       /* . */
+  { ISFUNC, rl_insert },       /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_insert },       /* 0 */
+  { ISFUNC, rl_insert },       /* 1 */
+  { ISFUNC, rl_insert },       /* 2 */
+  { ISFUNC, rl_insert },       /* 3 */
+  { ISFUNC, rl_insert },       /* 4 */
+  { ISFUNC, rl_insert },       /* 5 */
+  { ISFUNC, rl_insert },       /* 6 */
+  { ISFUNC, rl_insert },       /* 7 */
+  { ISFUNC, rl_insert },       /* 8 */
+  { ISFUNC, rl_insert },       /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, rl_insert },       /* : */
+  { ISFUNC, rl_insert },       /* ; */
+  { ISFUNC, rl_insert },       /* < */
+  { ISFUNC, rl_insert },       /* = */
+  { ISFUNC, rl_insert },       /* > */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_insert },       /* A */
+  { ISFUNC, rl_insert },       /* B */
+  { ISFUNC, rl_insert },       /* C */
+  { ISFUNC, rl_insert },       /* D */
+  { ISFUNC, rl_insert },       /* E */
+  { ISFUNC, rl_insert },       /* F */
+  { ISFUNC, rl_insert },       /* G */
+  { ISFUNC, rl_insert },       /* H */
+  { ISFUNC, rl_insert },       /* I */
+  { ISFUNC, rl_insert },       /* J */
+  { ISFUNC, rl_insert },       /* K */
+  { ISFUNC, rl_insert },       /* L */
+  { ISFUNC, rl_insert },       /* M */
+  { ISFUNC, rl_insert },       /* N */
+  { ISFUNC, rl_insert },       /* O */
+  { ISFUNC, rl_insert },       /* P */
+  { ISFUNC, rl_insert },       /* Q */
+  { ISFUNC, rl_insert },       /* R */
+  { ISFUNC, rl_insert },       /* S */
+  { ISFUNC, rl_insert },       /* T */
+  { ISFUNC, rl_insert },       /* U */
+  { ISFUNC, rl_insert },       /* V */
+  { ISFUNC, rl_insert },       /* W */
+  { ISFUNC, rl_insert },       /* X */
+  { ISFUNC, rl_insert },       /* Y */
+  { ISFUNC, rl_insert },       /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_insert },       /* [ */
+  { ISFUNC, rl_insert },       /* \ */
+  { ISFUNC, rl_insert },       /* ] */
+  { ISFUNC, rl_insert },       /* ^ */
+  { ISFUNC, rl_insert },       /* _ */
+  { ISFUNC, rl_insert },       /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_insert },       /* a */
+  { ISFUNC, rl_insert },       /* b */
+  { ISFUNC, rl_insert },       /* c */
+  { ISFUNC, rl_insert },       /* d */
+  { ISFUNC, rl_insert },       /* e */
+  { ISFUNC, rl_insert },       /* f */
+  { ISFUNC, rl_insert },       /* g */
+  { ISFUNC, rl_insert },       /* h */
+  { ISFUNC, rl_insert },       /* i */
+  { ISFUNC, rl_insert },       /* j */
+  { ISFUNC, rl_insert },       /* k */
+  { ISFUNC, rl_insert },       /* l */
+  { ISFUNC, rl_insert },       /* m */
+  { ISFUNC, rl_insert },       /* n */
+  { ISFUNC, rl_insert },       /* o */
+  { ISFUNC, rl_insert },       /* p */
+  { ISFUNC, rl_insert },       /* q */
+  { ISFUNC, rl_insert },       /* r */
+  { ISFUNC, rl_insert },       /* s */
+  { ISFUNC, rl_insert },       /* t */
+  { ISFUNC, rl_insert },       /* u */
+  { ISFUNC, rl_insert },       /* v */
+  { ISFUNC, rl_insert },       /* w */
+  { ISFUNC, rl_insert },       /* x */
+  { ISFUNC, rl_insert },       /* y */
+  { ISFUNC, rl_insert },       /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, rl_insert },       /* { */
+  { ISFUNC, rl_insert },       /* | */
+  { ISFUNC, rl_insert },       /* } */
+  { ISFUNC, rl_insert },       /* ~ */
+  { ISFUNC, rl_rubout }                /* RUBOUT */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
+
+  /* Meta keys.  Just like above, but the high bit is set. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-@ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-a */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-b */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-c */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-d */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-e */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-f */
+  { ISFUNC, rl_abort },                /* Meta-Control-g */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-h */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-i */
+  { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-k */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-l */
+  { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-n */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-o */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-p */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-q */
+  { ISFUNC, rl_revert_line },  /* Meta-Control-r */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-s */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-t */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-u */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-v */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-w */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-x */
+  { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-z */
+
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-[ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-\ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-] */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-^ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-SPACE */
+  { ISFUNC, (Function *)0x0 }, /* Meta-! */
+  { ISFUNC, (Function *)0x0 }, /* Meta-" */
+  { ISFUNC, (Function *)0x0 }, /* Meta-# */
+  { ISFUNC, (Function *)0x0 }, /* Meta-$ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-% */
+  { ISFUNC, (Function *)0x0 }, /* Meta-& */
+  { ISFUNC, (Function *)0x0 }, /* Meta-' */
+  { ISFUNC, (Function *)0x0 }, /* Meta-( */
+  { ISFUNC, (Function *)0x0 }, /* Meta-) */
+  { ISFUNC, (Function *)0x0 }, /* Meta-* */
+  { ISFUNC, (Function *)0x0 }, /* Meta-+ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-, */
+  { ISFUNC, rl_digit_argument }, /* Meta-- */
+  { ISFUNC, (Function *)0x0 }, /* Meta-. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-/ */
+
+  /* Regular digits. */
+  { ISFUNC, rl_digit_argument }, /* Meta-0 */
+  { ISFUNC, rl_digit_argument }, /* Meta-1 */
+  { ISFUNC, rl_digit_argument }, /* Meta-2 */
+  { ISFUNC, rl_digit_argument }, /* Meta-3 */
+  { ISFUNC, rl_digit_argument }, /* Meta-4 */
+  { ISFUNC, rl_digit_argument }, /* Meta-5 */
+  { ISFUNC, rl_digit_argument }, /* Meta-6 */
+  { ISFUNC, rl_digit_argument }, /* Meta-7 */
+  { ISFUNC, rl_digit_argument }, /* Meta-8 */
+  { ISFUNC, rl_digit_argument }, /* Meta-9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* Meta-: */
+  { ISFUNC, (Function *)0x0 },         /* Meta-; */
+  { ISFUNC, rl_beginning_of_history }, /* Meta-< */
+  { ISFUNC, (Function *)0x0 },         /* Meta-= */
+  { ISFUNC, rl_end_of_history },       /* Meta-> */
+  { ISFUNC, rl_possible_completions }, /* Meta-? */
+  { ISFUNC, (Function *)0x0 },         /* Meta-@ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-A */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-B */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-C */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-D */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-E */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-F */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-G */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-H */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-I */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-J */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-K */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-L */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-M */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-N */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-O */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-P */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-Q */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-R */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-S */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-T */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-U */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-V */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-W */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-X */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-Y */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-[ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-\ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-] */
+  { ISFUNC, (Function *)0x0 }, /* Meta-^ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-_ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-a */
+  { ISFUNC, rl_backward_word },        /* Meta-b */
+  { ISFUNC, rl_capitalize_word }, /* Meta-c */
+  { ISFUNC, rl_kill_word },    /* Meta-d */
+  { ISFUNC, (Function *)0x0 }, /* Meta-e */
+  { ISFUNC, rl_forward_word }, /* Meta-f */
+  { ISFUNC, (Function *)0x0 }, /* Meta-g */
+  { ISFUNC, (Function *)0x0 }, /* Meta-h */
+  { ISFUNC, (Function *)0x0 }, /* Meta-i */
+  { ISFUNC, (Function *)0x0 }, /* Meta-j */
+  { ISFUNC, (Function *)0x0 }, /* Meta-k */
+  { ISFUNC, rl_downcase_word },        /* Meta-l */
+  { ISFUNC, (Function *)0x0 }, /* Meta-m */
+  { ISFUNC, (Function *)0x0 }, /* Meta-n */
+  { ISFUNC, (Function *)0x0 }, /* Meta-o */
+  { ISFUNC, (Function *)0x0 }, /* Meta-p */
+  { ISFUNC, (Function *)0x0 }, /* Meta-q */
+  { ISFUNC, rl_revert_line },  /* Meta-r */
+  { ISFUNC, (Function *)0x0 }, /* Meta-s */
+  { ISFUNC, rl_transpose_words }, /* Meta-t */
+  { ISFUNC, rl_upcase_word },  /* Meta-u */
+  { ISFUNC, (Function *)0x0 }, /* Meta-v */
+  { ISFUNC, (Function *)0x0 }, /* Meta-w */
+  { ISFUNC, (Function *)0x0 }, /* Meta-x */
+  { ISFUNC, rl_yank_pop },     /* Meta-y */
+  { ISFUNC, (Function *)0x0 }, /* Meta-z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-{ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-| */
+  { ISFUNC, (Function *)0x0 }, /* Meta-} */
+  { ISFUNC, (Function *)0x0 }, /* Meta-~ */
+  { ISFUNC, rl_backward_kill_word } /* Meta-rubout */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = {
+
+  /* Control keys. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, (Function *)0x0 },         /* Control-a */
+  { ISFUNC, (Function *)0x0 },         /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, (Function *)0x0 },         /* Control-d */
+  { ISFUNC, (Function *)0x0 },         /* Control-e */
+  { ISFUNC, (Function *)0x0 },         /* Control-f */
+  { ISFUNC, rl_abort },                        /* Control-g */
+  { ISFUNC, (Function *)0x0 },         /* Control-h */
+  { ISFUNC, (Function *)0x0 },         /* Control-i */
+  { ISFUNC, (Function *)0x0 },         /* Control-j */
+  { ISFUNC, (Function *)0x0 },         /* Control-k */
+  { ISFUNC, (Function *)0x0 },         /* Control-l */
+  { ISFUNC, (Function *)0x0 },         /* Control-m */
+  { ISFUNC, (Function *)0x0 },         /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, (Function *)0x0 },         /* Control-p */
+  { ISFUNC, (Function *)0x0 },         /* Control-q */
+  { ISFUNC, rl_re_read_init_file },    /* Control-r */
+  { ISFUNC, (Function *)0x0 },         /* Control-s */
+  { ISFUNC, (Function *)0x0 },         /* Control-t */
+  { ISFUNC, rl_undo_command },         /* Control-u */
+  { ISFUNC, (Function *)0x0 },         /* Control-v */
+  { ISFUNC, (Function *)0x0 },         /* Control-w */
+  { ISFUNC, (Function *)0x0 },         /* Control-x */
+  { ISFUNC, (Function *)0x0 },         /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+  { ISFUNC, (Function *)0x0 },         /* Control-[ */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, (Function *)0x0 },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 },         /* SPACE */
+  { ISFUNC, (Function *)0x0 },         /* ! */
+  { ISFUNC, (Function *)0x0 },         /* " */
+  { ISFUNC, (Function *)0x0 },         /* # */
+  { ISFUNC, (Function *)0x0 },         /* $ */
+  { ISFUNC, (Function *)0x0 },         /* % */
+  { ISFUNC, (Function *)0x0 },         /* & */
+  { ISFUNC, (Function *)0x0 },         /* ' */
+  { ISFUNC, rl_start_kbd_macro },      /* ( */
+  { ISFUNC, rl_end_kbd_macro  },       /* ) */
+  { ISFUNC, (Function *)0x0 },         /* * */
+  { ISFUNC, (Function *)0x0 },         /* + */
+  { ISFUNC, (Function *)0x0 },         /* , */
+  { ISFUNC, (Function *)0x0 },         /* - */
+  { ISFUNC, (Function *)0x0 },         /* . */
+  { ISFUNC, (Function *)0x0 },         /* / */
+
+  /* Regular digits. */
+  { ISFUNC, (Function *)0x0 },         /* 0 */
+  { ISFUNC, (Function *)0x0 },         /* 1 */
+  { ISFUNC, (Function *)0x0 },         /* 2 */
+  { ISFUNC, (Function *)0x0 },         /* 3 */
+  { ISFUNC, (Function *)0x0 },         /* 4 */
+  { ISFUNC, (Function *)0x0 },         /* 5 */
+  { ISFUNC, (Function *)0x0 },         /* 6 */
+  { ISFUNC, (Function *)0x0 },         /* 7 */
+  { ISFUNC, (Function *)0x0 },         /* 8 */
+  { ISFUNC, (Function *)0x0 },         /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 }, /* : */
+  { ISFUNC, (Function *)0x0 }, /* ; */
+  { ISFUNC, (Function *)0x0 }, /* < */
+  { ISFUNC, (Function *)0x0 }, /* = */
+  { ISFUNC, (Function *)0x0 }, /* > */
+  { ISFUNC, (Function *)0x0 }, /* ? */
+  { ISFUNC, (Function *)0x0 }, /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version }, /* A */
+  { ISFUNC, rl_do_lowercase_version }, /* B */
+  { ISFUNC, rl_do_lowercase_version }, /* C */
+  { ISFUNC, rl_do_lowercase_version }, /* D */
+  { ISFUNC, rl_do_lowercase_version }, /* E */
+  { ISFUNC, rl_do_lowercase_version }, /* F */
+  { ISFUNC, rl_do_lowercase_version }, /* G */
+  { ISFUNC, rl_do_lowercase_version }, /* H */
+  { ISFUNC, rl_do_lowercase_version }, /* I */
+  { ISFUNC, rl_do_lowercase_version }, /* J */
+  { ISFUNC, rl_do_lowercase_version }, /* K */
+  { ISFUNC, rl_do_lowercase_version }, /* L */
+  { ISFUNC, rl_do_lowercase_version }, /* M */
+  { ISFUNC, rl_do_lowercase_version }, /* N */
+  { ISFUNC, rl_do_lowercase_version }, /* O */
+  { ISFUNC, rl_do_lowercase_version }, /* P */
+  { ISFUNC, rl_do_lowercase_version }, /* Q */
+  { ISFUNC, rl_do_lowercase_version }, /* R */
+  { ISFUNC, rl_do_lowercase_version }, /* S */
+  { ISFUNC, rl_do_lowercase_version }, /* T */
+  { ISFUNC, rl_do_lowercase_version }, /* U */
+  { ISFUNC, rl_do_lowercase_version }, /* V */
+  { ISFUNC, rl_do_lowercase_version }, /* W */
+  { ISFUNC, rl_do_lowercase_version }, /* X */
+  { ISFUNC, rl_do_lowercase_version }, /* Y */
+  { ISFUNC, rl_do_lowercase_version }, /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* [ */
+  { ISFUNC, (Function *)0x0 },         /* \ */
+  { ISFUNC, (Function *)0x0 },         /* ] */
+  { ISFUNC, (Function *)0x0 },         /* ^ */
+  { ISFUNC, (Function *)0x0 },         /* _ */
+  { ISFUNC, (Function *)0x0 },         /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 },         /* a */
+  { ISFUNC, (Function *)0x0 },         /* b */
+  { ISFUNC, (Function *)0x0 },         /* c */
+  { ISFUNC, (Function *)0x0 },         /* d */
+  { ISFUNC, rl_call_last_kbd_macro },  /* e */
+  { ISFUNC, (Function *)0x0 },         /* f */
+  { ISFUNC, (Function *)0x0 },         /* g */
+  { ISFUNC, (Function *)0x0 },         /* h */
+  { ISFUNC, (Function *)0x0 },         /* i */
+  { ISFUNC, (Function *)0x0 },         /* j */
+  { ISFUNC, (Function *)0x0 },         /* k */
+  { ISFUNC, (Function *)0x0 },         /* l */
+  { ISFUNC, (Function *)0x0 },         /* m */
+  { ISFUNC, (Function *)0x0 },         /* n */
+  { ISFUNC, (Function *)0x0 },         /* o */
+  { ISFUNC, (Function *)0x0 },         /* p */
+  { ISFUNC, (Function *)0x0 },         /* q */
+  { ISFUNC, (Function *)0x0 },         /* r */
+  { ISFUNC, (Function *)0x0 },         /* s */
+  { ISFUNC, (Function *)0x0 },         /* t */
+  { ISFUNC, (Function *)0x0 },         /* u */
+  { ISFUNC, (Function *)0x0 },         /* v */
+  { ISFUNC, (Function *)0x0 },         /* w */
+  { ISFUNC, (Function *)0x0 },         /* x */
+  { ISFUNC, (Function *)0x0 },         /* y */
+  { ISFUNC, (Function *)0x0 },         /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* { */
+  { ISFUNC, (Function *)0x0 },         /* | */
+  { ISFUNC, (Function *)0x0 },         /* } */
+  { ISFUNC, (Function *)0x0 },         /* ~ */
+  { ISFUNC, rl_backward_kill_line }    /* RUBOUT */
+};
diff --git a/readline/funmap.c b/readline/funmap.c
new file mode 100644 (file)
index 0000000..54af607
--- /dev/null
@@ -0,0 +1,212 @@
+/* funmap.c -- attach names to functions. */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline 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 1, or (at your option) any
+   later version.
+
+   Readline 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 Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+#ifndef FILE
+#include <stdio.h>
+#endif /* FILE */
+
+#include "readline.h"
+
+FUNMAP **funmap = (FUNMAP **)NULL;
+static int funmap_size = 0;
+static int funmap_entry = 0;
+
+static FUNMAP default_funmap[] = {
+  { "beginning-of-line", rl_beg_of_line },
+  { "backward-char", rl_backward },
+  { "delete-char", rl_delete },
+  { "end-of-line", rl_end_of_line },
+  { "forward-char", rl_forward },
+  { "accept-line", rl_newline },
+  { "kill-line", rl_kill_line },
+  { "clear-screen", rl_clear_screen },
+  { "next-history", rl_get_next_history },
+  { "previous-history", rl_get_previous_history },
+  { "quoted-insert", rl_quoted_insert },
+  { "reverse-search-history", rl_reverse_search_history },
+  { "forward-search-history", rl_forward_search_history },
+  { "transpose-chars", rl_transpose_chars },
+  { "unix-line-discard", rl_unix_line_discard },
+  { "unix-word-rubout", rl_unix_word_rubout },
+  { "yank", rl_yank },
+  { "yank-pop", rl_yank_pop },
+  { "yank-nth-arg", rl_yank_nth_arg },
+  { "backward-delete-char", rl_rubout },
+  { "backward-word", rl_backward_word },
+  { "kill-word", rl_kill_word },
+  { "forward-word", rl_forward_word },
+  { "tab-insert", rl_tab_insert },
+  { "backward-kill-word", rl_backward_kill_word },
+  { "backward-kill-line", rl_backward_kill_line },
+  { "transpose-words", rl_transpose_words },
+  { "digit-argument", rl_digit_argument },
+  { "complete", rl_complete },
+  { "possible-completions", rl_possible_completions },
+  { "do-lowercase-version", rl_do_lowercase_version },
+  { "digit-argument", rl_digit_argument },
+  { "universal-argument", rl_universal_argument },
+  { "abort", rl_abort },
+  { "undo", rl_undo_command },
+  { "upcase-word", rl_upcase_word },
+  { "downcase-word", rl_downcase_word },
+  { "capitalize-word", rl_capitalize_word },
+  { "revert-line", rl_revert_line },
+  { "beginning-of-history", rl_beginning_of_history },
+  { "end-of-history", rl_end_of_history },
+  { "self-insert", rl_insert },
+  { "start-kbd-macro", rl_start_kbd_macro },
+  { "end-kbd-macro", rl_end_kbd_macro },
+  { "re-read-init-file", rl_re_read_init_file },
+#ifdef VI_MODE
+  { "vi-movement-mode", rl_vi_movement_mode },
+  { "vi-insertion-mode", rl_vi_insertion_mode },
+  { "vi-arg-digit", rl_vi_arg_digit },
+  { "vi-prev-word", rl_vi_prev_word },
+  { "vi-next-word", rl_vi_next_word },
+  { "vi-char-search", rl_vi_char_search },
+  { "vi-editing-mode", rl_vi_editing_mode },
+  { "vi-eof-maybe", rl_vi_eof_maybe },
+  { "vi-append-mode", rl_vi_append_mode },
+  { "vi-put", rl_vi_put },
+  { "vi-append-eol", rl_vi_append_eol },
+  { "vi-insert-beg", rl_vi_insert_beg },
+  { "vi-delete", rl_vi_delete },
+  { "vi-comment", rl_vi_comment },
+  { "vi-first-print", rl_vi_first_print },
+  { "vi-fword", rl_vi_fword },
+  { "vi-fWord", rl_vi_fWord },
+  { "vi-bword", rl_vi_bword },
+  { "vi-bWord", rl_vi_bWord },
+  { "vi-eword", rl_vi_eword },
+  { "vi-eWord", rl_vi_eWord },
+  { "vi-end-word", rl_vi_end_word },
+  { "vi-change-case", rl_vi_change_case },
+  { "vi-match", rl_vi_match },
+  { "vi-bracktype", rl_vi_bracktype },
+  { "vi-change-char", rl_vi_change_char },
+  { "vi-yank-arg", rl_vi_yank_arg },
+  { "vi-search", rl_vi_search },
+  { "vi-search-again", rl_vi_search_again },
+  { "vi-dosearch", rl_vi_dosearch },
+  { "vi-subst", rl_vi_subst },
+  { "vi-overstrike", rl_vi_overstrike },
+  { "vi-overstrike-delete", rl_vi_overstrike_delete },
+  { "vi-replace, ", rl_vi_replace },
+  { "vi-column", rl_vi_column },
+  { "vi-delete-to", rl_vi_delete_to },
+  { "vi-change-to", rl_vi_change_to },
+  { "vi-yank-to", rl_vi_yank_to },
+  { "vi-complete", rl_vi_complete },
+#endif /* VI_MODE */
+
+ {(char *)NULL, (Function *)NULL }
+};
+
+rl_add_funmap_entry (name, function)
+     char *name;
+     Function *function;
+{
+  if (funmap_entry + 2 >= funmap_size)
+    if (!funmap)
+      funmap = (FUNMAP **)xmalloc ((funmap_size = 80) * sizeof (FUNMAP *));
+    else
+      funmap =
+       (FUNMAP **)xrealloc (funmap, (funmap_size += 80) * sizeof (FUNMAP *));
+  
+  funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
+  funmap[funmap_entry]->name = name;
+  funmap[funmap_entry]->function = function;
+
+  funmap[++funmap_entry] = (FUNMAP *)NULL;
+}
+
+static int funmap_initialized = 0;
+
+/* Make the funmap contain all of the default entries. */
+rl_initialize_funmap ()
+{
+  register int i;
+
+  if (funmap_initialized)
+    return;
+
+  for (i = 0; default_funmap[i].name; i++)
+    rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
+
+  funmap_initialized = 1;
+}
+
+/* Things that mean `Control'. */
+char *possible_control_prefixes[] = {
+  "Control-", "C-", "CTRL-", (char *)NULL
+};
+
+char *possible_meta_prefixes[] = {
+  "Meta", "M-", (char *)NULL
+};
+
+#ifdef STATIC_MALLOC
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
diff --git a/readline/history.c b/readline/history.c
new file mode 100644 (file)
index 0000000..3c07d11
--- /dev/null
@@ -0,0 +1,1478 @@
+/* History.c -- standalone history library */
+
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+   This file contains the GNU History Library (the Library), a set of
+   routines for managing the text of previously typed lines.
+
+   The Library 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 1, or (at your option)
+   any later version.
+
+   The Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* The goal is to make the implementation transparent, so that you
+   don't have to know what data types are used, just what functions
+   you can call.  I think I have done that. */
+
+/* Remove these declarations when we have a complete libgnu.a. */
+#define STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+#include <stdio.h>
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#if defined (sparc) && defined (sun)
+#include <alloca.h>
+#else
+extern char *alloca ();
+#endif
+#endif
+
+#include "history.h"
+
+#ifndef savestring
+#define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifndef digit
+#define digit(c)  ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef member
+#define member(c, s) ((c) ? index ((s), (c)) : 0)
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     History functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* An array of HIST_ENTRY.  This is where we store the history. */
+static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
+
+/* Non-zero means that we have enforced a limit on the amount of
+   history that we save. */
+static int history_stifled = 0;
+
+/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
+   entries to remember. */
+static int max_input_history;
+
+/* The current location of the interactive history pointer.  Just makes
+   life easier for outside callers. */
+static int history_offset = 0;
+
+/* The number of strings currently stored in the input_history list. */
+static int history_length = 0;
+
+/* The current number of slots allocated to the input_history. */
+static int history_size = 0;
+
+/* The number of slots to increase the_history by. */
+#define DEFAULT_HISTORY_GROW_SIZE 50
+
+/* The character that represents the start of a history expansion
+   request.  This is usually `!'. */
+char history_expansion_char = '!';
+
+/* The character that invokes word substitution if found at the start of
+   a line.  This is usually `^'. */
+char history_subst_char = '^';
+
+/* During tokenization, if this character is seen as the first character
+   of a word, then it, and all subsequent characters upto a newline are
+   ignored.  For a Bourne shell, this should be '#'.  Bash special cases
+   the interactive comment character to not be a comment delimiter. */
+char history_comment_char = '\0';
+
+/* The list of characters which inhibit the expansion of text if found
+   immediately following history_expansion_char. */
+char *history_no_expand_chars = " \t\n\r=";
+
+/* The logical `base' of the history array.  It defaults to 1. */
+int history_base = 1;
+
+/* Begin a session in which the history functions might be used.  This
+   initializes interactive variables. */
+void
+using_history ()
+{
+  history_offset = history_length;
+}
+
+/* Place STRING at the end of the history list.  The data field
+   is  set to NULL. */
+void
+add_history (string)
+     char *string;
+{
+  HIST_ENTRY *temp;
+
+  if (history_stifled && (history_length == max_input_history)) {
+    register int i;
+
+    /* If the history is stifled, and history_length is zero,
+       and it equals max_input_history, we don't save items. */
+    if (!history_length)
+      return;
+
+    /* If there is something in the slot, then remove it. */
+    if (the_history[0]) {
+      free (the_history[0]->line);
+      free (the_history[0]);
+    }
+
+    for (i = 0; i < history_length; i++)
+      the_history[i] = the_history[i + 1];
+
+    history_base++;
+
+  } else {
+
+    if (!history_size) {
+      the_history =
+       (HIST_ENTRY **)xmalloc ((history_size = DEFAULT_HISTORY_GROW_SIZE)
+                         * sizeof (HIST_ENTRY *));
+      history_length = 1;
+
+    } else {
+      if (history_length == (history_size - 1)) {
+       the_history =
+         (HIST_ENTRY **)xrealloc (the_history,
+                                  ((history_size += DEFAULT_HISTORY_GROW_SIZE)
+                                   * sizeof (HIST_ENTRY *)));
+      }
+      history_length++;
+    }
+  }
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  temp->line = savestring (string);
+  temp->data = (char *)NULL;
+
+  the_history[history_length] = (HIST_ENTRY *)NULL;
+  the_history[history_length - 1] = temp;
+}
+
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+HIST_ENTRY *
+replace_history_entry (which, line, data)
+     int which;
+     char *line;
+     char *data;
+{
+  HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  HIST_ENTRY *old_value;
+
+  if (which >= history_length)
+    return ((HIST_ENTRY *)NULL);
+
+  old_value = the_history[which];
+
+  temp->line = savestring (line);
+  temp->data = data;
+  the_history[which] = temp;
+
+  return (old_value);
+}
+
+/* Returns the magic number which says what history element we are
+   looking at now.  In this implementation, it returns history_offset. */
+int
+where_history ()
+{
+  return (history_offset);
+}
+
+/* Search the history for STRING, starting at history_offset.
+   If DIRECTION < 0, then the search is through previous entries,
+   else through subsequent.  If the string is found, then
+   current_history () is the history entry, and the value of this function
+   is the offset in the line of that history entry that the string was
+   found in.  Otherwise, nothing is changed, and a -1 is returned. */
+int
+history_search (string, direction)
+     char *string;
+     int direction;
+{
+  register int i = history_offset;
+  register int reverse = (direction < 0);
+  register char *line;
+  register int index;
+  int string_len = strlen (string);
+
+  /* Take care of trivial cases first. */
+
+  if (!history_length || ((i == history_length) && !reverse))
+    return (-1);
+
+  if (reverse && (i == history_length))
+    i--;
+
+  while (1)
+    {
+      /* Search each line in the history list for STRING. */
+
+      /* At limit for direction? */
+      if ((reverse && i < 0) ||
+         (!reverse && i == history_length))
+       return (-1);
+
+      line = the_history[i]->line;
+      index = strlen (line);
+
+      /* If STRING is longer than line, no match. */
+      if (string_len > index)
+       goto next_line;
+
+      /* Do the actual search. */
+      if (reverse)
+       {
+         index -= string_len;
+
+         while (index >= 0)
+           {
+             if (strncmp (string, line + index, string_len) == 0)
+               {
+                 history_offset = i;
+                 return (index);
+               }
+             index--;
+           }
+       }
+      else
+       {
+         register int limit = (string_len - index) + 1;
+         index = 0;
+
+         while (index < limit)
+           {
+             if (strncmp (string, line + index, string_len) == 0)
+               {
+                 history_offset = i;
+                 return (index);
+               }
+             index++;
+           }
+       }
+    next_line:
+      if (reverse)
+       i--;
+      else
+       i++;
+    }
+}
+
+/* Remove history element WHICH from the history.  The removed
+   element is returned to you so you can free the line, data,
+   and containing structure. */
+HIST_ENTRY *
+remove_history (which)
+     int which;
+{
+  HIST_ENTRY *return_value;
+
+  if (which >= history_length || !history_length)
+    return_value = (HIST_ENTRY *)NULL;
+  else
+    {
+      register int i;
+      return_value = the_history[which];
+
+      for (i = which; i < history_length; i++)
+       the_history[i] = the_history[i + 1];
+
+      history_length--;
+    }
+  return (return_value);
+}
+
+/* Stifle the history list, remembering only MAX number of lines. */
+void
+stifle_history (max)
+     int max;
+{
+  if (history_length > max)
+    {
+      register int i, j;
+
+      /* This loses because we cannot free the data. */
+      for (i = 0; i < (history_length - max); i++)
+       {
+         free (the_history[i]->line);
+         free (the_history[i]);
+       }
+      history_base = i;
+      for (j = 0, i = history_length - max; j < max; i++, j++)
+       the_history[j] = the_history[i];
+      the_history[j] = (HIST_ENTRY *)NULL;
+      history_length = j;
+    }
+  history_stifled = 1;
+  max_input_history = max;
+}
+
+/* Stop stifling the history.  This returns the previous amount the history
+ was stifled by.  The value is positive if the history was stifled, negative
+ if it wasn't. */
+int
+unstifle_history ()
+{
+  int result = max_input_history;
+  if (history_stifled)
+    {
+      result = - result;
+      history_stifled = 0;
+    }
+  return (result);
+}
+
+/* Return the string that should be used in the place of this
+   filename.  This only matters when you don't specify the
+   filename to read_history (), or write_history (). */
+static char *
+history_filename (filename)
+     char *filename;
+{
+  char *return_val = filename ? savestring (filename) : (char *)NULL;
+
+  if (!return_val)
+    {
+      char *home = (char *)getenv ("HOME");
+      if (!home) home = ".";
+      return_val = (char *)xmalloc (2 + strlen (home) + strlen (".history"));
+      strcpy (return_val, home);
+      strcat (return_val, "/");
+      strcat (return_val, ".history");
+    }
+  return (return_val);
+}
+
+/* What to use until the line gets too big. */
+#define TYPICAL_LINE_SIZE 2048
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
+   successful, or errno if not. */
+int
+read_history (filename)
+     char *filename;
+{
+  char *input = history_filename (filename);
+  FILE *file = fopen (input, "r");
+  char *line = (char *)xmalloc (TYPICAL_LINE_SIZE);
+  int line_size = TYPICAL_LINE_SIZE;
+  int done = 0;
+
+  if (!file)
+    {
+      extern int errno;
+      free (line);
+      return (errno);
+    }
+
+  while (!done)
+    {
+      int c;
+      int i;
+
+      i = 0;
+      while (!(done = ((c = getc (file)) == EOF)))
+       {
+         if (c == '\n')
+           break;
+
+         line [i++] = c;
+         if (i == line_size)
+           line = (char *)xrealloc (line, line_size += TYPICAL_LINE_SIZE);
+       }
+      line[i] = '\0';
+      if (line[0])
+       add_history (line);
+    }
+  free (line);
+  fclose (file);
+  return (0);
+}
+
+/* Overwrite FILENAME with the current history.  If FILENAME is NULL,
+   then write the history list to ~/.history.  Values returned
+   are as in read_history ().*/
+int
+write_history (filename)
+     char *filename;
+{
+  extern int errno;
+  char *output = history_filename (filename);
+  FILE *file = fopen (output, "w");
+  register int i;
+
+  if (!file) return (errno);
+  if (!history_length) return (0);
+
+  for (i = 0; i < history_length; i++)
+    fprintf (file, "%s\n", the_history[i]->line);
+
+  fclose (file);
+  return (0);
+}
+
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *
+current_history ()
+{
+  if ((history_offset == history_length) || !the_history)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[history_offset]);
+}
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry then return
+   a NULL pointer. */
+HIST_ENTRY *
+previous_history ()
+{
+  if (!history_offset)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[--history_offset]);
+}
+
+/* Move history_offset forward to the next history entry, and return
+   a pointer to that entry.  If there is no next entry then return a
+   NULL pointer. */
+HIST_ENTRY *
+next_history ()
+{
+  if (history_offset == history_length)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[++history_offset]);
+}
+
+/* Return the current history array.  The caller has to be carefull, since this
+   is the actual array of data, and could be bashed or made corrupt easily.
+   The array is terminated with a NULL pointer. */
+HIST_ENTRY **
+history_list ()
+{
+  return (the_history);
+}
+
+/* Return the history entry which is logically at OFFSET in the history array.
+   OFFSET is relative to history_base. */
+HIST_ENTRY *
+history_get (offset)
+     int offset;
+{
+  int index = offset - history_base;
+
+  if (index >= history_length ||
+      index < 0 ||
+      !the_history)
+    return ((HIST_ENTRY *)NULL);
+  return (the_history[index]);
+}
+
+/* Search for STRING in the history list.  DIR is < 0 for searching
+   backwards.  POS is an absolute index into the history list at
+   which point to begin searching. */
+int
+history_search_pos (string, dir, pos)
+     char *string;
+     int dir, pos;
+{
+  int ret, old = where_history ();
+  history_set_pos (pos);
+  if (history_search (string, dir) == -1)
+    {
+      history_set_pos (old);
+      return (-1);
+    }
+  ret = where_history ();
+  history_set_pos (old);
+  return ret;
+}
+
+/* Make the current history item be the one at POS, an absolute index.
+   Returns zero if POS is out of range, else non-zero. */
+int
+history_set_pos (pos)
+     int pos;
+{
+  if (pos > history_length || pos < 0 || !the_history)
+    return (0);
+  history_offset = pos;
+  return (1);
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Expansion                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Hairy history expansion on text, not tokens.  This is of general
+   use, and thus belongs in this library. */
+
+/* The last string searched for in a !?string? search. */
+static char *search_string = (char *)NULL;
+
+/* Return the event specified at TEXT + OFFSET modifying OFFSET to
+   point to after the event specifier.  Just a pointer to the history
+   line is returned; NULL is returned in the event of a bad specifier.
+   You pass STRING with *INDEX equal to the history_expansion_char that
+   begins this specification.
+   DELIMITING_QUOTE is a character that is allowed to end the string
+   specification for what to search for in addition to the normal
+   characters `:', ` ', `\t', `\n', and sometimes `?'.
+   So you might call this function like:
+   line = get_history_event ("!echo:p", &index, 0);  */
+char *
+get_history_event (string, caller_index, delimiting_quote)
+     char *string;
+     int *caller_index;
+     int delimiting_quote;
+{
+  register int i = *caller_index;
+  int which, sign = 1;
+  HIST_ENTRY *entry;
+
+  /* The event can be specified in a number of ways.
+
+     !!   the previous command
+     !n   command line N
+     !-n  current command-line minus N
+     !str the most recent command starting with STR
+     !?str[?]
+         the most recent command containing STR
+
+     All values N are determined via HISTORY_BASE. */
+
+  if (string[i] != history_expansion_char)
+    return ((char *)NULL);
+
+  /* Move on to the specification. */
+  i++;
+
+  /* Handle !! case. */
+  if (string[i] == history_expansion_char)
+    {
+      i++;
+      which = history_base + (history_length - 1);
+      *caller_index = i;
+      goto get_which;
+    }
+
+  /* Hack case of numeric line specification. */
+ read_which:
+  if (string[i] == '-')
+    {
+      sign = -1;
+      i++;
+    }
+
+  if (digit (string[i]))
+    {
+      int start = i;
+
+      /* Get the extent of the digits. */
+      for (; digit (string[i]); i++);
+
+      /* Get the digit value. */
+      sscanf (string + start, "%d", &which);
+
+      *caller_index = i;
+
+      if (sign < 0)
+       which = (history_length + history_base) - which;
+
+    get_which:
+      if (entry = history_get (which))
+       return (entry->line);
+
+      return ((char *)NULL);
+    }
+
+  /* This must be something to search for.  If the spec begins with
+     a '?', then the string may be anywhere on the line.  Otherwise,
+     the string must be found at the start of a line. */
+  {
+    int index;
+    char *temp;
+    int substring_okay = 0;
+
+    if (string[i] == '?')
+      {
+       substring_okay++;
+       i++;
+      }
+
+    for (index = i; string[i]; i++)
+      if (whitespace (string[i]) ||
+         string[i] == '\n' ||
+         string[i] == ':' ||
+         (substring_okay && string[i] == '?') ||
+         string[i] == delimiting_quote)
+       break;
+
+    temp = (char *)alloca (1 + (i - index));
+    strncpy (temp, &string[index], (i - index));
+    temp[i - index] = '\0';
+
+    if (string[i] == '?')
+      i++;
+
+    *caller_index = i;
+
+  search_again:
+
+    index = history_search (temp, -1);
+
+    if (index < 0)
+    search_lost:
+      {
+       history_offset = history_length;
+       return ((char *)NULL);
+      }
+
+    if (index == 0 || substring_okay || 
+       (strncmp (temp, the_history[history_offset]->line,
+                 strlen (temp)) == 0))
+      {
+      search_won:
+       entry = current_history ();
+       history_offset = history_length;
+       
+       /* If this was a substring search, then remember the string that
+          we matched for word substitution. */
+       if (substring_okay)
+         {
+           if (search_string)
+             free (search_string);
+           search_string = savestring (temp);
+         }
+
+       return (entry->line);
+      }
+
+    if (history_offset)
+      history_offset--;
+    else
+      goto search_lost;
+    
+    goto search_again;
+  }
+}
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+   to a string.  Returns:
+
+   0) If no expansions took place (or, if the only change in
+      the text was the de-slashifying of the history expansion
+      character)
+   1) If expansions did take place
+  -1) If there was an error in expansion.
+
+  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  error message. */
+int
+history_expand (string, output)
+     char *string;
+     char **output;
+{
+  register int j, l = strlen (string);
+  int i, word_spec_error = 0;
+  int cc, modified = 0;
+  char *word_spec, *event;
+  int starting_index, only_printing = 0, substitute_globally = 0;
+
+  char *get_history_word_specifier (), *rindex ();
+
+  /* The output string, and its length. */
+  int len = 0;
+  char *result = (char *)NULL;
+
+  /* Used in add_string; */
+  char *temp, tt[2], tbl[3];
+
+  /* Prepare the buffer for printing error messages. */
+  result = (char *)xmalloc (len = 255);
+
+  result[0] = tt[1] = tbl[2] = '\0';
+  tbl[0] = '\\';
+  tbl[1] = history_expansion_char;
+
+  /* Grovel the string.  Only backslash can quote the history escape
+     character.  We also handle arg specifiers. */
+
+  /* Before we grovel forever, see if the history_expansion_char appears
+     anywhere within the text. */
+
+  /* The quick substitution character is a history expansion all right.  That
+     is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
+     that is the substitution that we do. */
+  if (string[0] == history_subst_char)
+    {
+      char *format_string = (char *)alloca (10 + strlen (string));
+
+      sprintf (format_string, "%c%c:s%s",
+              history_expansion_char, history_expansion_char,
+              string);
+      string = format_string;
+      l += 4;
+      goto grovel;
+    }
+
+  /* If not quick substitution, still maybe have to do expansion. */
+
+  /* `!' followed by one of the characters in history_no_expand_chars
+     is NOT an expansion. */
+  for (i = 0; string[i]; i++)
+    if (string[i] == history_expansion_char)
+      if (!string[i + 1] || member (string[i + 1], history_no_expand_chars))
+       continue;
+      else
+       goto grovel;
+
+  free (result);
+  *output = savestring (string);
+  return (0);
+
+ grovel:
+
+  for (i = j = 0; i < l; i++)
+    {
+      int tchar = string[i];
+      if (tchar == history_expansion_char)
+       tchar = -3;
+
+      switch (tchar)
+       {
+       case '\\':
+         if (string[i + 1] == history_expansion_char)
+           {
+             i++;
+             temp = tbl;
+             goto do_add;
+           }
+         else
+           goto add_char;
+
+         /* case history_expansion_char: */
+       case -3:
+         starting_index = i + 1;
+         cc = string[i + 1];
+
+         /* If the history_expansion_char is followed by one of the
+            characters in history_no_expand_chars, then it is not a
+            candidate for expansion of any kind. */
+         if (member (cc, history_no_expand_chars))
+           goto add_char;
+
+         /* There is something that is listed as a `word specifier' in csh
+            documentation which means `the expanded text to this point'.
+            That is not a word specifier, it is an event specifier. */
+
+         if (cc == '#')
+           goto hack_pound_sign;
+
+         /* If it is followed by something that starts a word specifier,
+            then !! is implied as the event specifier. */
+
+         if (member (cc, ":$*%^"))
+           {
+             char fake_s[3];
+             int fake_i = 0;
+             i++;
+             fake_s[0] = fake_s[1] = history_expansion_char;
+             fake_s[2] = '\0';
+             event = get_history_event (fake_s, &fake_i, 0);
+           }
+         else
+           {
+             int quoted_search_delimiter = 0;
+
+             /* If the character before this `!' is a double or single
+                quote, then this expansion takes place inside of the
+                quoted string.  If we have to search for some text ("!foo"),
+                allow the delimiter to end the search string. */
+             if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
+               quoted_search_delimiter = string[i - 1];
+
+             event = get_history_event (string, &i, quoted_search_delimiter);
+           }
+         
+         if (!event)
+         event_not_found:
+           {
+           int l = 1 + (i - starting_index);
+
+           temp = (char *)alloca (1 + l);
+           strncpy (temp, string + starting_index, l);
+           temp[l - 1] = 0;
+           sprintf (result, "%s: %s.", temp,
+                    word_spec_error ? "Bad word specifier" : "Event not found");
+         error_exit:
+           *output = result;
+           return (-1);
+         }
+
+         /* If a word specifier is found, then do what that requires. */
+         starting_index = i;
+
+         word_spec = get_history_word_specifier (string, event, &i);
+
+         /* There is no such thing as a `malformed word specifier'.  However,
+            it is possible for a specifier that has no match.  In that case,
+            we complain. */
+         if (word_spec == (char *)-1)
+         bad_word_spec:
+         {
+           word_spec_error++;
+           goto event_not_found;
+         }
+
+         /* If no word specifier, than the thing of interest was the event. */
+         if (!word_spec)
+           temp = event;
+         else
+           {
+             temp = (char *)alloca (1 + strlen (word_spec));
+             strcpy (temp, word_spec);
+             free (word_spec);
+           }
+
+         /* Perhaps there are other modifiers involved.  Do what they say. */
+
+       hack_specials:
+
+         if (string[i] == ':')
+           {
+             char *tstr;
+
+             switch (string[i + 1])
+               {
+                 /* :p means make this the last executed line.  So we
+                    return an error state after adding this line to the
+                    history. */
+               case 'p':
+                 only_printing++;
+                 goto next_special;
+
+                 /* :t discards all but the last part of the pathname. */
+               case 't':
+                 tstr = rindex (temp, '/');
+                 if (tstr)
+                   temp = ++tstr;
+                 goto next_special;
+
+                 /* :h discards the last part of a pathname. */
+               case 'h':
+                 tstr = rindex (temp, '/');
+                 if (tstr)
+                   *tstr = '\0';
+                 goto next_special;
+
+                 /* :r discards the suffix. */
+               case 'r':
+                 tstr = rindex (temp, '.');
+                 if (tstr)
+                   *tstr = '\0';
+                 goto next_special;
+
+                 /* :e discards everything but the suffix. */
+               case 'e':
+                 tstr = rindex (temp, '.');
+                 if (tstr)
+                   temp = tstr;
+                 goto next_special;
+
+                 /* :s/this/that substitutes `this' for `that'. */
+                 /* :gs/this/that substitutes `this' for `that' globally. */
+               case 'g':
+                 if (string[i + 2] == 's')
+                   {
+                     i++;
+                     substitute_globally = 1;
+                     goto substitute;
+                   }
+                 else
+                   
+               case 's':
+                 substitute:
+                 {
+                   char *this, *that, *new_event;
+                   int delimiter = 0;
+                   int si, l_this, l_that, l_temp = strlen (temp);
+
+                   if (i + 2 < strlen (string))
+                     delimiter = string[i + 2];
+
+                   if (!delimiter)
+                     break;
+
+                   i += 3;
+
+                   /* Get THIS. */
+                   for (si = i; string[si] && string[si] != delimiter; si++);
+                   l_this = (si - i);
+                   this = (char *)alloca (1 + l_this);
+                   strncpy (this, string + i, l_this);
+                   this[l_this] = '\0';
+
+                   i = si;
+                   if (string[si])
+                     i++;
+
+                   /* Get THAT. */
+                   for (si = i; string[si] && string[si] != delimiter; si++);
+                   l_that = (si - i);
+                   that = (char *)alloca (1 + l_that);
+                   strncpy (that, string + i, l_that);
+                   that[l_that] = '\0';
+
+                   i = si;
+                   if (string[si]) i++;
+
+                   /* Ignore impossible cases. */
+                   if (l_this > l_temp)
+                     goto cant_substitute;
+
+                   /* Find the first occurrence of THIS in TEMP. */
+                   si = 0;
+                   for (; (si + l_this) <= l_temp; si++)
+                     if (strncmp (temp + si, this, l_this) == 0)
+                       {
+                         new_event =
+                           (char *)alloca (1 + (l_that - l_this) + l_temp);
+                         strncpy (new_event, temp, si);
+                         strncpy (new_event + si, that, l_that);
+                         strncpy (new_event + si + l_that,
+                                  temp + si + l_this,
+                                  l_temp - (si + l_this));
+                         new_event[(l_that - l_this) + l_temp] = '\0';
+                         temp = new_event;
+
+                         if (substitute_globally)
+                           {
+                             si += l_that;
+                             l_temp = strlen (temp);
+                             substitute_globally++;
+                             continue;
+                           }
+
+                         goto hack_specials;
+                       }
+
+                 cant_substitute:
+
+                   if (substitute_globally > 1)
+                     {
+                       substitute_globally = 0;
+                       goto hack_specials;
+                     }
+
+                   goto event_not_found;
+                 }
+
+                 /* :# is the line so far.  Note that we have to
+                    alloca () it since RESULT could be realloc ()'ed
+                    below in add_string. */
+               case '#':
+               hack_pound_sign:
+                 if (result)
+                   {
+                     temp = (char *)alloca (1 + strlen (result));
+                     strcpy (temp, result);
+                   }
+                 else
+                   temp = "";
+
+               next_special:
+                 i += 2;
+                 goto hack_specials;
+               }
+
+           }
+         /* Believe it or not, we have to back the pointer up by one. */
+         --i;
+         goto add_string;
+
+         /* A regular character.  Just add it to the output string. */
+       default:
+       add_char:
+         tt[0] = string[i];
+         temp = tt;
+         goto do_add;
+
+       add_string:
+         modified++;
+
+       do_add:
+         j += strlen (temp);
+         while (j > len)
+           result = (char *)xrealloc (result, (len += 255));
+
+         strcpy (result + (j - strlen (temp)), temp);
+       }
+    }
+
+  *output = result;
+
+  if (only_printing)
+    {
+      add_history (result);
+      return (-1);
+    }
+
+  return (modified != 0);
+}
+
+/* Return a consed string which is the word specified in SPEC, and found
+   in FROM.  NULL is returned if there is no spec.  -1 is returned if
+   the word specified cannot be found.  CALLER_INDEX is the offset in
+   SPEC to start looking; it is updated to point to just after the last
+   character parsed. */
+char *
+get_history_word_specifier (spec, from, caller_index)
+     char *spec, *from;
+     int *caller_index;
+{
+  register int i = *caller_index;
+  int first, last;
+  int expecting_word_spec = 0;
+  char *history_arg_extract ();
+
+  /* The range of words to return doesn't exist yet. */
+  first = last = 0;
+
+  /* If we found a colon, then this *must* be a word specification.  If
+     it isn't, then it is an error. */
+  if (spec[i] == ':')
+    i++, expecting_word_spec++;
+
+  /* Handle special cases first. */
+
+  /* `%' is the word last searched for. */
+  if (spec[i] == '%')
+    {
+      *caller_index = i + 1;
+      if (search_string)
+       return (savestring (search_string));
+      else
+       return (savestring (""));
+    }
+
+  /* `*' matches all of the arguments, but not the command. */
+  if (spec[i] == '*')
+    {
+      char *star_result;
+
+      *caller_index = i + 1;
+      star_result = history_arg_extract (1, '$', from);
+
+      if (!star_result)
+       star_result = savestring ("");
+
+      return (star_result);
+    }
+
+  /* `$' is last arg. */
+  if (spec[i] == '$')
+    {
+      *caller_index = i + 1;
+      return (history_arg_extract ('$', '$', from));
+    }
+
+  /* Try to get FIRST and LAST figured out. */
+  if (spec[i] == '-' || spec[i] == '^')
+    {
+      first = 1;
+      goto get_last;
+    }
+
+ get_first:
+  if (digit (spec[i]) && expecting_word_spec)
+    {
+      sscanf (spec + i, "%d", &first);
+      for (; digit (spec[i]); i++);
+    }
+  else
+    return ((char *)NULL);
+
+ get_last:
+  if (spec[i] == '^')
+    {
+      i++;
+      last = 1;
+      goto get_args;
+    }
+
+  if (spec[i] != '-')
+    {
+      last = first;
+      goto get_args;
+    }
+
+  i++;
+
+  if (digit (spec[i]))
+    {
+      sscanf (spec + i, "%d", &last);
+      for (; digit (spec[i]); i++);
+    }
+  else
+    if (spec[i] == '$')
+      {
+       i++;
+       last = '$';
+      }
+
+ get_args:
+  {
+    char *result = (char *)NULL;
+
+    *caller_index = i;
+
+    if (last >= first)
+      result = history_arg_extract (first, last, from);
+
+    if (result)
+      return (result);
+    else
+      return ((char *)-1);
+  }
+}
+
+/* Extract the args specified, starting at FIRST, and ending at LAST.
+   The args are taken from STRING.  If either FIRST or LAST is < 0,
+   then make that arg count from the right (subtract from the number of
+   tokens, so that FIRST = -1 means the next to last token on the line. */
+char *
+history_arg_extract (first, last, string)
+     int first, last;
+     char *string;
+{
+  register int i, len;
+  char *result = (char *)NULL;
+  int size = 0, offset = 0;
+
+  char **history_tokenize (), **list;
+
+  if (!(list = history_tokenize (string)))
+    return ((char *)NULL);
+
+  for (len = 0; list[len]; len++);
+
+  if (last < 0)
+    last = len + last - 1;
+
+  if (first < 0)
+    first = len + first - 1;
+
+  if (last == '$')
+    last = len - 1;
+
+  if (first == '$')
+    first = len - 1;
+
+  last++;
+
+  if (first > len || last > len)
+    result = ((char *)NULL);
+  else
+    {
+      for (i = first; i < last; i++)
+       {
+         int l = strlen (list[i]);
+
+         if (!result)
+           result = (char *)xmalloc ((size = (2 + l)));
+         else
+           result = (char *)xrealloc (result, (size += (2 + l)));
+         strcpy (result + offset, list[i]);
+         offset += l;
+         if (i + 1 < last)
+           {
+             strcpy (result + offset, " ");
+             offset++;
+           }
+       }
+    }
+
+  for (i = 0; i < len; i++)
+    free (list[i]);
+
+  free (list);
+
+  return (result);
+}
+
+#define slashify_in_quotes "\\`\"$"
+
+/* Return an array of tokens, much as the shell might.  The tokens are
+   parsed out of STRING. */
+char **
+history_tokenize (string)
+     char *string;
+{
+  char **result = (char **)NULL;
+  register int i, start, result_index, size;
+  int len;
+
+  i = result_index = size = 0;
+
+  /* Get a token, and stuff it into RESULT.  The tokens are split
+     exactly where the shell would split them. */
+ get_token:
+
+  /* Skip leading whitespace. */
+  for (; string[i] && whitespace(string[i]); i++);
+
+  start = i;
+
+  if (!string[i] || string[i] == history_comment_char)
+    return (result);
+
+  if (member (string[i], "()\n")) {
+    i++;
+    goto got_token;
+  }
+
+  if (member (string[i], "<>;&|")) {
+    int peek = string[i + 1];
+
+    if (peek == string[i]) {
+      if (peek ==  '<') {
+       if (string[1 + 2] == '-')
+         i++;
+       i += 2;
+       goto got_token;
+      }
+
+      if (member (peek, ">:&|")) {
+       i += 2;
+       goto got_token;
+      }
+    } else {
+      if ((peek == '&' &&
+         (string[i] == '>' || string[i] == '<')) ||
+         ((peek == '>') &&
+         (string[i] == '&'))) {
+       i += 2;
+       goto got_token;
+      }
+    }
+    i++;
+    goto got_token;
+  }
+
+  /* Get word from string + i; */
+  {
+    int delimiter = 0;
+
+    if (member (string[i], "\"'`"))
+      delimiter = string[i++];
+
+    for (;string[i]; i++) {
+
+      if (string[i] == '\\') {
+
+       if (string[i + 1] == '\n') {
+         i++;
+         continue;
+       } else {
+         if (delimiter != '\'')
+           if ((delimiter != '"') ||
+               (member (string[i], slashify_in_quotes))) {
+             i++;
+             continue;
+           }
+       }
+      }
+
+      if (delimiter && string[i] == delimiter) {
+       delimiter = 0;
+       continue;
+      }
+
+      if (!delimiter && (member (string[i], " \t\n;&()|<>")))
+       goto got_token;
+
+      if (!delimiter && member (string[i], "\"'`")) {
+       delimiter = string[i];
+       continue;
+      }
+    }
+    got_token:
+
+    len = i - start;
+    if (result_index + 2 >= size) {
+      if (!size)
+       result = (char **)xmalloc ((size = 10) * (sizeof (char *)));
+      else
+       result =
+         (char **)xrealloc (result, ((size += 10) * (sizeof (char *))));
+    }
+    result[result_index] = (char *)xmalloc (1 + len);
+    strncpy (result[result_index], string + start, len);
+    result[result_index][len] = '\0';
+    result_index++;
+    result[result_index] = (char *)NULL;
+  }
+  if (string[i])
+    goto get_token;
+
+  return (result);
+}
+
+#ifdef STATIC_MALLOC
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                             Test Code                           */
+/*                                                                 */
+/* **************************************************************** */
+#ifdef TEST
+main ()
+{
+  char line[1024], *t;
+  int done = 0;
+
+  line[0] = 0;
+
+  while (!done)
+    {
+      fprintf (stdout, "history%% ");
+      t = gets (line);
+
+      if (!t)
+       strcpy (line, "quit");
+
+      if (line[0])
+       {
+         char *expansion;
+         int result;
+
+         using_history ();
+
+         result = history_expand (line, &expansion);
+         strcpy (line, expansion);
+         free (expansion);
+         if (result)
+           fprintf (stderr, "%s\n", line);
+
+         if (result < 0)
+           continue;
+
+         add_history (line);
+       }
+
+      if (strcmp (line, "quit") == 0) done = 1;
+      if (strcmp (line, "save") == 0) write_history (0);
+      if (strcmp (line, "read") == 0) read_history (0);
+      if (strcmp (line, "list") == 0)
+       {
+         register HIST_ENTRY **the_list = history_list ();
+         register int i;
+
+         if (the_list)
+           for (i = 0; the_list[i]; i++)
+             fprintf (stdout, "%d: %s\n", i + history_base, the_list[i]->line);
+       }
+      if (strncmp (line, "delete", strlen ("delete")) == 0)
+       {
+         int which;
+         if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1)
+           {
+             HIST_ENTRY *entry = remove_history (which);
+             if (!entry)
+               fprintf (stderr, "No such entry %d\n", which);
+             else
+               {
+                 free (entry->line);
+                 free (entry);
+               }
+           }
+         else
+           {
+             fprintf (stderr, "non-numeric arg given to `delete'\n");
+           }
+       }
+    }
+}
+
+#endif                         /* TEST */
+\f
+/*
+* Local variables:
+* compile-command: "gcc -g -DTEST -o history history.c"
+* end:
+*/
diff --git a/readline/history.h b/readline/history.h
new file mode 100644 (file)
index 0000000..0bac209
--- /dev/null
@@ -0,0 +1,108 @@
+/* History.h -- the names of functions that you can call in history. */
+
+typedef struct _hist_entry {
+  char *line;
+  char *data;
+} HIST_ENTRY;
+
+/* For convenience only.  You set this when interpreting history commands.
+   It is the logical offset of the first history element. */
+extern int history_base;
+
+/* Begin a session in which the history functions might be used.  This
+   just initializes the interactive variables. */
+extern void using_history ();
+
+/* Place STRING at the end of the history list.
+   The associated data field (if any) is set to NULL. */
+extern void add_history ();
+
+/* Returns the number which says what history element we are now
+   looking at.  */
+extern int where_history ();
+  
+/* Set the position in the history list to POS. */
+int history_set_pos ();
+   
+/* Search for STRING in the history list, starting at POS, an
+   absolute index into the list.  DIR, if negative, says to search
+   backwards from POS, else forwards.
+   Returns the absolute index of the history element where STRING
+   was found, or -1 otherwise. */
+extern int history_search_pos ();
+
+/* A reasonably useless function, only here for completeness.  WHICH
+   is the magic number that tells us which element to delete.  The
+   elements are numbered from 0. */
+extern HIST_ENTRY *remove_history ();
+
+/* Stifle the history list, remembering only MAX number of entries. */
+extern void stifle_history ();
+
+/* Stop stifling the history.  This returns the previous amount the
+   history was stifled by.  The value is positive if the history was
+   stifled, negative if it wasn't. */
+extern int unstifle_history ();
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
+   successful, or errno if not. */
+extern int read_history ();
+
+/* Append the current history to FILENAME.  If FILENAME is NULL,
+   then append the history list to ~/.history.  Values returned
+   are as in read_history ().  */
+extern int write_history ();
+
+
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+extern HIST_ENTRY *replace_history_entry ();
+
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *current_history ();
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry, return
+   a NULL pointer. */
+extern HIST_ENTRY *previous_history ();
+
+/* Move history_offset forward to the next item in the input_history,
+   and return the a pointer to that entry.  If there is no next entry,
+   return a NULL pointer. */
+extern HIST_ENTRY *next_history ();
+
+/* Return a NULL terminated array of HIST_ENTRY which is the current input
+   history.  Element 0 of this list is the beginning of time.  If there
+   is no history, return NULL. */
+extern HIST_ENTRY **history_list ();
+
+/* Search the history for STRING, starting at history_offset.
+   If DIRECTION < 0, then the search is through previous entries,
+   else through subsequent.  If the string is found, then
+   current_history () is the history entry, and the value of this function
+   is the offset in the line of that history entry that the string was
+   found in.  Otherwise, nothing is changed, and a -1 is returned. */
+extern int history_search ();
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+   to a string.  Returns:
+
+   0) If no expansions took place (or, if the only change in
+      the text was the de-slashifying of the history expansion
+      character)
+   1) If expansions did take place
+  -1) If there was an error in expansion.
+
+  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  error message. */
+extern int history_expand ();
+
+/* Extract a string segment consisting of the FIRST through LAST
+   arguments present in STRING.  Arguments are broken up as in
+   the shell. */
+extern char *history_arg_extract ();
+
+
diff --git a/readline/history.texinfo b/readline/history.texinfo
new file mode 100755 (executable)
index 0000000..1e619e1
--- /dev/null
@@ -0,0 +1,194 @@
+\input texinfo.tex
+@setfilename history.info
+
+@ifinfo
+This file documents the GNU History library.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+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 also that the
+GNU Copyright statement is available to the distributee, and 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
+
+@node Top, Introduction, , (DIR)
+
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+@menu
+* Introduction::       What is the GNU History library for?
+* Interactive Use::    What it feels like using History as a user.
+* Programming::                How to use History in your programs.
+@end menu
+
+@node Introduction, Interactive Use, , Top
+@unnumbered Introduction
+
+Many programs read input from the user a line at a time.  The GNU history
+library is able to keep track of those lines, associate arbitrary data with
+each line, and utilize information from previous lines in making up new
+ones.
+
+The programmer using the History library has available to him functions for
+remembering lines on a history stack, associating arbitrary data with a
+line, removing lines from the stack, searching through the stack for a
+line containing an arbitrary text string, and referencing any line on the
+stack directly.  In addition, a history @dfn{expansion} function is
+available which provides for a consistent user interface across many
+different programs.
+
+The end-user using programs written with the History library has the
+benifit of a consistent user interface, with a set of well-known commands
+for manipulating the text of previous lines and using that text in new
+commands.  The basic history manipulation commands are similar to the
+history substitution used by Csh.
+
+If the programmer desires, he can use the Readline library, which includes
+history manipulation by default, and has the added advantage of Emacs style
+command line editing.
+
+@node Interactive Use, Programming, Introduction, Top
+@chapter Interactive Use
+
+@section History Expansion
+@cindex expansion
+
+The History library provides a history expansion feature that is similar to
+the history expansion in Csh.  The following text describes what syntax
+features are available.
+
+History expansion takes place in two parts.  The first is to determine
+which line from the previous history should be used during substitution.
+The second is to select portions of that line for inclusion into the
+current one.  The line selected from the previous history is called the
+@dfn{event}, and the portions of that line that are acted upon are called
+@dfn{words}.  The line is broken into words in the same fashion that the
+Bash shell does, so that several English (or Unix) words surrounded by
+quotes are considered as one word.
+
+@menu
+* Event Designators::  How to specify which history line to use.
+* Word Designators::   Specifying which words are of interest.
+* Modifiers::          Modifying the results of susbstitution.
+@end menu
+
+@node Event Designators, Word Designators, , Interactive Use
+@subsection Event Designators
+@cindex event designators
+
+An event designator is a reference to a command line entry in the history
+list.
+
+@table @var
+
+@item !
+Start a history subsititution, except when followed by a @key{SPC},
+@key{TAB}, @key{RET}, @key{=} or @key{(}.
+
+@item !!
+Refer to the previous command.  This is a synonym for @code{!-1}.
+
+@item !n
+Refer to command line @var{n}.
+
+@item !-n
+Refer to the current command line minus @var{n}.
+
+@item !string
+Refer to the most recent command starting with @var{string}.
+
+@item !?string[?]
+Refer to the most recent command containing @var{string}.
+
+@end table
+
+@node Word Designators, Modifiers, Event Designators, Interactive Use
+@subsection Word Designators
+
+A @key{:} separates the event specification from the word designator.  It
+can be omitted if the word designator begins with a @key{^}, @key{$},
+@key{*} or @key{%}.  Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+
+@table @asis
+
+@item @var{0} (zero)
+The zero'th word.  For many applications, this is the command word.
+
+@item n
+The @var{n}'th word.
+
+@item @var{^}
+The first argument.  that is, word 1.
+
+@item @var{$}
+The last argument.
+
+@item @var{%}
+The word matched by the most recent @code{?string?} search.
+
+@item @var{x}-@var{y}
+A range of words; @code{-@var{y}} is equivalent to @code{0-@var{y}}.
+
+@item @var{*}
+All of the words, excepting the zero'th.  This is a synonym for @samp{1-$}.
+It is not an error to use @samp{*} if there is just one word in the event.
+The empty string is returned in that case.
+
+@end table
+
+@node Modifiers, , Word Designators, Interactive Use
+@subsection Modifiers
+
+After the optional word designator, you can add a sequence of one or more
+of the following modifiers, each preceded by a @key{:}.
+
+@table @code
+
+@item #
+The entire command line typed so far.  This means the current command,
+not the previous command, so it really isn't a word designator, and doesn't
+belong in this section.
+
+@item h
+Remove a trailing pathname component, leaving only the head.
+
+@item r
+Remove a trailing suffix of the form ".xxx", leaving the basename (root).
+
+@item e
+Remove all but the suffix (end).
+
+@item t
+Remove all leading  pathname  components (before the last slash), leaving
+the tail.
+
+@item p
+Print the new command but do not execute it.  This takes effect
+immediately, so it should be the last specifier on the line.
+
+@end table
+
+@node Programming, , Interactive Use, Top
+@chapter Programming
+
+@bye
diff --git a/readline/inc-history.texinfo b/readline/inc-history.texinfo
new file mode 100755 (executable)
index 0000000..e61c25d
--- /dev/null
@@ -0,0 +1,187 @@
+@ifinfo
+This file documents the GNU History library.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+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.
+@end ifinfo
+
+@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).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and 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 ignore
+
+@node History Top
+@ifinfo
+This file is meant to be an inclusion in the documentation of programs
+that use the history library features.  There is also a standalone
+document, entitled @file{history.texinfo}.
+@end ifinfo
+
+This chapter describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+@menu
+* Introduction to History::    What is the GNU History library for?
+* History Interaction::                What it feels like using History as a user.
+@end menu
+
+@node Introduction to History, History Interaction, History Top, Top
+@appendixsec Introduction to History
+
+Many programs read input from the user a line at a time.  The GNU history
+library is able to keep track of those lines, associate arbitrary data with
+each line, and utilize information from previous lines in making up new
+ones.
+
+The programmer using the History library has available to him functions
+for remembering lines on a history stack, associating arbitrary data
+with a line, removing lines from the stack, searching through the stack
+for a line containing an arbitrary text string, and referencing any line
+on the stack directly.  In addition, a history @dfn{expansion} function
+is available which provides for a consistent user interface across many
+different programs.
+
+The end-user using programs written with the History library has the
+benifit of a consistent user interface, with a set of well-known
+commands for manipulating the text of previous lines and using that text
+in new commands.  The basic history manipulation commands are similar to
+the history substitution used by Csh.
+
+If the programmer desires, he can use the Readline library, which
+includes history manipulation by default, and has the added advantage of
+Emacs style command line editing.
+
+@node History Interaction, , Introduction to History, Top
+@appendixsec History Interaction
+@cindex expansion
+
+The History library provides a history expansion feature that is similar
+to the history expansion in Csh.  The following text describes what
+syntax features are available.
+
+History expansion takes place in two parts.  The first is to determine
+which line from the previous history should be used during substitution.
+The second is to select portions of that line for inclusion into the
+current one.  The line selected from the previous history is called the
+@dfn{event}, and the portions of that line that are acted upon are
+called @dfn{words}.  The line is broken into words in the same fashion
+that the Bash shell does, so that several English (or Unix) words
+surrounded by quotes are considered as one word.
+
+@menu
+* Event Designators::  How to specify which history line to use.  *
+Word Designators::     Specifying which words are of interest.  *
+Modifiers::            Modifying the results of susbstitution.
+@end menu
+
+@node Event Designators, Word Designators, , History Interaction
+@appendixsubsec Event Designators
+@cindex event designators
+
+An event designator is a reference to a command line entry in the
+history list.
+
+@table @asis
+
+@item @code{!}
+Start a history subsititution, except when followed by a space, tab, or
+the end of the line... @kbd{=} or @kbd{(}.
+
+@item @code{!!}
+Refer to the previous command.  This is a synonym for @code{!-1}.
+
+@item @code{!n}
+Refer to command line @var{n}.
+
+@item @code{!-n}
+Refer to the command line @var{n} lines back.
+
+@item @code{!string}
+Refer to the most recent command starting with @var{string}.
+
+@item @code{!?string}[@code{?}]
+Refer to the most recent command containing @var{string}.
+
+@end table
+
+@node Word Designators, Modifiers, Event Designators, History Interaction
+@appendixsubsec Word Designators
+
+A @kbd{:} separates the event specification from the word designator.  It
+can be omitted if the word designator begins with a @kbd{^}, @kbd{$},
+@kbd{*} or @kbd{%}.  Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+
+@table @code
+
+@item 0 (zero)
+The zero'th word.  For many applications, this is the command word.
+
+@item n
+The @var{n}'th word.
+
+@item ^
+The first argument.  that is, word 1.
+
+@item $
+The last argument.
+
+@item %
+The word matched by the most recent @code{?string?} search.
+
+@item x-y
+A range of words; @code{-@var{y}} Abbreviates @code{0-@var{y}}.
+
+@item *
+All of the words, excepting the zero'th.  This is a synonym for @code{1-$}.
+It is not an error to use @kbd{*} if there is just one word in the event.
+The empty string is returned in that case.
+
+@end table
+
+@node Modifiers, , Word Designators, History Interaction
+@appendixsubsec Modifiers
+
+After the optional word designator, you can add a sequence of one or more
+of the following modifiers, each preceded by a @kbd{:}.
+
+@table @code
+
+@item #
+The entire command line typed so far.  This means the current command,
+not the previous command, so it really isn't a word designator, and doesn't
+belong in this section.
+
+@item h
+Remove a trailing pathname component, leaving only the head.
+
+@item r
+Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename.
+
+@item e
+Remove all but the suffix.
+
+@item t
+Remove all leading  pathname  components, leaving the tail.
+
+@item p
+Print the new command but do not execute it.  This takes effect
+immediately, so it should be the last specifier on the line.
+
+@end table
diff --git a/readline/inc-readline.texinfo b/readline/inc-readline.texinfo
new file mode 100755 (executable)
index 0000000..2e6c49e
--- /dev/null
@@ -0,0 +1,490 @@
+@ignore
+
+This file documents the end user interface to the GNU command line
+editing feautres.  It is to be an appendix to manuals for programs which
+use these features.  There is a document entitled "readline.texinfo"
+which contains both end-user and programmer documentation for the GNU
+Readline Library.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Authored by Brian Fox.
+
+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).
+
+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
+GNU Copyright statement is available to the distributee, and 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 ignore
+
+@node Command Line Editing, , , Top
+@appendix Command Line Editing
+
+This appendix describes GNU's command line editing interface.
+
+@menu
+* Introduction and Notation::  Notation used in this appendix.
+* Basic Line Editing::         The minimum set of commands for editing a line.
+* Movement Commands::          Commands for moving the cursor about the line.
+* Cutting and Pasting::                Deletion and copying of text sections.
+* Transposition::              Exchanging two characters or words.
+* Completion::                 Expansion of a partially typed word into
+                                the full text.
+@end menu
+
+@node Introduction and Notation, Basic Line Editing, Command Line Editing, Command Line Editing
+@appendixsec Introduction to Line Editing
+
+In this appendix a the following notation is used to describe
+keystrokes.
+
+The text @kbd{C-k} is read as `Control-K' and describes the character
+produced when the Control key is depressed and the @key{k} key is struck.
+
+The text @kbd{M-k} is read as `Meta-K' and describes the character
+produced when the meta key (if you have one) is depressed, and the @key{k}
+key is struck.  If you do not have a meta key, the identical keystroke
+can be generated by typing @key{ESC} @i{first}, and then typing @key{k}.
+Either process is known as @dfn{metafying} the @key{k} key.
+
+The text @kbd{M-C-k} is read as `Meta-Control-k' and describes the
+character produced by @dfn{metafying} @kbd{C-k}.
+
+In addition, several keys have their own names.  Specifically,
+@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all
+stand for themselves when seen in this text, or in an init file
+(@pxref{Readline Init File}, for more info).
+
+@node Readline Interaction, Readline Init File, Readline Introduction, Readline Top
+@appendixsec Readline Interaction
+@cindex interaction, readline
+
+Often during an interactive session you will type in a long line of
+text, only to notice that the first word on the line is misspelled.  The
+Readline library gives you a set of commands for manipulating the text
+as you type it in, allowing you to just fix your typo, and not forcing
+you to retype the majority of the line.  Using these editing commands,
+you move the cursor to the place that needs correction, and delete or
+insert the text of the corrections.  Then, when you are satisfied with
+the line, you simply press @key{RETURN}.  You do not have to be at the
+end of the line to press @key{RETURN}; the entire line will be accepted
+in any case.
+
+@menu
+* Readline Bare Essentials::   The least you need to know about Readline.
+* Readline Movement Commands:: Moving about the input line.
+* Readline Killing Commands::  How to delete text, and how to get it back!
+* Readline Arguments::         Giving numeric arguments to commands.
+@end menu
+
+@node Readline Bare Essentials, Readline Movement Commands, Readline Interaction, Readline Interaction
+@appendixsubsec Readline Bare Essentials
+
+In order to enter characters into the line, simply type them.  The typed
+character appears where the cursor was, and then the cursor moves one
+space to the right.  If you mistype a character, you can use @key{DEL} to
+back up, and delete the mistyped character.
+
+Sometimes you may miss typing a character that you wanted to type, and
+not notice your error until you have typed several other characters.  In
+that case, you can type @kbd{C-b} to move the cursor to the left, and then
+correct your mistake.  Aftwerwards, you can move the cursor to the right
+with @kbd{C-f}.
+
+When you add text in the middle of a line, you will notice that characters
+to the right of the cursor get `pushed over' to make room for the text
+that you have inserted.  Likewise, when you delete text behind the cursor,
+characters to the right of the cursor get `pulled back' to fill in the
+blank space created by the removal of the text.  A list of the basic bare
+essentials for editing the text of an input line follows.
+
+@table @asis
+@item @kbd{C-b}
+Move back one character.
+@item @kbd{C-f}
+Move forward one character.
+@item @key{DEL}
+Delete the character to the left of the cursor.
+@item @kbd{C-d}
+Delete the character underneath the cursor.
+@item @w{Printing characters}
+Insert itself into the line at the cursor.
+@item @kbd{C-_}
+Undo the last thing that you did.  You can undo all the way back to an
+empty line.
+@end table
+
+@node Readline Movement Commands, Readline Killing Commands, Readline Bare Essentials, Readline Interaction
+@appendixsubsec Readline Movement Commands
+
+
+The above table describes the most basic possible keystrokes that you need
+in order to do editing of the input line.  For your convenience, many
+other commands have been added in addition to @kbd{C-b}, @kbd{C-f},
+@kbd{C-d}, and @key{DEL}.  Here are some commands for moving more rapidly
+about the line.
+
+@table @kbd
+@item C-a
+Move to the start of the line.
+@item C-e
+Move to the end of the line.
+@item M-f
+Move forward a word.
+@item M-b
+Move backward a word.
+@item C-l
+Clear the screen, reprinting the current line at the top.
+@end table
+
+Notice how @kbd{C-f} moves forward a character, while @kbd{M-f} moves
+forward a word.  It is a loose convention that control keystrokes
+operate on characters while meta keystrokes operate on words.
+
+@node Readline Killing Commands, Readline Arguments, Readline Movement Commands, Readline Interaction
+@appendixsubsec Readline Killing Commands
+
+@dfn{Killing} text means to delete the text from the line, but to save
+it away for later use, usually by @dfn{yanking} it back into the line.
+If the description for a command says that it `kills' text, then you can
+be sure that you can get the text back in a different (or the same)
+place later.
+
+Here is the list of commands for killing text.
+
+@table @kbd
+@item C-k
+Kill the text from the current cursor position to the end of the line.
+
+@item M-d
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.
+
+@item M-@key{DEL}
+Kill fromthe cursor the start ofthe previous word, or if between words, to the start of the previous word.
+
+@item C-w
+Kill from the cursor to the previous whitespace.  This is different than
+@kbd{M-@key{DEL}} because the word boundaries differ.
+
+@end table
+
+And, here is how to @dfn{yank} the text back into the line.  Yanking
+is
+
+@table @kbd
+@item C-y
+Yank the most recently killed text back into the buffer at the cursor.
+
+@item M-y
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is @kbd{C-y} or @kbd{M-y}.
+@end table
+
+When you use a kill command, the text is saved in a @dfn{kill-ring}.
+Any number of consecutive kills save all of the killed text together, so
+that when you yank it back, you get it in one clean sweep.  The kill
+ring is not line specific; the text that you killed on a previously
+typed line is available to be yanked back later, when you are typing
+another line.
+
+@node Readline Arguments, , Readline Killing Commands, Readline Interaction
+@appendixsubsec Readline Arguments
+
+You can pass numeric arguments to Readline commands.  Sometimes the
+argument acts as a repeat count, other times it is the @i{sign} of the
+argument that is significant.  If you pass a negative argument to a
+command which normally acts in a forward direction, that command will
+act in a backward direction.  For example, to kill text back to the
+start of the line, you might type @kbd{M--} @kbd{C-k}.
+
+The general way to pass numeric arguments to a command is to type meta
+digits before the command.  If the first `digit' you type is a minus
+sign (@kbd{-}), then the sign of the argument will be negative.  Once
+you have typed one meta digit to get the argument started, you can type
+the remainder of the digits, and then the command.  For example, to give
+the @kbd{C-d} command an argument of 10, you could type @kbd{M-1 0 C-d}.
+
+
+@node Readline Init File, , Readline Interaction, Readline Top
+@appendixsec Readline Init File
+
+Although the Readline library comes with a set of Emacs-like
+keybindings, it is possible that you would like to use a different set
+of keybindings.  You can customize programs that use Readline by putting
+commands in an @dfn{init} file in your home directory.  The name of this
+file is @file{~/.inputrc}.
+
+When a program which uses the Readline library starts up, the
+@file{~/.inputrc} file is read, and the keybindings are set.
+
+@menu
+* Readline Init Syntax::       Syntax for the commands in @file{~/.inputrc}.
+* Readline Vi Mode::           Switching to @code{vi} mode in Readline.
+@end menu
+
+@node Readline Init Syntax, Readline Vi Mode, Readline Init File, Readline Init File
+@appendixsubsec Readline Init Syntax
+
+You can start up with a vi-like editing mode by placing
+
+@example
+@code{set editing-mode vi}
+@end example
+
+in your @file{~/.inputrc} file.
+
+You can have Readline use a single line for display, scrolling the input
+between the two edges of the screen by placing
+
+@example
+@code{set horizontal-scroll-mode On}
+@end example
+
+@noindent
+in your @file{~/.inputrc} file.
+
+The syntax for controlling keybindings in the @file{~/.inputrc} file is
+simple.  First you have to know the @i{name} of the command that you
+want to change.  The following pages contain tables of the command name, the
+default keybinding, and a short description of what the command does.
+
+Once you know the name of the command, simply place the name of the key
+you wish to bind the command to, a colon, and then the name of the
+command on a line in the @file{~/.inputrc} file.  Here is an example:
+
+@example
+# This is a comment line.
+Meta-Rubout:   backward-kill-word
+Control-u:     universal-argument
+@end example
+
+@menu
+* Commands For Moving::                Moving about the line.
+* Commands For History::       Getting at previous lines.
+* Commands For Text::          Commands for changing text.
+* Commands For Killing::       Commands for killing and yanking.
+* Numeric Arguments::          Specifying numeric arguments, repeat counts.
+* Commands For Completion::    Getting Readline to do the typing for you.
+* Miscellaneous Commands::     Other miscillaneous commands.
+@end menu
+
+@node Commands For Moving, Commands For History, Readline Init Syntax, Readline Init Syntax
+@appendixsubsubsec Commands For Moving
+@table @code
+@item beginning-of-line (C-a)
+Move to the start of the current line.
+
+@item end-of-line (C-e)
+Move to the end of the line.
+
+@item forward-char (C-f)
+Move forward a character.
+
+@item backward-char (C-b)
+Move back a character.
+
+@item forward-word (M-f)
+Move forward to the end of the next word.
+
+@item backward-word (M-b)
+Move back to the start of this, or the previous, word.
+
+@item clear-screen (C-l)
+Clear the screen leaving the current line at the top of the screen.
+
+@end table
+
+@node Commands For History, Commands For Text, Commands For Moving, Readline Init Syntax
+@appendixsubsubsec Using the History
+
+@table @code
+@item accept-line (Newline, Return)
+Accept the line regardless of where the cursor is.  If this line is
+non-empty, add it to the history list.  If this line was a history
+line, then restore the history line to its original state.
+
+@item previous-history (C-p)
+Move `up' through the history list.
+
+@item next-history (C-n)
+Move `down' through the history list.
+
+@item beginning-of-history (M-<)
+Move to the first line in the history.
+
+@item end-of-history (M->)
+Move to the end of the input history, i.e., the line you are entering!
+
+@item reverse-search-history (C-r)
+Search backward starting at the current line and moving `up' through
+the history as necessary.  This is an incremental search.
+
+@item forward-search-history (C-s)
+Search forward starting at the current line and moving `down' through
+the the history as neccessary.
+
+@end table
+
+@node Commands For Text, Commands For Killing, Commands For History, Readline Init Syntax
+@appendixsubsubsec Changing Text
+
+@table @code
+@item delete-char (C-d)
+Delete the character under the cursor.  If the cursor is at the
+beginning of the line, and there are no characters in the line, and
+the last character typed was not C-d, then return EOF.
+
+@item backward-delete-char (Rubout)
+Delete the character behind the cursor.  A numeric arg says to kill
+the characters instead of deleting them.
+
+@item quoted-insert (C-q, C-v)
+Add the next character that you type to the line verbatim.  This is
+how to insert things like C-q for example.
+
+@item tab-insert (M-TAB)
+Insert a tab character.
+
+@item self-insert (a, b, A, 1, !, ...)
+Insert yourself.
+
+@item transpose-chars (C-t)
+Drag the character before point forward over the character at point.
+Point moves forward as well.  If point is at the end of the line, then
+transpose the two characters before point.  Negative args don't work.
+
+@item transpose-words (M-t)
+Drag the word behind the cursor past the word in front of the cursor
+moving the cursor over that word as well.
+
+@item upcase-word (M-u)
+Uppercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+
+@item downcase-word (M-l)
+Lowercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+
+@item capitalize-word (M-c)
+Uppercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+
+@end table
+
+@node Commands For Killing, Numeric Arguments, Commands For Text, Readline Init Syntax
+@appendixsubsubsec Killing And Yanking
+
+@table @code
+
+@item kill-line (C-k)
+Kill the text from the current cursor position to the end of the line.
+
+@item backward-kill-line ()
+Kill backward to the beginning of the line.  This is normally unbound.
+
+@item kill-word (M-d)
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.
+
+@item backward-kill-word (M-DEL)
+Kill the word behind the cursor.
+
+@item unix-line-discard (C-u)
+Do what C-u used to do in Unix line input.  We save the killed text on
+the kill-ring, though.
+
+@item unix-word-rubout (C-w)
+Do what C-w used to do in Unix line input.  The killed text is saved
+on the kill-ring.  This is different than backward-kill-word because
+the word boundaries differ.
+
+@item yank (C-y)
+Yank the top of the kill ring into the buffer at point.
+
+@item yank-pop (M-y)
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is yank or yank-pop.
+@end table
+
+@node Numeric Arguments, Commands For Completion, Commands For Killing, Readline Init Syntax
+@appendixsubsubsec Numeric Arguments
+@table @code
+
+@item digit-argument (M-0, M-1, ... M--)
+Add this digit to the argument already accumulating, or start a new
+argument.  M-- starts a negative argument.
+
+@item universal-argument ()
+Do what C-u does in emacs.  By default, this is not bound.
+@end table
+
+
+@node Commands For Completion, Miscellaneous Commands, Numeric Arguments, Readline Init Syntax
+@appendixsubsubsec Letting Readline Type
+
+@table @code
+@item complete (TAB)
+Attempt to do completion on the text before point.  This is
+implementation defined.  Generally, if you are typing a filename
+argument, you can do filename completion; if you are typing a command,
+you can do command completion, if you are typing in a symbol to GDB, you
+can do symbol name completion, if you are typing in a variable to Bash,
+you can do variable name completion...
+
+@item possible-completions (M-?)
+List the possible completions of the text before point.
+@end table
+
+@node Miscellaneous Commands, , Commands For Completion, Readline Init Syntax
+@appendixsubsubsec Other Commands
+@table @code
+
+@item abort (@kbd{C-g})
+Ding!  Stops things.
+
+@item do-uppercase-version (@kbd{M-a}, @kbd{M-b}, @dots)
+Run the command that is bound to your uppercase brother.
+
+@item prefix-meta (@key{ESC})
+Make the next character that you type be metafied.  This is for
+people without a meta key.  @kbd{@key{ESC}-f} is equivalent to @kbd{M-f}.
+
+@item undo (@kbd{C-_})
+Incremental undo, separately remembered for each line.
+
+@item revert-line (@kbd{M-r})
+Undo all changes made to this line.  This is like typing the `undo'
+command enough times to get back to the beginning.
+@end table
+
+@node Readline Vi Mode, , Readline Init Syntax, Readline Init File
+@appendixsubsec Readline Vi Mode
+
+While the Readline library does not have a full set of Vi editing
+functions, it does contain enough to allow simple editing of the line.
+
+In order to switch interactively between Emacs and Vi editing modes, use
+the command M-C-j (toggle-editing-mode).
+
+When you enter a line in Vi mode, you are already placed in `insertion'
+mode, as if you had typed an `i'.  Pressing @key{ESC} switches you into
+`edit' mode, where you can edit the text of the line with the standard
+Vi movement keys, move to previous history lines with `k', and following
+lines with `j', and so forth.
+
+
+
+
diff --git a/readline/keymaps.c b/readline/keymaps.c
new file mode 100644 (file)
index 0000000..b7c79ce
--- /dev/null
@@ -0,0 +1,172 @@
+/* keymaps.c -- Functions and keymaps for the GNU Readline library. */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline 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 1, or (at your option) any
+   later version.
+
+   Readline 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 Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "keymaps.h"
+#include "emacs_keymap.c"
+
+#ifdef VI_MODE
+#include "vi_keymap.c"
+#endif
+
+/* Remove these declarations when we have a complete libgnu.a. */
+#define STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Functions for manipulating Keymaps.           */
+/*                                                                 */
+/* **************************************************************** */
+
+
+/* Return a new, empty keymap.
+   Free it with free() when you are done. */
+Keymap
+rl_make_bare_keymap ()
+{
+  register int i;
+  Keymap keymap = (Keymap)xmalloc (128 * sizeof (KEYMAP_ENTRY));
+
+  for (i = 0; i < 128; i++)
+    {
+      keymap[i].type = ISFUNC;
+      keymap[i].function = (Function *)NULL;
+    }
+
+  for (i = 'A'; i < ('Z' + 1); i++)
+    {
+      keymap[i].type = ISFUNC;
+      keymap[i].function = rl_do_lowercase_version;
+    }
+
+  return (keymap);
+}
+
+/* Return a new keymap which is a copy of MAP. */
+Keymap
+rl_copy_keymap (map)
+     Keymap map;
+{
+  register int i;
+  Keymap temp = rl_make_bare_keymap ();
+
+  for (i = 0; i < 128; i++)
+    {
+      temp[i].type = map[i].type;
+      temp[i].function = map[i].function;
+    }
+  return (temp);
+}
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+   the uppercase Meta characters bound to run their lowercase equivalents,
+   and the Meta digits bound to produce numeric arguments. */
+Keymap
+rl_make_keymap ()
+{
+  extern rl_insert (), rl_rubout (), rl_do_lowercase_version ();
+  extern rl_digit_argument ();
+  register int i;
+  Keymap newmap;
+
+  newmap = rl_make_bare_keymap ();
+
+  /* All printing characters are self-inserting. */
+  for (i = ' '; i < 126; i++)
+    newmap[i].function = rl_insert;
+
+  newmap[TAB].function = rl_insert;
+  newmap[RUBOUT].function = rl_rubout;
+
+  return (newmap);
+}
+
+/* Free the storage associated with MAP. */
+rl_discard_keymap (map)
+     Keymap (map);
+{
+  int i;
+
+  if (!map)
+    return;
+
+  for (i = 0; i < 128; i++)
+    {
+      switch (map[i].type)
+       {
+       case ISFUNC:
+         break;
+
+       case ISKMAP:
+         rl_discard_keymap ((Keymap)map[i].function);
+         break;
+
+       case ISMACR:
+         free ((char *)map[i].function);
+         break;
+       }
+    }
+}
+
+#ifdef STATIC_MALLOC
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
diff --git a/readline/keymaps.h b/readline/keymaps.h
new file mode 100644 (file)
index 0000000..3c577b3
--- /dev/null
@@ -0,0 +1,53 @@
+/* keymaps.h -- Manipulation of readline keymaps. */
+
+#ifndef _KEYMAPS_H_
+#define _KEYMAPS_H_
+
+#include <readline/chardefs.h>
+
+#ifndef __FUNCTION_DEF
+typedef int Function ();
+#define __FUNCTION_DEF
+#endif
+
+/* A keymap contains one entry for each key in the ASCII set.
+   Each entry consists of a type and a pointer.
+   POINTER is the address of a function to run, or the
+   address of a keymap to indirect through.
+   TYPE says which kind of thing POINTER is. */
+typedef struct _keymap_entry {
+  char type;
+  Function *function;
+} KEYMAP_ENTRY;
+
+/* I wanted to make the above structure contain a union of:
+   union { Function *function; struct _keymap_entry *keymap; } value;
+   but this made it impossible for me to create a static array.
+   Maybe I need C lessons. */
+
+typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[128];
+typedef KEYMAP_ENTRY *Keymap;
+
+/* The values that TYPE can have in a keymap entry. */
+#define ISFUNC 0
+#define ISKMAP 1
+#define ISMACR 2
+
+extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
+extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
+
+/* Return a new, empty keymap.
+   Free it with free() when you are done. */
+Keymap rl_make_bare_keymap ();
+
+/* Return a new keymap which is a copy of MAP. */
+Keymap rl_copy_keymap ();
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+   the lowercase Meta characters bound to run their equivalents, and
+   the Meta digits bound to produce numeric arguments. */
+Keymap rl_make_keymap ();
+
+#endif /* _KEYMAPS_H_ */
+
+
diff --git a/readline/readline.c b/readline/readline.c
new file mode 100644 (file)
index 0000000..b05a7c9
--- /dev/null
@@ -0,0 +1,5641 @@
+/* readline.c -- a general facility for reading lines of input
+   with emacs style editing and completion. */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+   This file contains the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   The Library 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 1, or (at your option)
+   any later version.
+
+   The Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Remove these declarations when we have a complete libgnu.a. */
+#define STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <signal.h>
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#if defined (sparc) && defined (sun)
+#include <alloca.h>
+#endif
+#endif
+
+#define NEW_TTY_DRIVER
+#if defined (SYSV) || defined (hpux)  || defined (Xenix)
+#undef NEW_TTY_DRIVER
+#include <termio.h>
+#else
+#include <sgtty.h>
+#endif
+
+#include <errno.h>
+extern int errno;
+
+#include <setjmp.h>
+
+/* These next are for filename completion.  Perhaps this belongs
+   in a different place. */
+#include <sys/stat.h>
+
+#include <pwd.h>
+#ifdef SYSV
+struct passwd *getpwuid (), *getpwent ();
+#endif
+
+#define HACK_TERMCAP_MOTION
+
+#ifndef SYSV
+#include <sys/dir.h>
+#else  /* SYSV */
+#if defined (Xenix)
+#include <sys/ndir.h>
+#else
+#ifdef hpux
+#include <ndir.h>
+#else
+#include <dirent.h>
+#define direct dirent
+#define d_namlen d_reclen
+#endif  /* hpux */
+#endif  /* xenix */
+#endif  /* SYSV */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#ifndef digit
+#define digit(c)  ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef isletter
+#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+#ifndef member
+char *index ();
+#define member(c, s) ((c) ? index ((s), (c)) : 0)
+#endif
+
+#ifndef isident
+#define isident(c) ((isletter(c) || digit(c) || c == '_'))
+#endif
+
+#ifndef exchange
+#define exchange(x, y) {int temp = x; x = y; y = temp;}
+#endif
+
+static update_line ();
+static void output_character_function ();
+static delete_chars ();
+static delete_chars ();
+static insert_some_chars ();
+
+#ifdef VOID_SIGHANDLER
+#define sighandler void
+#else
+#define sighandler int
+#endif
+
+/* This typedef is equivalant to the one for Function; it allows us
+   to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
+typedef sighandler SigHandler ();
+
+/* If on, then readline handles signals in a way that doesn't screw. */
+#define HANDLE_SIGNALS
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Line editing input utility                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* A pointer to the keymap that is currently in use.
+   By default, it is the standard emacs keymap. */
+Keymap keymap = emacs_standard_keymap;
+
+#define vi_mode 0
+#define emacs_mode 1
+
+/* The current style of editing. */
+int rl_editing_mode = emacs_mode;
+
+/* Non-zero if the previous command was a kill command. */
+static int last_command_was_kill = 0;
+
+/* The current value of the numeric argument specified by the user. */
+int rl_numeric_arg = 1;
+
+/* Non-zero if an argument was typed. */
+int rl_explicit_arg = 0;
+
+/* Temporary value used while generating the argument. */
+static int arg_sign = 1;
+
+/* Non-zero means we have been called at least once before. */
+static int rl_initialized = 0;
+
+/* If non-zero, this program is running in an EMACS buffer. */
+static char *running_in_emacs = (char *)NULL;
+
+/* The current offset in the current input line. */
+int rl_point;
+
+/* Mark in the current input line. */
+int rl_mark;
+
+/* Length of the current input line. */
+int rl_end;
+
+/* Make this non-zero to return the current input_line. */
+int rl_done;
+
+/* The last function executed by readline. */
+Function *rl_last_func = (Function *)NULL;
+
+/* Top level environment for readline_internal (). */
+static jmp_buf readline_top_level;
+
+/* The streams we interact with. */
+static FILE *in_stream, *out_stream;
+
+/* The names of the streams that we do input and output to. */
+FILE *rl_instream = stdin, *rl_outstream = stdout;
+
+/* Non-zero means echo characters as they are read. */
+int readline_echoing_p = 1;
+
+/* Current prompt. */
+char *rl_prompt;
+
+/* The number of characters read in order to type this complete command. */
+int rl_key_sequence_length = 0;
+
+/* If non-zero, then this is the address of a function to call just
+   before readline_internal () prints the first prompt. */
+Function *rl_startup_hook = (Function *)NULL;
+
+/* If non-zero, then this is the address of a function to call when
+   completing on a directory name.  The function is called with
+   the address of a string (the current directory name) as an arg. */
+Function *rl_symbolic_link_hook = (Function *)NULL;
+
+/* What we use internally.  You should always refer to RL_LINE_BUFFER. */
+static char *the_line;
+
+/* The character that can generate an EOF.  Really read from
+   the terminal driver... just defaulted here. */
+static int eof_char = CTRL ('D');
+
+/* Non-zero makes this the next keystroke to read. */
+int rl_pending_input = 0;
+
+/* Pointer to a useful terminal name. */
+char *rl_terminal_name = (char *)NULL;
+
+/* Line buffer and maintenence. */
+char *rl_line_buffer = (char *)NULL;
+static int rl_line_buffer_len = 0;
+#define DEFAULT_BUFFER_SIZE 256
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     `Forward' declarations                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means do not parse any lines other than comments and
+   parser directives. */
+static unsigned char parsing_conditionalized_out = 0;
+
+/* Caseless strcmp (). */
+static int stricmp (), strnicmp ();
+
+/* Non-zero means to save keys that we dispatch on in a kbd macro. */
+static int defining_kbd_macro = 0;
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Top Level Functions                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means
+   none.  A return value of NULL means that EOF was encountered. */
+char *
+readline (prompt)
+     char *prompt;
+{
+  static rl_prep_terminal (), rl_deprep_terminal ();
+  char *readline_internal ();
+  char *value;
+
+  rl_prompt = prompt;
+
+  /* If we are at EOF return a NULL string. */
+  if (rl_pending_input == EOF)
+    {
+      rl_pending_input = 0;
+      return ((char *)NULL);
+    }
+
+  rl_initialize ();
+  rl_prep_terminal ();
+
+#ifdef HANDLE_SIGNALS
+  rl_set_signals ();
+#endif
+
+  value = readline_internal ();
+  rl_deprep_terminal ();
+
+#ifdef HANDLE_SIGNALS
+  rl_clear_signals ();
+#endif
+
+  return (value);
+}
+
+/* Read a line of input from the global rl_instream, doing output on
+   the global rl_outstream.
+   If rl_prompt is non-null, then that is our prompt. */
+char *
+readline_internal ()
+{
+  int lastc, c, eof_found;
+
+  in_stream = rl_instream; out_stream = rl_outstream;
+  lastc = eof_found = 0;
+
+  if (rl_startup_hook)
+    (*rl_startup_hook) ();
+
+  if (!readline_echoing_p)
+    {
+      if (rl_prompt)
+       {
+         fprintf (out_stream, "%s", rl_prompt);
+         fflush (out_stream);
+       }
+    }
+  else
+    {
+      rl_on_new_line ();
+      rl_redisplay ();
+#ifdef VI_MODE
+      if (rl_editing_mode == vi_mode)
+       rl_vi_insertion_mode ();
+#endif /* VI_MODE */
+    }
+
+  while (!rl_done)
+    {
+      int lk = last_command_was_kill;
+      int code = setjmp (readline_top_level);
+
+      if (code)
+       rl_redisplay ();
+
+      if (!rl_pending_input)
+       {
+         /* Then initialize the argument and number of keys read. */
+         rl_init_argument ();
+         rl_key_sequence_length = 0;
+       }
+
+      c = rl_read_key ();
+
+      /* EOF typed to a non-blank line is a <NL>. */
+      if (c == EOF && rl_end)
+       c = NEWLINE;
+
+      /* The character eof_char typed to blank line, and not as the
+        previous character is interpreted as EOF. */
+      if (((c == eof_char && lastc != c) || c == EOF) && !rl_end)
+       {
+         eof_found = 1;
+         break;
+       }
+
+      lastc = c;
+      rl_dispatch (c, keymap);
+
+      /* If there was no change in last_command_was_kill, then no kill
+        has taken place.  Note that if input is pending we are reading
+        a prefix command, so nothing has changed yet. */
+      if (!rl_pending_input)
+       {
+         if (lk == last_command_was_kill)
+           last_command_was_kill = 0;
+       }
+
+#ifdef VI_MODE
+      /* In vi mode, when you exit insert mode, the cursor moves back
+        over the previous character.  We explicitly check for that here. */
+      if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap)
+       rl_vi_check ();
+#endif
+
+      if (!rl_done)
+       rl_redisplay ();
+    }
+
+  /* Restore the original of this history line, iff the line that we
+     are editing was originally in the history, AND the line has changed. */
+  {
+    HIST_ENTRY *entry = current_history ();
+
+    if (entry && rl_undo_list)
+      {
+       char *temp = savestring (the_line);
+       rl_revert_line ();
+       entry = replace_history_entry (where_history (), the_line,
+                                      (HIST_ENTRY *)NULL);
+       free_history_entry (entry);
+
+       strcpy (the_line, temp);
+       free (temp);
+      }
+  }
+
+  /* At any rate, it is highly likely that this line has an undo list.  Get
+     rid of it now. */
+  if (rl_undo_list)
+    free_undo_list ();
+
+  if (eof_found)
+    return (char *)NULL;
+  else
+    return (savestring (the_line));
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                        Signal Handling                          */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef SIGWINCH
+static SigHandler *old_sigwinch = (SigHandler *)NULL;
+
+static sighandler
+rl_handle_sigwinch (sig, code, scp)
+     int sig, code;
+     struct sigcontext *scp;
+{
+  char *term = rl_terminal_name, *getenv ();
+
+  if (readline_echoing_p)
+    {
+      if (!term)
+       term = getenv ("TERM");
+      if (!term)
+       term = "dumb";
+      rl_reset_terminal (term);
+#ifdef NEVER
+      crlf ();
+      rl_forced_update_display ();
+#endif
+    }
+
+  if (old_sigwinch &&
+      old_sigwinch != (SigHandler *)SIG_IGN &&
+      old_sigwinch != (SigHandler *)SIG_DFL)
+    (*old_sigwinch)(sig, code, scp);
+}
+#endif  /* SIGWINCH */
+
+#ifdef HANDLE_SIGNALS
+/* Interrupt handling. */
+static SigHandler *old_int  = (SigHandler *)NULL,
+                 *old_tstp = (SigHandler *)NULL,
+                 *old_ttou = (SigHandler *)NULL,
+                 *old_ttin = (SigHandler *)NULL,
+                 *old_cont = (SigHandler *)NULL;
+
+/* Handle an interrupt character. */
+static sighandler
+rl_signal_handler (sig, code, scp)
+     int sig, code;
+     struct sigcontext *scp;
+{
+  static rl_prep_terminal (), rl_deprep_terminal ();
+
+  switch (sig)
+    {
+    case SIGINT:
+      free_undo_list ();
+      rl_clear_message ();
+      rl_init_argument ();
+
+#ifdef SIGTSTP
+    case SIGTSTP:
+    case SIGTTOU:
+    case SIGTTIN:
+#endif
+
+      rl_clean_up_for_exit ();
+      rl_deprep_terminal ();
+      rl_clear_signals ();
+      rl_pending_input = 0;
+
+      kill (getpid (), sig);
+      sigsetmask (0);
+
+      rl_prep_terminal ();
+      rl_set_signals ();
+    }
+}
+
+rl_set_signals ()
+{
+  old_int = (SigHandler *)signal (SIGINT, rl_signal_handler);
+  if (old_int == (SigHandler *)SIG_IGN)
+    signal (SIGINT, SIG_IGN);
+
+#ifdef SIGTSTP
+  old_tstp = (SigHandler *)signal (SIGTSTP, rl_signal_handler);
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    signal (SIGTSTP, SIG_IGN);
+#endif
+#ifdef SIGTTOU
+  old_ttou = (SigHandler *)signal (SIGTTOU, rl_signal_handler);
+  old_ttin = (SigHandler *)signal (SIGTTIN, rl_signal_handler);
+
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    {
+      signal (SIGTTOU, SIG_IGN);
+      signal (SIGTTIN, SIG_IGN);
+    }
+#endif
+
+#ifdef SIGWINCH
+  old_sigwinch = (SigHandler *)signal (SIGWINCH, rl_handle_sigwinch);
+#endif
+}
+
+rl_clear_signals ()
+{
+  signal (SIGINT, old_int);
+
+#ifdef SIGTSTP
+  signal (SIGTSTP, old_tstp);
+#endif
+
+#ifdef SIGTTOU
+  signal (SIGTTOU, old_ttou);
+  signal (SIGTTIN, old_ttin);
+#endif
+
+#ifdef SIGWINCH
+      signal (SIGWINCH, old_sigwinch);
+#endif
+}
+#endif  /* HANDLE_SIGNALS */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Input Buffering                   */
+/*                                                                 */
+/* **************************************************************** */
+
+/* If the terminal was in xoff state when we got to it, then xon_char
+   contains the character that is supposed to start it again. */
+static int xon_char, xoff_state;
+static int pop_index = 0, push_index = 0, ibuffer_len = 511;
+static unsigned char ibuffer[512];
+
+/* Non-null means it is a pointer to a function to run while waiting for
+   character input. */
+Function *rl_event_hook = (Function *)NULL;
+
+#define any_typein (push_index != pop_index)
+
+/* Add KEY to the buffer of characters to be read. */
+rl_stuff_char (key)
+     int key;
+{
+  if (key == EOF)
+    {
+      key = NEWLINE;
+      rl_pending_input = EOF;
+    }
+  ibuffer[push_index++] = key;
+  if (push_index >= ibuffer_len)
+    push_index = 0;
+}
+
+/* Return the amount of space available in the
+   buffer for stuffing characters. */
+int
+ibuffer_space ()
+{
+  if (pop_index > push_index)
+    return (pop_index - push_index);
+  else
+    return (ibuffer_len - (push_index - pop_index));
+}
+
+/* Get a key from the buffer of characters to be read.
+   Return the key in KEY.
+   Result is KEY if there was a key, or 0 if there wasn't. */
+int
+rl_get_char (key)
+     int *key;
+{
+  if (push_index == pop_index)
+    return (0);
+
+  *key = ibuffer[pop_index++];
+
+  if (pop_index >= ibuffer_len)
+    pop_index = 0;
+
+  return (1);
+}
+
+/* Stuff KEY into the *front* of the input buffer.
+   Returns non-zero if successful, zero if there is
+   no space left in the buffer. */
+int
+rl_unget_char (key)
+     int key;
+{
+  if (ibuffer_space ())
+    {
+      pop_index--;
+      if (pop_index < 0)
+       pop_index = ibuffer_len - 1;
+      ibuffer[pop_index] = key;
+      return (1);
+    }
+  return (0);
+}
+
+/* If a character is available to be read, then read it
+   and stuff it into IBUFFER.  Otherwise, just return. */
+rl_gather_tyi ()
+{
+  int tty = fileno (in_stream);
+  register int tem, result = -1;
+  long chars_avail;
+  char input;
+
+#ifdef FIONREAD
+  result = ioctl (tty, FIONREAD, &chars_avail);
+#endif
+
+  if (result == -1)
+    {
+      fcntl (tty, F_SETFL, O_NDELAY);
+      chars_avail = read (tty, &input, 1);
+      fcntl (tty, F_SETFL, 0);
+      if (chars_avail == -1 && errno == EAGAIN)
+       return;
+    }
+
+  tem = ibuffer_space ();
+
+  if (chars_avail > tem)
+    chars_avail = tem;
+
+  /* One cannot read all of the available input.  I can only read a single
+     character at a time, or else programs which require input can be
+     thwarted.  If the buffer is larger than one character, I lose.
+     Damn! */
+  if (tem < ibuffer_len)
+    chars_avail = 0;
+
+  if (result != -1)
+    {
+      while (chars_avail--)
+       rl_stuff_char (rl_getc (in_stream));
+    }
+  else
+    {
+      if (chars_avail)
+       rl_stuff_char (input);
+    }
+}
+
+/* Read a key, including pending input. */
+int
+rl_read_key ()
+{
+  int c;
+
+  rl_key_sequence_length++;
+
+  if (rl_pending_input)
+    {
+      c = rl_pending_input;
+      rl_pending_input = 0;
+    }
+  else
+    {
+      static int next_macro_key ();
+
+      /* If input is coming from a macro, then use that. */
+      if (c = next_macro_key ())
+       return (c);
+
+      /* If the user has an event function, then call it periodically. */
+      if (rl_event_hook)
+       {
+         while (rl_event_hook && !rl_get_char (&c))
+           {
+             (*rl_event_hook) ();
+             rl_gather_tyi ();
+           }
+       }
+      else
+       {
+         if (!rl_get_char (&c))
+           c = rl_getc (in_stream);
+       }
+    }
+
+#ifdef NEVER  /* This breaks supdup to 4.0.3c machines. */
+#ifdef TIOCSTART
+  /* Ugh.  But I can't think of a better way. */
+  if (xoff_state && c == xon_char)
+    {
+      ioctl (fileno (in_stream), TIOCSTART, 0);
+      xoff_state = 0;
+      return (rl_read_key ());
+    }
+#endif /* TIOCSTART */
+#endif
+
+  return (c);
+}
+
+/* I'm beginning to hate the declaration rules for various compilers. */
+static void add_macro_char ();
+
+/* Do the command associated with KEY in MAP.
+   If the associated command is really a keymap, then read
+   another key, and dispatch into that map. */
+rl_dispatch (key, map)
+     register int key;
+     Keymap map;
+{
+
+  if (defining_kbd_macro)
+    add_macro_char (key);
+
+  if (key > 127 && key < 256)
+    {
+      if (map[ESC].type == ISKMAP)
+       {
+         map = (Keymap)map[ESC].function;
+         key -= 128;
+         rl_dispatch (key, map);
+       }
+      else
+       ding ();
+      return;
+    }
+
+  switch (map[key].type)
+    {
+    case ISFUNC:
+      {
+       Function *func = map[key].function;
+
+       if (func != (Function *)NULL)
+         {
+           /* Special case rl_do_lowercase_version (). */
+           if (func == rl_do_lowercase_version)
+             {
+               rl_dispatch (to_lower (key), map);
+               return;
+             }
+
+           (*map[key].function)(rl_numeric_arg * arg_sign, key);
+         }
+       else
+         {
+           ding ();
+           return;
+         }
+      }
+      break;
+
+    case ISKMAP:
+      if (map[key].function != (Function *)NULL)
+       {
+         int newkey;
+
+         rl_key_sequence_length++;
+         newkey = rl_read_key ();
+         rl_dispatch (newkey, (Keymap)map[key].function);
+       }
+      else
+       {
+         ding ();
+         return;
+       }
+      break;
+
+    case ISMACR:
+      if (map[key].function != (Function *)NULL)
+       {
+         static with_macro_input ();
+         char *macro = savestring ((char *)map[key].function);
+
+         with_macro_input (macro);
+         return;
+       }
+      break;
+    }
+
+  /* If we have input pending, then the last command was a prefix
+     command.  Don't change the state of rl_last_func. */
+  if (!rl_pending_input)
+    rl_last_func = map[key].function;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Hacking Keyboard Macros                     */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The currently executing macro string.  If this is non-zero,
+   then it is a malloc ()'ed string where input is coming from. */
+static char *executing_macro = (char *)NULL;
+
+/* The offset in the above string to the next character to be read. */
+static int executing_macro_index = 0;
+
+/* The current macro string being built.  Characters get stuffed
+   in here by add_macro_char (). */
+static char *current_macro = (char *)NULL;
+
+/* The size of the buffer allocated to current_macro. */
+static int current_macro_size = 0;
+
+/* The index at which characters are being added to current_macro. */
+static int current_macro_index = 0;
+
+/* A structure used to save nested macro strings.
+   It is a linked list of string/index for each saved macro. */
+struct saved_macro {
+  struct saved_macro *next;
+  char *string;
+  int index;
+};
+
+/* The list of saved macros. */
+struct saved_macro *macro_list = (struct saved_macro *)NULL;
+
+/* Forward declarations of static functions.  Thank you C. */
+static void push_executing_macro (), pop_executing_macro ();
+
+/* This one has to be declared earlier in the file. */
+/* static void add_macro_char (); */
+
+/* Set up to read subsequent input from STRING.
+   STRING is free ()'ed when we are done with it. */
+static
+with_macro_input (string)
+     char *string;
+{
+  push_executing_macro ();
+  executing_macro = string;
+  executing_macro_index = 0;
+}
+
+/* Return the next character available from a macro, or 0 if
+   there are no macro characters. */
+static int
+next_macro_key ()
+{
+  if (!executing_macro)
+    return (0);
+
+  if (!executing_macro[executing_macro_index])
+    {
+      pop_executing_macro ();
+      return (next_macro_key ());
+    }
+
+  return (executing_macro[executing_macro_index++]);
+}
+
+/* Save the currently executing macro on a stack of saved macros. */
+static void
+push_executing_macro ()
+{
+  struct saved_macro *saver;
+
+  saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
+  saver->next = macro_list;
+  saver->index = executing_macro_index;
+  saver->string = executing_macro;
+
+  macro_list = saver;
+}
+
+/* Discard the current macro, replacing it with the one
+   on the top of the stack of saved macros. */
+static void
+pop_executing_macro ()
+{
+  if (executing_macro)
+    free (executing_macro);
+
+  executing_macro = (char *)NULL;
+  executing_macro_index = 0;
+
+  if (macro_list)
+    {
+      struct saved_macro *disposer = macro_list;
+      executing_macro = macro_list->string;
+      executing_macro_index = macro_list->index;
+      macro_list = macro_list->next;
+      free (disposer);
+    }
+}
+
+/* Add a character to the macro being built. */
+static void
+add_macro_char (c)
+     int c;
+{
+  if (current_macro_index + 1 >= current_macro_size)
+    {
+      if (!current_macro)
+       current_macro = (char *)xmalloc (current_macro_size = 25);
+      else
+       current_macro =
+         (char *)xrealloc (current_macro, current_macro_size += 25);
+    }
+
+  current_macro[current_macro_index++] = c;
+  current_macro[current_macro_index] = '\0';
+}
+
+/* Begin defining a keyboard macro.
+   Keystrokes are recorded as they are executed.
+   End the definition with rl_end_kbd_macro ().
+   If a numeric argument was explicitly typed, then append this
+   definition to the end of the existing macro, and start by
+   re-executing the existing macro. */
+rl_start_kbd_macro (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  if (defining_kbd_macro)
+    rl_abort ();
+
+  if (rl_explicit_arg)
+    {
+      if (current_macro)
+       with_macro_input (savestring (current_macro));
+    }
+  else
+    current_macro_index = 0;
+
+  defining_kbd_macro = 1;
+}
+
+/* Stop defining a keyboard macro.
+   A numeric argument says to execute the macro right now,
+   that many times, counting the definition as the first time. */
+rl_end_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (!defining_kbd_macro)
+    rl_abort ();
+
+  current_macro_index -= (rl_key_sequence_length - 1);
+  current_macro[current_macro_index] = '\0';
+
+  defining_kbd_macro = 0;
+
+  rl_call_last_kbd_macro (--count, 0);
+}
+
+/* Execute the most recently defined keyboard macro.
+   COUNT says how many times to execute it. */
+rl_call_last_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (!current_macro)
+    rl_abort ();
+
+  while (count--)
+    with_macro_input (savestring (current_macro));
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Initializations                             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Initliaze readline (and terminal if not already). */
+rl_initialize ()
+{
+  extern char *rl_display_prompt;
+
+  /* If we have never been called before, initialize the
+     terminal and data structures. */
+  if (!rl_initialized)
+    {
+      readline_initialize_everything ();
+      rl_initialized++;
+    }
+
+  /* Initalize the current line information. */
+  rl_point = rl_end = 0;
+  the_line = rl_line_buffer;
+  the_line[0] = 0;
+
+  /* We aren't done yet.  We haven't even gotten started yet! */
+  rl_done = 0;
+
+  /* Tell the history routines what is going on. */
+  start_using_history ();
+
+  /* Make the display buffer match the state of the line. */
+  {
+    extern char *rl_display_prompt;
+    extern int forced_display;
+
+    rl_on_new_line ();
+
+    rl_display_prompt = rl_prompt ? rl_prompt : "";
+    forced_display = 1;
+  }
+
+  /* No such function typed yet. */
+  rl_last_func = (Function *)NULL;
+
+  /* Parsing of key-bindings begins in an enabled state. */
+  parsing_conditionalized_out = 0;
+}
+
+/* Initialize the entire state of the world. */
+readline_initialize_everything ()
+{
+  /* Find out if we are running in Emacs. */
+  running_in_emacs = (char *)getenv ("EMACS");
+
+  /* Allocate data structures. */
+  if (!rl_line_buffer)
+    rl_line_buffer =
+      (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
+
+  /* Initialize the terminal interface. */
+  init_terminal_io ((char *)NULL);
+
+  /* Bind tty characters to readline functions. */
+  readline_default_bindings ();
+
+  /* Initialize the function names. */
+  rl_initialize_funmap ();
+
+  /* Read in the init file. */
+  rl_read_init_file ((char *)NULL);
+
+  /* If the completion parser's default word break characters haven't
+     been set yet, then do so now. */
+  {
+    extern char *rl_completer_word_break_characters;
+    extern char *rl_basic_word_break_characters;
+
+    if (rl_completer_word_break_characters == (char *)NULL)
+      rl_completer_word_break_characters = rl_basic_word_break_characters;
+  }
+}
+
+/* If this system allows us to look at the values of the regular
+   input editing characters, then bind them to their readline
+   equivalents. */
+readline_default_bindings ()
+{
+
+#ifdef NEW_TTY_DRIVER
+  struct sgttyb ttybuff;
+  int tty = fileno (rl_instream);
+
+  if (ioctl (tty, TIOCGETP, &ttybuff) != -1)
+    {
+      int erase = ttybuff.sg_erase, kill = ttybuff.sg_kill;
+
+      if (erase != -1 && keymap[erase].type == ISFUNC)
+       keymap[erase].function = rl_rubout;
+
+      if (kill != -1 && keymap[kill].type == ISFUNC)
+       keymap[kill].function = rl_unix_line_discard;
+    }
+
+#ifdef TIOCGLTC
+  {
+    struct ltchars lt;
+
+    if (ioctl (tty, TIOCGLTC, &lt) != -1)
+      {
+       int erase = lt.t_werasc, nextc = lt.t_lnextc;
+
+       if (erase != -1 && keymap[erase].type == ISFUNC)
+         keymap[erase].function = rl_unix_word_rubout;
+
+       if (nextc != -1 && keymap[nextc].type == ISFUNC)
+         keymap[nextc].function = rl_quoted_insert;
+      }
+  }
+#endif /* TIOCGLTC */
+#else /* not NEW_TTY_DRIVER */
+  struct termio ttybuff;
+  int tty = fileno (rl_instream);
+
+  if (ioctl (tty, TCGETA, &ttybuff) != -1)
+    {
+      int erase = ttybuff.c_cc[VERASE];
+      int kill = ttybuff.c_cc[VKILL];
+
+      if (erase != -1 && keymap[(unsigned char)erase].type == ISFUNC)
+       keymap[(unsigned char)erase].function = rl_rubout;
+
+      if (kill != -1 && keymap[(unsigned char)kill].type == ISFUNC)
+       keymap[(unsigned char)kill].function = rl_unix_line_discard;
+    }
+#endif /* NEW_TTY_DRIVER */
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Numeric Arguments                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Handle C-u style numeric args, as well as M--, and M-digits. */
+
+/* Add the current digit to the argument in progress. */
+rl_digit_argument (ignore, key)
+     int ignore, key;
+{
+  rl_pending_input = key;
+  rl_digit_loop ();
+}
+
+/* What to do when you abort reading an argument. */
+rl_discard_argument ()
+{
+  ding ();
+  rl_clear_message ();
+  rl_init_argument ();
+}
+
+/* Create a default argument. */
+rl_init_argument ()
+{
+  rl_numeric_arg = arg_sign = 1;
+  rl_explicit_arg = 0;
+}
+
+/* C-u, universal argument.  Multiply the current argument by 4.
+   Read a key.  If the key has nothing to do with arguments, then
+   dispatch on it.  If the key is the abort character then abort. */
+rl_universal_argument ()
+{
+  rl_numeric_arg *= 4;
+  rl_digit_loop ();
+}
+
+rl_digit_loop ()
+{
+  int key, c;
+  while (1)
+    {
+      rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg);
+      key = c = rl_read_key ();
+
+      if (keymap[c].type == ISFUNC &&
+         keymap[c].function == rl_universal_argument)
+       {
+         rl_numeric_arg *= 4;
+         continue;
+       }
+      c = UNMETA (c);
+      if (numeric (c))
+       {
+         if (rl_explicit_arg)
+           rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
+         else
+           rl_numeric_arg = (c - '0');
+         rl_explicit_arg = 1;
+       }
+      else
+       {
+         if (c == '-' && !rl_explicit_arg)
+           {
+             rl_numeric_arg = 1;
+             arg_sign = -1;
+           }
+         else
+           {
+             rl_clear_message ();
+             rl_dispatch (key, keymap);
+             return;
+           }
+       }
+    }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Display stuff                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is the stuff that is hard for me.  I never seem to write good
+   display routines in C.  Let's see how I do this time. */
+
+/* (PWP) Well... Good for a simple line updater, but totally ignores
+   the problems of input lines longer than the screen width.
+
+   update_line and the code that calls it makes a multiple line,
+   automatically wrapping line update.  Carefull attention needs
+   to be paid to the vertical position variables.
+
+   handling of terminals with autowrap on (incl. DEC braindamage)
+   could be improved a bit.  Right now I just cheat and decrement
+   screenwidth by one. */
+
+/* Keep two buffers; one which reflects the current contents of the
+   screen, and the other to draw what we think the new contents should
+   be.  Then compare the buffers, and make whatever changes to the
+   screen itself that we should.  Finally, make the buffer that we
+   just drew into be the one which reflects the current contents of the
+   screen, and place the cursor where it belongs.
+
+   Commands that want to can fix the display themselves, and then let
+   this function know that the display has been fixed by setting the
+   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
+
+/* Termcap variables: */
+extern char *term_up, *term_dc, *term_cr;
+extern int screenheight, screenwidth, terminal_can_insert;
+
+/* What YOU turn on when you have handled all redisplay yourself. */
+int rl_display_fixed = 0;
+
+/* The visible cursor position.  If you print some text, adjust this. */
+int last_c_pos = 0;
+int last_v_pos = 0;
+
+/* The last left edge of text that was displayed.  This is used when
+   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
+static int last_lmargin = 0;
+
+/* The line display buffers.  One is the line currently displayed on
+   the screen.  The other is the line about to be displayed. */
+static char *visible_line = (char *)NULL;
+static char *invisible_line = (char *)NULL;
+
+/* Number of lines currently on screen minus 1. */
+int vis_botlin = 0;
+
+/* A buffer for `modeline' messages. */
+char msg_buf[128];
+
+/* Non-zero forces the redisplay even if we thought it was unnecessary. */
+int forced_display = 0;
+
+/* The stuff that gets printed out before the actual text of the line.
+   This is usually pointing to rl_prompt. */
+char *rl_display_prompt = (char *)NULL;
+
+/* Default and initial buffer size.  Can grow. */
+static int line_size = 1024;
+
+/* Non-zero means to always use horizontal scrolling in line display. */
+static int horizontal_scroll_mode = 0;
+
+/* Non-zero means to display an asterisk at the starts of history lines
+   which have been modified. */
+static int mark_modified_lines = 0;
+
+/* I really disagree with this, but my boss (among others) insists that we
+   support compilers that don't work.  I don't think we are gaining by doing
+   so; what is the advantage in producing better code if we can't use it? */
+/* The following two declarations belong inside the
+   function block, not here. */
+static void move_cursor_relative ();
+static void output_some_chars ();
+static void output_character_function ();
+static int compare_strings ();
+
+/* Basic redisplay algorithm. */
+rl_redisplay ()
+{
+  register int in, out, c, linenum;
+  register char *line = invisible_line;
+  int c_pos = 0;
+  int inv_botlin = 0;          /* Number of lines in newly drawn buffer. */
+
+  extern int readline_echoing_p;
+
+  if (!readline_echoing_p)
+    return;
+
+  if (!rl_display_prompt)
+    rl_display_prompt = "";
+
+  if (!invisible_line)
+    {
+      visible_line = (char *)xmalloc (line_size);
+      invisible_line = (char *)xmalloc (line_size);
+      line = invisible_line;
+      for (in = 0; in < line_size; in++)
+       {
+         visible_line[in] = 0;
+         invisible_line[in] = 1;
+       }
+      rl_on_new_line ();
+    }
+
+  /* Draw the line into the buffer. */
+  c_pos = -1;
+
+  /* Mark the line as modified or not.  We only do this for history
+     lines. */
+  out = 0;
+  if (mark_modified_lines && current_history () && rl_undo_list)
+    {
+      line[out++] = '*';
+      line[out] = '\0';
+    }
+
+  /* If someone thought that the redisplay was handled, but the currently
+     visible line has a different modification state than the one about
+     to become visible, then correct the callers misconception. */
+  if (visible_line[0] != invisible_line[0])
+    rl_display_fixed = 0;
+
+  strncpy (line + out,  rl_display_prompt, strlen (rl_display_prompt));
+  out += strlen (rl_display_prompt);
+  line[out] = '\0';
+
+  for (in = 0; in < rl_end; in++)
+    {
+      c = the_line[in];
+
+      if (out + 1 >= line_size)
+       {
+         line_size *= 2;
+         visible_line = (char *)xrealloc (visible_line, line_size);
+         invisible_line = (char *)xrealloc (invisible_line, line_size);
+         line = invisible_line;
+       }
+
+      if (in == rl_point)
+       c_pos = out;
+
+      if (c > 127)
+       {
+         line[out++] = 'M';
+         line[out++] = '-';
+         line[out++] = c - 128;
+       }
+#define DISPLAY_TABS
+#ifdef DISPLAY_TABS
+      else if (c == '\t')
+       {
+         register int newout = (out | (int)7) + 1;
+         while (out < newout)
+           line[out++] = ' ';
+       }
+#endif
+      else if (c < 32)
+       {
+         line[out++] = 'C';
+         line[out++] = '-';
+         line[out++] = c + 64;
+       }
+      else
+       line[out++] = c;
+    }
+  line[out] = '\0';
+  if (c_pos < 0)
+    c_pos = out;
+
+  /* PWP: now is when things get a bit hairy.  The visible and invisible
+     line buffers are really multiple lines, which would wrap every
+     (screenwidth - 1) characters.  Go through each in turn, finding
+     the changed region and updating it.  The line order is top to bottom. */
+
+  /* If we can move the cursor up and down, then use multiple lines,
+     otherwise, let long lines display in a single terminal line, and
+     horizontally scroll it. */
+
+  if (!horizontal_scroll_mode && term_up && *term_up)
+    {
+      int total_screen_chars = (screenwidth * screenheight);
+
+      if (!rl_display_fixed || forced_display)
+       {
+         forced_display = 0;
+
+         /* If we have more than a screenful of material to display, then
+            only display a screenful.  We should display the last screen,
+            not the first.  I'll fix this in a minute. */
+         if (out >= total_screen_chars)
+           out = total_screen_chars - 1;
+
+         /* Number of screen lines to display. */
+         inv_botlin = out / screenwidth;
+
+         /* For each line in the buffer, do the updating display. */
+         for (linenum = 0; linenum <= inv_botlin; linenum++)
+           update_line (linenum > vis_botlin ? ""
+                        : &visible_line[linenum * screenwidth],
+                        &invisible_line[linenum * screenwidth],
+                        linenum);
+
+         /* We may have deleted some lines.  If so, clear the left over
+            blank ones at the bottom out. */
+         if (vis_botlin > inv_botlin)
+           {
+             char *tt;
+             for (; linenum <= vis_botlin; linenum++)
+               {
+                 tt = &visible_line[linenum * screenwidth];
+                 move_vert (linenum);
+                 move_cursor_relative (0, tt);
+                 clear_to_eol ((linenum == vis_botlin)?
+                               strlen (tt) : screenwidth);
+               }
+           }
+         vis_botlin = inv_botlin;
+
+         /* Move the cursor where it should be. */
+         move_vert (c_pos / screenwidth);
+         move_cursor_relative (c_pos % screenwidth,
+                               &invisible_line[(c_pos / screenwidth) * screenwidth]);
+       }
+    }
+  else                         /* Do horizontal scrolling. */
+    {
+      int lmargin;
+
+      /* Always at top line. */
+      last_v_pos = 0;
+
+      /* If the display position of the cursor would be off the edge
+        of the screen, start the display of this line at an offset that
+        leaves the cursor on the screen. */
+      if (c_pos - last_lmargin > screenwidth - 2)
+       lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3);
+      else if (c_pos - last_lmargin < 1)
+       lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3);
+      else
+       lmargin = last_lmargin;
+
+      /* If the first character on the screen isn't the first character
+        in the display line, indicate this with a special character. */
+      if (lmargin > 0)
+       line[lmargin] = '<';
+
+      if (lmargin + screenwidth < out)
+       line[lmargin + screenwidth - 1] = '>';
+
+      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
+       {
+         forced_display = 0;
+         update_line (&visible_line[last_lmargin],
+                      &invisible_line[lmargin], 0);
+
+         move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
+         last_lmargin = lmargin;
+       }
+    }
+  fflush (out_stream);
+
+  /* Swap visible and non-visible lines. */
+  {
+    char *temp = visible_line;
+    visible_line = invisible_line;
+    invisible_line = temp;
+    rl_display_fixed = 0;
+  }
+}
+
+/* PWP: update_line() is based on finding the middle difference of each
+   line on the screen; vis:
+
+                            /old first difference
+       /beginning of line   |              /old last same       /old EOL
+       v                    v              v                    v
+old:   eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new:   eddie> Oh, my little buggy says to me, as lurgid as
+       ^                    ^        ^                    ^
+       \beginning of line   |        \new last same       \new end of line
+                            \new first difference
+
+   All are character pointers for the sake of speed.  Special cases for
+   no differences, as well as for end of line additions must be handeled.
+
+   Could be made even smarter, but this works well enough */
+static
+update_line (old, new, current_line)
+     register char *old, *new;
+     int current_line;
+{
+  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
+  int lendiff, wsatend;
+
+  /* Find first difference. */
+  for (ofd = old, nfd = new;
+       (ofd - old < screenwidth) && *ofd && (*ofd == *nfd);
+       ofd++, nfd++)
+    ;
+
+  /* Move to the end of the screen line. */
+  for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++);
+  for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++);
+
+  /* If no difference, continue to next line. */
+  if (ofd == oe && nfd == ne)
+    return;
+
+  wsatend = 1;                 /* flag for trailing whitespace */
+  ols = oe - 1;                        /* find last same */
+  nls = ne - 1;
+  while ((*ols == *nls) && (ols > ofd) && (nls > nfd))
+    {
+      if (*ols != ' ')
+       wsatend = 0;
+      ols--;
+      nls--;
+    }
+
+  if (wsatend)
+    {
+      ols = oe;
+      nls = ne;
+    }
+  else if (*ols != *nls)
+    {
+      if (*ols)                        /* don't step past the NUL */
+       ols++;
+      if (*nls)
+       nls++;
+    }
+
+  move_vert (current_line);
+  move_cursor_relative (ofd - old, old);
+
+  /* if (len (new) > len (old)) */
+  lendiff = (nls - nfd) - (ols - ofd);
+
+  /* Insert (diff(len(old),len(new)) ch */
+  if (lendiff > 0)
+    {
+      if (terminal_can_insert)
+       {
+         extern char *term_IC;
+
+         /* Sometimes it is cheaper to print the characters rather than
+            use the terminal's capabilities. */
+         if ((2 * (ne - nfd)) < lendiff && !term_IC)
+           {
+             output_some_chars (nfd, (ne - nfd));
+             last_c_pos += (ne - nfd);
+           }
+         else
+           {
+             if (*ols)
+               {
+                 insert_some_chars (nfd, lendiff);
+                 last_c_pos += lendiff;
+               }
+             else
+               {
+                 /* At the end of a line the characters do not have to
+                    be "inserted".  They can just be placed on the screen. */
+                 output_some_chars (nfd, lendiff);
+                 last_c_pos += lendiff;
+               }
+             /* Copy (new) chars to screen from first diff to last match. */
+             if (((nls - nfd) - lendiff) > 0)
+               {
+                 output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff));
+                 last_c_pos += ((nls - nfd) - lendiff);
+               }
+           }
+       }
+      else
+       {               /* cannot insert chars, write to EOL */
+         output_some_chars (nfd, (ne - nfd));
+         last_c_pos += (ne - nfd);
+       }
+    }
+  else                         /* Delete characters from line. */
+    {
+      /* If possible and inexpensive to use terminal deletion, then do so. */
+      if (term_dc && (2 * (ne - nfd)) >= (-lendiff))
+       {
+         if (lendiff)
+           delete_chars (-lendiff); /* delete (diff) characters */
+
+         /* Copy (new) chars to screen from first diff to last match */
+         if ((nls - nfd) > 0)
+           {
+             output_some_chars (nfd, (nls - nfd));
+             last_c_pos += (nls - nfd);
+           }
+       }
+      /* Otherwise, print over the existing material. */
+      else
+       {
+         output_some_chars (nfd, (ne - nfd));
+         last_c_pos += (ne - nfd);
+         clear_to_eol ((oe - old) - (ne - new));
+       }
+    }
+}
+
+/* (PWP) tell the update routines that we have moved onto a
+   new (empty) line. */
+rl_on_new_line ()
+{
+  if (visible_line)
+    visible_line[0] = '\0';
+
+  last_c_pos = last_v_pos = 0;
+  vis_botlin = last_lmargin = 0;
+}
+
+/* Actually update the display, period. */
+rl_forced_update_display ()
+{
+  if (visible_line)
+    {
+      register char *temp = visible_line;
+
+      while (*temp) *temp++ = '\0';
+    }
+  rl_on_new_line ();
+  forced_display++;
+  rl_redisplay ();
+}
+
+/* Move the cursor from last_c_pos to NEW, which are buffer indices.
+   DATA is the contents of the screen line of interest; i.e., where
+   the movement is being done. */
+static void
+move_cursor_relative (new, data)
+     int new;
+     char *data;
+{
+  register int i;
+
+  /* It may be faster to output a CR, and then move forwards instead
+     of moving backwards. */
+  if (new + 1 < last_c_pos - new)
+    {
+      tputs (term_cr, 1, output_character_function);
+      last_c_pos = 0;
+    }
+
+  if (last_c_pos == new) return;
+
+  if (last_c_pos < new)
+    {
+      /* Move the cursor forward.  We do it by printing the command
+        to move the cursor forward if there is one, else print that
+        portion of the output buffer again.  Which is cheaper? */
+
+      /* The above comment is left here for posterity.  It is faster
+        to print one character (non-control) than to print a control
+        sequence telling the terminal to move forward one character.
+        That kind of control is for people who don't know what the
+        data is underneath the cursor. */
+#ifdef HACK_TERMCAP_MOTION
+      extern char *term_forward_char;
+
+      if (term_forward_char)
+       for (i = last_c_pos; i < new; i++)
+         tputs (term_forward_char, 1, output_character_function);
+      else
+       for (i = last_c_pos; i < new; i++)
+         putc (data[i], out_stream);
+#else
+      for (i = last_c_pos; i < new; i++)
+       putc (data[i], out_stream);
+#endif                         /* HACK_TERMCAP_MOTION */
+    }
+  else
+    backspace (last_c_pos - new);
+  last_c_pos = new;
+}
+
+/* PWP: move the cursor up or down. */
+move_vert (to)
+     int to;
+{
+  void output_character_function ();
+  register int delta, i;
+
+  if (last_v_pos == to) return;
+
+  if (to > screenheight)
+    return;
+
+  if ((delta = to - last_v_pos) > 0)
+    {
+      for (i = 0; i < delta; i++)
+       putc ('\n', out_stream);
+      tputs (term_cr, 1, output_character_function);
+      last_c_pos = 0;          /* because crlf() will do \r\n */
+    }
+  else
+    {                  /* delta < 0 */
+      if (term_up && *term_up)
+       for (i = 0; i < -delta; i++)
+         tputs (term_up, 1, output_character_function);
+    }
+  last_v_pos = to;             /* now to is here */
+}
+
+/* Physically print C on out_stream.  This is for functions which know
+   how to optimize the display. */
+rl_show_char (c)
+     int c;
+{
+  if (c > 127)
+    {
+      fprintf (out_stream, "M-");
+      c -= 128;
+    }
+
+#ifdef DISPLAY_TABS
+  if (c < 32 && c != '\t')
+#else
+  if (c < 32)
+#endif
+    {
+
+      c += 64;
+    }
+
+  putc (c, out_stream);
+  fflush (out_stream);
+}
+
+#ifdef DISPLAY_TABS
+int
+rl_character_len (c, pos)
+     register int c, pos;
+{
+  if (c < ' ' || c > 126)
+    {
+      if (c == '\t')
+       return (((pos | (int)7) + 1) - pos);
+      else
+       return (3);
+    }
+  else
+    return (1);
+}
+#else
+int
+rl_character_len (c)
+     int c;
+{
+  if (c < ' ' || c > 126)
+    return (3);
+  else
+    return (1);
+}
+#endif  /* DISPLAY_TAB */
+
+/* How to print things in the "echo-area".  The prompt is treated as a
+   mini-modeline. */
+rl_message (string, arg1, arg2)
+     char *string;
+{
+  sprintf (msg_buf, string, arg1, arg2);
+  rl_display_prompt = msg_buf;
+  rl_redisplay ();
+}
+
+/* How to clear things from the "echo-area". */
+rl_clear_message ()
+{
+  rl_display_prompt = rl_prompt;
+  rl_redisplay ();
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Terminal and Termcap                        */
+/*                                                                 */
+/* **************************************************************** */
+
+static char *term_buffer = (char *)NULL;
+static char *term_string_buffer = (char *)NULL;
+
+/* Non-zero means this terminal can't really do anything. */
+int dumb_term = 0;
+
+char PC;
+char *BC, *UP;
+
+/* Some strings to control terminal actions.  These are output by tputs (). */
+char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
+
+int screenwidth, screenheight;
+
+/* Non-zero if we determine that the terminal can do character insertion. */
+int terminal_can_insert = 0;
+
+/* How to insert characters. */
+char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
+
+/* How to delete characters. */
+char *term_dc, *term_DC;
+
+#ifdef HACK_TERMCAP_MOTION
+char *term_forward_char;
+#endif  /* HACK_TERMCAP_MOTION */
+
+/* How to go up a line. */
+char *term_up;
+
+/* Re-initialize the terminal considering that the TERM/TERMCAP variable
+   has changed. */
+rl_reset_terminal (terminal_name)
+     char *terminal_name;
+{
+  init_terminal_io (terminal_name);
+}
+
+init_terminal_io (terminal_name)
+     char *terminal_name;
+{
+  char *term = (terminal_name? terminal_name : (char *)getenv ("TERM"));
+  char *tgetstr (), *buffer;
+
+
+  if (!term_string_buffer)
+    term_string_buffer = (char *)xmalloc (2048);
+
+  if (!term_buffer)
+    term_buffer = (char *)xmalloc (2048);
+
+  buffer = term_string_buffer;
+
+  term_clrpag = term_cr = term_clreol = (char *)NULL;
+
+  if (!term)
+    term = "dumb";
+
+  if (tgetent (term_buffer, term) < 0)
+    {
+      dumb_term = 1;
+      return;
+    }
+
+  BC = tgetstr ("pc", &buffer);
+  PC = buffer ? *buffer : 0;
+
+  term_backspace = tgetstr ("le", &buffer);
+
+  term_cr = tgetstr ("cr", &buffer);
+  term_clreol = tgetstr ("ce", &buffer);
+  term_clrpag = tgetstr ("cl", &buffer);
+
+  if (!term_cr)
+    term_cr =  "\r";
+
+#ifdef HACK_TERMCAP_MOTION
+  term_forward_char = tgetstr ("nd", &buffer);
+#endif  /* HACK_TERMCAP_MOTION */
+
+  screenwidth = tgetnum ("co");
+  if (screenwidth <= 0)
+    screenwidth = 80;
+  screenwidth--;               /* PWP: avoid autowrap bugs */
+
+  screenheight = tgetnum ("li");
+  if (screenheight <= 0)
+    screenheight = 24;
+
+  term_im = tgetstr ("im", &buffer);
+  term_ei = tgetstr ("ei", &buffer);
+  term_IC = tgetstr ("IC", &buffer);
+  term_ic = tgetstr ("ic", &buffer);
+
+  /* "An application program can assume that the terminal can do
+      character insertion if *any one of* the capabilities `IC',
+      `im', `ic' or `ip' is provided."  But we can't do anything if
+      only `ip' is provided, so... */
+  terminal_can_insert = (term_IC || term_im || term_ic);
+
+  term_up = tgetstr ("up", &buffer);
+  term_dc = tgetstr ("dc", &buffer);
+  term_DC = tgetstr ("DC", &buffer);
+}
+
+/* A function for the use of tputs () */
+static void
+output_character_function (c)
+     int c;
+{
+  putc (c, out_stream);
+}
+
+/* Write COUNT characters from STRING to the output stream. */
+static void
+output_some_chars (string, count)
+     char *string;
+     int count;
+{
+  fwrite (string, 1, count, out_stream);
+}
+
+
+/* Delete COUNT characters from the display line. */
+static
+delete_chars (count)
+     int count;
+{
+  if (count > screenwidth)
+    return;
+
+  if (term_DC && *term_DC)
+    {
+      char *tgoto (), *buffer;
+      buffer = tgoto (term_DC, 0, count);
+      tputs (buffer, 1, output_character_function);
+    }
+  else
+    {
+      if (term_dc && *term_dc)
+       while (count--)
+         tputs (term_dc, 1, output_character_function);
+    }
+}
+
+/* Insert COUNT character from STRING to the output stream. */
+static
+insert_some_chars (string, count)
+     char *string;
+     int count;
+{
+  /* If IC is defined, then we do not have to "enter" insert mode. */
+  if (term_IC)
+    {
+      char *tgoto (), *buffer;
+      buffer = tgoto (term_IC, 0, count);
+      tputs (buffer, 1, output_character_function);
+      output_some_chars (string, count);
+    }
+  else
+    {
+      register int i;
+
+      /* If we have to turn on insert-mode, then do so. */
+      if (term_im && *term_im)
+       tputs (term_im, 1, output_character_function);
+
+      /* If there is a special command for inserting characters, then
+        use that first to open up the space. */
+      if (term_ic && *term_ic)
+       {
+         for (i = count; i--; )
+           tputs (term_ic, 1, output_character_function);
+       }
+
+      /* Print the text. */
+      output_some_chars (string, count);
+
+      /* If there is a string to turn off insert mode, we had best use
+        it now. */
+      if (term_ei && *term_ei)
+       tputs (term_ei, 1, output_character_function);
+    }
+}
+
+/* Move the cursor back. */
+backspace (count)
+     int count;
+{
+  register int i;
+
+  if (term_backspace)
+    for (i = 0; i < count; i++)
+      tputs (term_backspace, 1, output_character_function);
+  else
+    for (i = 0; i < count; i++)
+      putc ('\b', out_stream);
+}
+
+/* Move to the start of the next line. */
+crlf ()
+{
+  tputs (term_cr, 1, output_character_function);
+  putc ('\n', out_stream);
+}
+
+/* Clear to the end of the line.  COUNT is the minimum
+   number of character spaces to clear, */
+clear_to_eol (count)
+     int count;
+{
+  if (term_clreol)
+    {
+      tputs (term_clreol, 1, output_character_function);
+    }
+  else
+    {
+      register int i;
+
+      /* Do one more character space. */
+      count++;
+
+      for (i = 0; i < count; i++)
+       putc (' ', out_stream);
+
+      backspace (count);
+    }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                   Saving and Restoring the TTY                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped = 0;
+
+#ifdef NEW_TTY_DRIVER
+
+/* Standard flags, including ECHO. */
+static int original_tty_flags = 0;
+
+/* Local mode flags, like LPASS8. */
+static int local_mode_flags = 0;
+
+/* Terminal characters.  This has C-s and C-q in it. */
+static struct tchars original_tchars;
+
+/* Local special characters.  This has the interrupt characters in it. */
+static struct ltchars original_ltchars;
+
+/* We use this to get and set the tty_flags. */
+static struct sgttyb the_ttybuff;
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+static
+rl_prep_terminal ()
+{
+  int tty = fileno (rl_instream);
+  int oldmask = sigblock (sigmask (SIGINT));
+
+  if (!terminal_prepped)
+    {
+      /* We always get the latest tty values.  Maybe stty changed them. */
+      ioctl (tty, TIOCGETP, &the_ttybuff);
+      original_tty_flags = the_ttybuff.sg_flags;
+
+      readline_echoing_p = (original_tty_flags & ECHO);
+
+       
+#if defined (TIOCLGET)
+      ioctl (tty, TIOCLGET, &local_mode_flags);
+#endif
+
+      /* If this terminal doesn't care how the 8th bit is used,
+        then we can use it for the meta-key.
+        We check by seeing if BOTH odd and even parity are allowed. */
+      if ((the_ttybuff.sg_flags & ODDP) && (the_ttybuff.sg_flags & EVENP))
+       {
+#ifdef PASS8
+         the_ttybuff.sg_flags |= PASS8;
+#endif
+         /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET) && defined (LPASS8)
+         {
+           int flags;
+           flags = local_mode_flags | LPASS8;
+           ioctl (tty, TIOCLSET, &flags);
+         }
+#endif
+       }
+
+#ifdef TIOCGETC
+      {
+       struct tchars temp;
+
+       ioctl (tty, TIOCGETC, &original_tchars);
+       bcopy (&original_tchars, &temp, sizeof (struct tchars));
+
+       /* Get rid of C-s and C-q.
+          We remember the value of startc (C-q) so that if the terminal is in
+          xoff state, the user can xon it by pressing that character. */
+       xon_char = temp.t_startc;
+       temp.t_stopc = -1;
+       temp.t_startc = -1;
+
+       /* If there is an XON character, bind it to restart the output. */
+       if (xon_char != -1)
+         rl_bind_key (xon_char, rl_restart_output);
+
+       /* If there is an EOF char, bind eof_char to it. */
+       if (temp.t_eofc != -1)
+         eof_char = temp.t_eofc;
+
+#ifdef NEVER
+       /* Get rid of C-\ and C-c. */
+       temp.t_intrc = temp.t_quitc = -1;
+#endif
+
+       ioctl (tty, TIOCSETC, &temp);
+      }
+#endif /* TIOCGETC */
+
+#ifdef TIOCGLTC
+      {
+       struct ltchars temp;
+
+       ioctl (tty, TIOCGLTC, &original_ltchars);
+       bcopy (&original_ltchars, &temp, sizeof (struct ltchars));
+
+       /* Make the interrupt keys go away.  Just enough to make people happy. */
+       temp.t_dsuspc = -1;     /* C-y */
+       temp.t_lnextc = -1;     /* C-v */
+
+       ioctl (tty, TIOCSLTC, &temp);
+      }
+#endif /* TIOCGLTC */
+
+      the_ttybuff.sg_flags &= ~ECHO;
+      the_ttybuff.sg_flags |= CBREAK;
+      ioctl (tty, TIOCSETN, &the_ttybuff);
+
+      terminal_prepped = 1;
+    }
+  sigsetmask (oldmask);
+}
+
+/* Restore the terminal to its original state. */
+static
+rl_deprep_terminal ()
+{
+  int tty = fileno (rl_instream);
+  int oldmask = sigblock (sigmask (SIGINT));
+
+  if (terminal_prepped)
+    {
+      the_ttybuff.sg_flags = original_tty_flags;
+      ioctl (tty, TIOCSETN, &the_ttybuff);
+      readline_echoing_p = 1;
+
+#if defined (TIOCLGET)
+      ioctl (tty, TIOCLSET, &local_mode_flags);
+#endif
+
+#ifdef TIOCSLTC
+      ioctl (tty, TIOCSLTC, &original_ltchars);
+#endif
+
+#ifdef TIOCSETC
+      ioctl (tty, TIOCSETC, &original_tchars);
+#endif
+      terminal_prepped = 0;
+    }
+
+  sigsetmask (oldmask);
+}
+
+#else  /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+#define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+#define VTIME VEOL
+#endif
+
+static struct termio otio;
+
+static
+rl_prep_terminal ()
+{
+  int tty = fileno (rl_instream);
+  struct termio tio;
+
+  ioctl (tty, TCGETA, &tio);
+  ioctl (tty, TCGETA, &otio);
+
+  readline_echoing_p = (tio.c_lflag & ECHO);
+
+  tio.c_lflag &= ~(ICANON|ECHO);
+  tio.c_iflag &= ~(IXON|IXOFF|IXANY|ISTRIP|INPCK);
+
+#if !defined (HANDLE_SIGNALS)
+  tio.c_lflag &= ~ISIG;
+#endif
+
+  tio.c_cc[VMIN] = 1;
+  tio.c_cc[VTIME] = 0;
+  ioctl (tty, TCSETAW, &tio);
+  ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
+}
+
+static
+rl_deprep_terminal ()
+{
+  int tty = fileno (rl_instream);
+  ioctl (tty, TCSETAW, &otio);
+  ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
+}
+#endif  /* NEW_TTY_DRIVER */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Utility Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return 0 if C is not a member of the class of characters that belong
+   in words, or 1 if it is. */
+
+int allow_pathname_alphabetic_chars = 0;
+char *pathname_alphabetic_chars = "/-_=~.#$";
+
+int
+alphabetic (c)
+     int c;
+{
+  char *rindex ();
+  if (pure_alphabetic (c) || (numeric (c)))
+    return (1);
+
+  if (allow_pathname_alphabetic_chars)
+    return ((int)rindex (pathname_alphabetic_chars, c));
+  else
+    return (0);
+}
+
+/* Return non-zero if C is a numeric character. */
+int
+numeric (c)
+     int c;
+{
+  return (c >= '0' && c <= '9');
+}
+
+/* Ring the terminal bell. */
+int
+ding ()
+{
+  if (readline_echoing_p)
+    {
+      fprintf (stderr, "\007");
+      fflush (stderr);
+    }
+  return (-1);
+}
+
+/* How to abort things. */
+rl_abort ()
+{
+  ding ();
+  rl_clear_message ();
+  rl_init_argument ();
+  rl_pending_input = 0;
+
+  defining_kbd_macro = 0;
+  while (executing_macro)
+    pop_executing_macro ();
+
+  longjmp (readline_top_level, 1);
+}
+
+/* Return a copy of the string between FROM and TO.
+   FROM is inclusive, TO is not. */
+static char *
+rl_copy (from, to)
+     int from, to;
+{
+  register int length;
+  char *copy;
+
+  /* Fix it if the caller is confused. */
+  if (from > to) {
+    int t = from;
+    from = to;
+    to = t;
+  }
+
+  length = to - from;
+  copy = (char *)xmalloc (1 + length);
+  strncpy (copy, the_line + from, length);
+  copy[length] = '\0';
+  return (copy);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Insert and Delete                           */
+/*                                                                 */
+/* **************************************************************** */
+
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  rl_insert () calls this
+   function. */
+rl_insert_text (string)
+     char *string;
+{
+  extern int doing_an_undo;
+  register int i, l = strlen (string);
+  while (rl_end + l >= rl_line_buffer_len)
+    {
+      rl_line_buffer =
+       (char *)xrealloc (rl_line_buffer,
+                         rl_line_buffer_len += DEFAULT_BUFFER_SIZE);
+      the_line = rl_line_buffer;
+    }
+
+  for (i = rl_end; i >= rl_point; i--)
+    the_line[i + l] = the_line[i];
+  strncpy (the_line + rl_point, string, l);
+
+  /* Remember how to undo this if we aren't undoing something. */
+  if (!doing_an_undo)
+    {
+      /* If possible and desirable, concatenate the undos. */
+      if ((strlen (string) == 1) &&
+         rl_undo_list &&
+         (rl_undo_list->what == UNDO_INSERT) &&
+         (rl_undo_list->end == rl_point) &&
+         (rl_undo_list->end - rl_undo_list->start < 20))
+       rl_undo_list->end++;
+      else
+       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+    }
+  rl_point += l;
+  rl_end += l;
+  the_line[rl_end] = '\0';
+}
+
+/* Delete the string between FROM and TO.  FROM is
+   inclusive, TO is not. */
+rl_delete_text (from, to)
+     int from, to;
+{
+  extern int doing_an_undo;
+  register char *text;
+
+  /* Fix it if the caller is confused. */
+  if (from > to) {
+    int t = from;
+    from = to;
+    to = t;
+  }
+  text = rl_copy (from, to);
+  strncpy (the_line + from, the_line + to, rl_end - to);
+
+  /* Remember how to undo this delete. */
+  if (!doing_an_undo)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
+
+  rl_end -= (to - from);
+  the_line[rl_end] = '\0';
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg pased to this command.
+   The second is the key which invoked this command.
+*/
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT characters. */
+rl_forward (count)
+     int count;
+{
+  if (count < 0)
+    rl_backward (-count);
+  else
+    while (count)
+      {
+#ifdef VI_MODE
+       if (rl_point == (rl_end - (rl_editing_mode == vi_mode)))
+#else
+       if (rl_point == rl_end)
+#endif
+         {
+           ding ();
+           return;
+         }
+       else
+         rl_point++;
+       --count;
+      }
+}
+
+/* Move backward COUNT characters. */
+rl_backward (count)
+     int count;
+{
+  if (count < 0)
+    rl_forward (-count);
+  else
+    while (count)
+      {
+       if (!rl_point)
+         {
+           ding ();
+           return;
+         }
+       else
+         --rl_point;
+       --count;
+      }
+}
+
+/* Move to the beginning of the line. */
+rl_beg_of_line ()
+{
+  rl_point = 0;
+}
+
+/* Move to the end of the line. */
+rl_end_of_line ()
+{
+  rl_point = rl_end;
+}
+
+/* Move forward a word.  We do what Emacs does. */
+rl_forward_word (count)
+     int count;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_backward_word (-count);
+      return;
+    }
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+       return;
+
+      /* If we are not in a word, move forward until we are in one.
+        Then, move forward until we hit a non-alphabetic character. */
+      c = the_line[rl_point];
+      if (!alphabetic (c))
+       {
+         while (++rl_point < rl_end)
+           {
+             c = the_line[rl_point];
+             if (alphabetic (c)) break;
+           }
+       }
+      if (rl_point == rl_end) return;
+      while (++rl_point < rl_end)
+       {
+         c = the_line[rl_point];
+         if (!alphabetic (c)) break;
+       }
+      --count;
+    }
+}
+
+/* Move backward a word.  We do what Emacs does. */
+rl_backward_word (count)
+     int count;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_forward_word (-count);
+      return;
+    }
+
+  while (count)
+    {
+      if (!rl_point)
+       return;
+
+      /* Like rl_forward_word (), except that we look at the characters
+        just before point. */
+
+      c = the_line[rl_point - 1];
+      if (!alphabetic (c))
+       {
+         while (--rl_point)
+           {
+             c = the_line[rl_point - 1];
+             if (alphabetic (c)) break;
+           }
+       }
+
+      while (rl_point)
+       {
+         c = the_line[rl_point - 1];
+         if (!alphabetic (c))
+           break;
+         else --rl_point;
+       }
+      --count;
+    }
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+rl_refresh_line ()
+{
+  int curr_line = last_c_pos / screenwidth;
+  extern char *term_clreol;
+
+  move_vert(curr_line);
+  move_cursor_relative (0, the_line);   /* XXX is this right */
+
+  if (term_clreol)
+    tputs (term_clreol, 1, output_character_function);
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+   the prompt and the current input line.  Given a numeric arg, redraw only
+   the current line. */
+rl_clear_screen ()
+{
+  extern char *term_clrpag;
+
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line ();
+      return;
+    }
+
+  if (term_clrpag)
+    tputs (term_clrpag, 1, output_character_function);
+  else
+    crlf ();
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert the character C at the current location, moving point forward. */
+rl_insert (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+
+  if (count <= 0)
+    return;
+
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count < 1024)
+    {
+      string = (char *)alloca (1 + count);
+
+      for (i = 0; i < count; i++)
+       string[i] = c;
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      return;
+    }
+
+  if (count > 1024)
+    {
+      int decreaser;
+
+      string = (char *)alloca (1024 + 1);
+
+      for (i = 0; i < 1024; i++)
+       string[i] = c;
+
+      while (count)
+       {
+         decreaser = (count > 1024 ? 1024 : count);
+         string[decreaser] = '\0';
+         rl_insert_text (string);
+         count -= decreaser;
+       }
+      return;
+    }
+
+  /* We are inserting a single character.
+     If there is pending input, then make a string of all of the
+     pending characters that are bound to rl_insert, and insert
+     them all. */
+  if (any_typein)
+    {
+      int key = 0, t;
+
+      i = 0;
+      string = (char *)alloca (ibuffer_len + 1);
+      string[i++] = c;
+
+      while ((t = rl_get_char (&key)) &&
+            (keymap[key].type == ISFUNC &&
+             keymap[key].function == rl_insert))
+       string[i++] = key;
+
+      if (t)
+       rl_unget_char (key);
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      return;
+    }
+  else
+    {
+      /* Inserting a single character. */
+      string = (char *)alloca (2);
+
+      string[1] = '\0';
+      string[0] = c;
+      rl_insert_text (string);
+    }
+}
+
+/* Insert the next typed character verbatim. */
+rl_quoted_insert (count)
+     int count;
+{
+  int c = rl_read_key ();
+  rl_insert (count, c);
+}
+
+/* Insert a tab character. */
+rl_tab_insert (count)
+     int count;
+{
+  rl_insert (count, '\t');
+}
+
+/* What to do when a NEWLINE is pressed.  We accept the whole line.
+   KEY is the key that invoked this command.  I guess it could have
+   meaning in the future. */
+rl_newline (count, key)
+     int count, key;
+{
+
+  rl_done = 1;
+
+#ifdef VI_MODE
+  {
+    extern int vi_doing_insert;
+    if (vi_doing_insert)
+      {
+       rl_end_undo_group ();
+       vi_doing_insert = 0;
+      }
+  }
+#endif /* VI_MODE */
+
+  if (readline_echoing_p)
+    {
+      move_vert (vis_botlin);
+      vis_botlin = 0;
+      crlf ();
+      fflush (out_stream);
+      rl_display_fixed++;
+    }
+}
+
+rl_clean_up_for_exit ()
+{
+  if (readline_echoing_p)
+    {
+      move_vert (vis_botlin);
+      vis_botlin = 0;
+      fflush (out_stream);
+      rl_restart_output ();
+    }
+}
+
+/* What to do for some uppercase characters, like meta characters,
+   and some characters appearing in emacs_ctlx_keymap.  This function
+   is just a stub, you bind keys to it and the code in rl_dispatch ()
+   is special cased. */
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+}
+
+/* Rubout the character behind point. */
+rl_rubout (count)
+     int count;
+{
+  if (count < 0)
+    {
+      rl_delete (-count);
+      return;
+    }
+
+  if (!rl_point)
+    {
+      ding ();
+      return;
+    }
+
+  if (count > 1)
+    {
+      int orig_point = rl_point;
+      rl_backward (count);
+      rl_kill_text (orig_point, rl_point);
+    }
+  else
+    {
+      int c = the_line[--rl_point];
+      rl_delete_text (rl_point, rl_point + 1);
+
+      if (rl_point == rl_end && alphabetic (c) && last_c_pos)
+       {
+         backspace (1);
+         putc (' ', out_stream);
+         backspace (1);
+         last_c_pos--;
+         visible_line[last_c_pos] = '\0';
+         rl_display_fixed++;
+       }
+    }
+}
+
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+rl_delete (count, invoking_key)
+     int count, invoking_key;
+{
+  if (count < 0)
+    {
+      rl_rubout (-count);
+      return;
+    }
+
+  if (rl_point == rl_end)
+    {
+      ding ();
+      return;
+    }
+
+  if (count > 1)
+    {
+      int orig_point = rl_point;
+      rl_forward (count);
+      rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+    }
+  else
+    rl_delete_text (rl_point, rl_point + 1);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Kill commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The next two functions mimic unix line editing behaviour, except they
+   save the deleted text on the kill ring.  This is safer than not saving
+   it, and since we have a ring, nobody should get screwed. */
+
+/* This does what C-w does in Unix.  We can't prevent people from
+   using behaviour that they expect. */
+rl_unix_word_rubout ()
+{
+  if (!rl_point) ding ();
+  else {
+    int orig_point = rl_point;
+    while (rl_point && whitespace (the_line[rl_point - 1]))
+      rl_point--;
+    while (rl_point && !whitespace (the_line[rl_point - 1]))
+      rl_point--;
+    rl_kill_text (rl_point, orig_point);
+  }
+}
+
+/* Here is C-u doing what Unix does.  You don't *have* to use these
+   key-bindings.  We have a choice of killing the entire line, or
+   killing from where we are to the start of the line.  We choose the
+   latter, because if you are a Unix weenie, then you haven't backspaced
+   into the line at all, and if you aren't, then you know what you are
+   doing. */
+rl_unix_line_discard ()
+{
+  if (!rl_point) ding ();
+  else {
+    rl_kill_text (rl_point, 0);
+    rl_point = 0;
+  }
+}
+
+\f
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Commands For Typos                          */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Random and interesting things in here.  */
+
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+rl_upcase_word (count)
+     int count;
+{
+  rl_change_case (count, UpCase);
+}
+
+/* Lowercase the word at point. */
+rl_downcase_word (count)
+     int count;
+{
+  rl_change_case (count, DownCase);
+}
+
+/* Upcase the first letter, downcase the rest. */
+rl_capitalize_word (count)
+     int count;
+{
+  rl_change_case (count, CapCase);
+}
+
+/* The meaty function.
+   Change the case of COUNT words, performing OP on them.
+   OP is one of UpCase, DownCase, or CapCase.
+   If a negative argument is given, leave point where it started,
+   otherwise, leave it where it moves to. */
+rl_change_case (count, op)
+     int count, op;
+{
+  register int start = rl_point, end;
+  int state = 0;
+
+  rl_forward_word (count);
+  end = rl_point;
+
+  if (count < 0)
+    {
+      int temp = start;
+      start = end;
+      end = temp;
+    }
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  for (; start < end; start++)
+    {
+      switch (op)
+       {
+       case UpCase:
+         the_line[start] = to_upper (the_line[start]);
+         break;
+
+       case DownCase:
+         the_line[start] = to_lower (the_line[start]);
+         break;
+
+       case CapCase:
+         if (state == 0)
+           {
+             the_line[start] = to_upper (the_line[start]);
+             state = 1;
+           }
+         else
+           {
+             the_line[start] = to_lower (the_line[start]);
+           }
+         if (!pure_alphabetic (the_line[start]))
+           state = 0;
+         break;
+
+       default:
+         abort ();
+       }
+    }
+  rl_point = end;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point. */
+rl_transpose_words (count)
+     int count;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count) return;
+
+  /* Find the two words. */
+  rl_forward_word (count);
+  w2_end = rl_point;
+  rl_backward_word (1);
+  w2_beg = rl_point;
+  rl_backward_word (count);
+  w1_beg = rl_point;
+  rl_forward_word (1);
+  w1_end = rl_point;
+
+  /* Do some check to make sure that there really are two words. */
+  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+    {
+      ding ();
+      rl_point = orig_point;
+      return;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy (w1_beg, w1_end);
+  word2 = rl_copy (w2_beg, w2_end);
+
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
+
+  /* Do the stuff at word2 first, so that we don't have to worry
+     about word1 moving. */
+  rl_point = w2_beg;
+  rl_delete_text (w2_beg, w2_end);
+  rl_insert_text (word1);
+
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
+
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
+
+  /* I think that does it. */
+  rl_end_undo_group ();
+  free (word1); free (word2);
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+rl_transpose_chars (count)
+     int count;
+{
+  if (!count)
+    return;
+
+  if (!rl_point || rl_end < 2) {
+    ding ();
+    return;
+  }
+
+  while (count) {
+    if (rl_point == rl_end) {
+      int t = the_line[rl_point - 1];
+      the_line[rl_point - 1] = the_line[rl_point - 2];
+      the_line[rl_point - 2] = t;
+    } else {
+      int t = the_line[rl_point];
+      the_line[rl_point] = the_line[rl_point - 1];
+      the_line[rl_point - 1] = t;
+      if (count < 0 && rl_point)
+       rl_point--;
+      else
+       rl_point++;
+    }
+    if (count < 0)
+      count++;
+    else
+      count--;
+  }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Bogus Flow Control                          */
+/*                                                                 */
+/* **************************************************************** */
+
+rl_restart_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (stdin);
+#ifdef TIOCSTART
+  ioctl (fildes, TIOCSTART, 0);
+#endif /* TIOCSTART */
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*     Completion matching, from readline's point of view.         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Pointer to the generator function for completion_matches ().
+   NULL means to use filename_entry_function (), the default filename
+   completer. */
+Function *rl_completion_entry_function = (Function *)NULL;
+
+/* Pointer to alternative function to create matches.
+   Function is called with TEXT, START, and END.
+   START and END are indices in RL_LINE_BUFFER saying what the boundaries
+   of TEXT are.
+   If this function exists and returns NULL then call the value of
+   rl_completion_entry_function to try to match, otherwise use the
+   array of strings returned. */
+Function *rl_attempted_completion_function = (Function *)NULL;
+
+/* Complete the word at or before point.  You have supplied the function
+   that does the initial simple matching selection algorithm (see
+   completion_matches ()).  The default is to do filename completion. */
+rl_complete (ignore, invoking_key)
+     int ignore, invoking_key;
+{
+  rl_complete_internal (TAB);
+}
+
+/* List the possible completions.  See description of rl_complete (). */
+rl_possible_completions ()
+{
+  rl_complete_internal ('?');
+}
+
+/* The user must press "y" or "n". Non-zero return means "y" pressed. */
+get_y_or_n ()
+{
+  int c;
+ loop:
+  c = rl_read_key ();
+  if (c == 'y' || c == 'Y') return (1);
+  if (c == 'n' || c == 'N') return (0);
+  if (c == ABORT_CHAR) rl_abort ();
+  ding (); goto loop;
+}
+
+/* Up to this many items will be displayed in response to a
+   possible-completions call.  After that, we ask the user if
+   she is sure she wants to see them all. */
+int rl_completion_query_items = 100;
+
+/* The basic list of characters that signal a break between words for the
+   completer routine.  The contents of this variable is what breaks words
+   in the shell, i.e. " \t\n\"\\'`@$><=" */
+char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=";
+
+/* The list of characters that signal a break between words for
+   rl_complete_internal.  The default list is the contents of
+   rl_basic_word_break_characters.  */
+char *rl_completer_word_break_characters = (char *)NULL;
+
+/* List of characters that are word break characters, but should be left
+   in TEXT when it is passed to the completion function.  The shell uses
+   this to help determine what kind of completing to do. */
+char *rl_special_prefixes = (char *)NULL;
+
+/* If non-zero, then disallow duplicates in the matches. */
+int rl_ignore_completion_duplicates = 1;
+
+/* Non-zero means that the results of the matches are to be treated
+   as filenames.  This is ALWAYS zero on entry, and can only be changed
+   within a completion entry finder function. */
+int rl_filename_completion_desired = 0;
+
+/* Complete the word at or before point.
+   WHAT_TO_DO says what to do with the completion.
+   `?' means list the possible completions.
+   TAB means do standard completion.
+   `*' means insert all of the possible completions. */
+rl_complete_internal (what_to_do)
+     int what_to_do;
+{
+  char *filename_completion_function ();
+  char **completion_matches (), **matches;
+  Function *our_func;
+  int start, end, delimiter = 0;
+  char *text;
+
+  if (rl_completion_entry_function)
+    our_func = rl_completion_entry_function;
+  else
+    our_func = (int (*)())filename_completion_function;
+
+  /* Only the completion entry function can change this. */
+  rl_filename_completion_desired = 0;
+
+  /* We now look backwards for the start of a filename/variable word. */
+  end = rl_point;
+  if (rl_point)
+    {
+      while (--rl_point &&
+            !rindex (rl_completer_word_break_characters, the_line[rl_point]));
+
+      /* If we are at a word break, then advance past it. */
+      if (rindex (rl_completer_word_break_characters,  (the_line[rl_point])))
+       {
+         /* If the character that caused the word break was a quoting
+            character, then remember it as the delimiter. */
+         if (rindex ("\"'", the_line[rl_point]) && (end - rl_point) > 1)
+           delimiter = the_line[rl_point];
+
+         /* If the character isn't needed to determine something special
+            about what kind of completion to perform, then advance past it. */
+
+         if (!rl_special_prefixes ||
+             !rindex (rl_special_prefixes, the_line[rl_point]))
+           rl_point++;
+       }
+    }
+
+  start = rl_point;
+  rl_point = end;
+  text = rl_copy (start, end);
+
+  /* If the user wants to TRY to complete, but then wants to give
+     up and use the default completion function, they set the
+     variable rl_attempted_completion_function. */
+  if (rl_attempted_completion_function)
+    {
+      matches =
+       (char **)(*rl_attempted_completion_function) (text, start, end);
+
+      if (matches)
+       goto after_usual_completion;
+    }
+
+  matches = completion_matches (text, our_func, start, end);
+
+ after_usual_completion:
+  free (text);
+
+  if (!matches)
+    ding ();
+  else
+    {
+      register int i;
+
+    some_matches:
+
+      /* It seems to me that in all the cases we handle we would like
+        to ignore duplicate possiblilities.  Scan for the text to
+        insert being identical to the other completions. */
+      if (rl_ignore_completion_duplicates)
+       {
+         char *lowest_common;
+         int j, newlen = 0;
+
+         /* Sort the items. */
+         /* It is safe to sort this array, because the lowest common
+            denominator found in matches[0] will remain in place. */
+         for (i = 0; matches[i]; i++);
+         qsort (matches, i, sizeof (char *), compare_strings);
+
+         /* Remember the lowest common denimator for it may be unique. */
+         lowest_common = savestring (matches[0]);
+
+         for (i = 0; matches[i + 1]; i++)
+           {
+             if (strcmp (matches[i], matches[i + 1]) == 0)
+               {
+                 free (matches[i]);
+                 matches[i] = (char *)-1;
+               }
+             else
+               newlen++;
+           }
+
+         /* We have marked all the dead slots with (char *)-1.
+            Copy all the non-dead entries into a new array. */
+         {
+           char **temp_array =
+             (char **)malloc ((3 + newlen) * sizeof (char *));
+
+           for (i = 1, j = 1; matches[i]; i++)
+             if (matches[i] != (char *)-1)
+               temp_array[j++] = matches[i];
+           temp_array[j] = (char *)NULL;
+
+           if (matches[0] != (char *)-1)
+             free (matches[0]);
+           free (matches);
+
+           matches = temp_array;
+         }
+
+         /* Place the lowest common denominator back in [0]. */
+         matches[0] = lowest_common;
+
+         /* If there is one string left, and it is identical to the
+            lowest common denominator, then the LCD is the string to
+            insert. */
+         if (j == 2 && strcmp (matches[0], matches[1]) == 0)
+           {
+             free (matches[1]);
+             matches[1] = (char *)NULL;
+           }
+       }
+
+      switch (what_to_do)
+       {
+       case TAB:
+         if (matches[0])
+           {
+             rl_delete_text (start, rl_point);
+             rl_point = start;
+             rl_insert_text (matches[0]);
+           }
+
+         /* If there are more matches, ring the bell to indicate.
+            If this was the only match, and we are hacking files,
+            check the file to see if it was a directory.  If so,
+            add a '/' to the name.  If not, and we are at the end
+            of the line, then add a space. */
+         if (matches[1])
+           {
+             ding ();          /* There are other matches remaining. */
+           }
+         else
+           {
+             char temp_string[2];
+
+             temp_string[0] = delimiter ? delimiter : ' ';
+             temp_string[1] = '\0';
+
+             if (rl_filename_completion_desired)
+               {
+                 struct stat finfo;
+                 char *tilde_expand ();
+                 char *filename = tilde_expand (matches[0]);
+
+                 if ((stat (filename, &finfo) == 0) &&
+                     ((finfo.st_mode & S_IFMT) == S_IFDIR))
+                   {
+                     if (the_line[rl_point] != '/')
+                       rl_insert_text ("/");
+                   }
+                 else
+                   {
+                     if (rl_point == rl_end)
+                       rl_insert_text (temp_string);
+                   }
+                 free (filename);
+               }
+             else
+               {
+                 if (rl_point == rl_end)
+                   rl_insert_text (temp_string);
+               }
+           }
+         break;
+
+       case '*':
+         {
+           int i = 1;
+
+           rl_delete_text (start, rl_point);
+           rl_point = start;
+           rl_begin_undo_group ();
+           if (matches[1])
+             {
+               while (matches[i])
+                 {
+                   rl_insert_text (matches[i++]);
+                   rl_insert_text (" ");
+                 }
+             }
+           else
+             {
+               rl_insert_text (matches[0]);
+               rl_insert_text (" ");
+             }
+           rl_end_undo_group ();
+         }
+         break;
+
+
+       case '?':
+         {
+           int len, count, limit, max = 0;
+           int j, k, l;
+
+           /* Handle simple case first.  What if there is only one answer? */
+           if (!matches[1])
+             {
+               char *rindex (), *temp;
+
+               if (rl_filename_completion_desired)
+                 temp = rindex (matches[0], '/');
+               else
+                 temp = (char *)NULL;
+
+               if (!temp)
+                 temp = matches[0];
+               else
+                 temp++;
+
+               crlf ();
+               fprintf (out_stream, "%s", temp);
+               crlf ();
+               goto restart;
+             }
+
+           /* There is more than one answer.  Find out how many there are,
+              and find out what the maximum printed length of a single entry
+              is. */
+           for (i = 1; matches[i]; i++)
+             {
+               char *rindex (), *temp = (char *)NULL;
+
+               /* If we are hacking filenames, then only count the characters
+                  after the last slash in the pathname. */
+               if (rl_filename_completion_desired)
+                 temp = rindex (matches[i], '/');
+               else
+                 temp = (char *)NULL;
+
+               if (!temp)
+                 temp = matches[i];
+               else
+                 temp++;
+
+               if (strlen (temp) > max)
+                 max = strlen (temp);
+             }
+
+           len = i;
+
+           /* If there are many items, then ask the user if she
+              really wants to see them all. */
+           if (len >= rl_completion_query_items)
+             {
+               crlf ();
+               fprintf (out_stream,
+                        "There are %d possibilities.  Do you really", len);
+               crlf ();
+               fprintf (out_stream, "wish to see them all? (y or n)");
+               fflush (out_stream);
+               if (!get_y_or_n ())
+                 {
+                   crlf ();
+                   goto restart;
+                 }
+             }
+           /* How many items of MAX length can we fit in the screen window? */
+           max += 2;
+           limit = screenwidth / max;
+           if (limit != 1 && (limit * max == screenwidth))
+             limit--;
+
+           /* How many iterations of the printing loop? */
+           count = (len + (limit - 1)) / limit;
+
+           /* Watch out for special case.  If LEN is less than LIMIT, then
+              just do the inner printing loop. */
+           if (len < limit) count = 1;
+
+           /* Sort the items if they are not already sorted. */
+           if (!rl_ignore_completion_duplicates)
+             qsort (matches, len, sizeof (char *), compare_strings);
+
+           /* Print the sorted items, up-and-down alphabetically, like
+              ls might. */
+           crlf ();
+
+           for (i = 1; i < count + 1; i++)
+             {
+               for (j = 0, l = i; j < limit; j++)
+                 {
+                   if (l > len || !matches[l])
+                     {
+                       break;
+                     }
+                   else
+                     {
+                       char *rindex (), *temp = (char *)NULL;
+
+                       if (rl_filename_completion_desired)
+                         temp = rindex (matches[l], '/');
+                       else
+                         temp = (char *)NULL;
+
+                       if (!temp)
+                         temp = matches[l];
+                       else
+                         temp++;
+
+                       fprintf (out_stream, "%s", temp);
+                       for (k = 0; k < max - strlen (temp); k++)
+                         putc (' ', out_stream);
+                     }
+                   l += count;
+                 }
+               crlf ();
+             }
+         restart:
+
+           rl_on_new_line ();
+         }
+         break;
+
+       default:
+         abort ();
+       }
+
+      for (i = 0; matches[i]; i++)
+       free (matches[i]);
+      free (matches);
+    }
+}
+
+/* Stupid comparison routine for qsort () ing strings. */
+static int
+compare_strings (s1, s2)
+  char **s1, **s2;
+{
+  return (strcmp (*s1, *s2));
+}
+
+/* A completion function for usernames.
+   TEXT contains a partial username preceded by a random
+   character (usually `~').  */
+char *
+username_completion_function (text, state)
+     int state;
+     char *text;
+{
+  static char *username = (char *)NULL;
+  static struct passwd *entry;
+  static int namelen;
+
+  if (!state)
+    {
+      if (username)
+       free (username);
+      username = savestring (&text[1]);
+      namelen = strlen (username);
+      setpwent ();
+    }
+
+  while (entry = getpwent ())
+    {
+      if (strncmp (username, entry->pw_name, namelen) == 0)
+       break;
+    }
+
+  if (!entry)
+    {
+      endpwent ();
+      return ((char *)NULL);
+    }
+  else
+    {
+      char *value = (char *)xmalloc (2 + strlen (entry->pw_name));
+      *value = *text;
+      strcpy (value + 1, entry->pw_name);
+      rl_filename_completion_desired = 1;
+      return (value);
+    }
+}
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+Function *rl_tilde_expander = (Function *)NULL;
+
+/* Expand FILENAME if it begins with a tilde.  This always returns
+   a new string. */
+char *
+tilde_expand (filename)
+     char *filename;
+{
+  char *dirname = filename ? savestring (filename) : (char *)NULL;
+
+  if (dirname && *dirname == '~')
+    {
+      char *temp_name;
+      if (!dirname[1] || dirname[1] == '/')
+       {
+         /* Prepend $HOME to the rest of the string. */
+         char *temp_home = (char *)getenv ("HOME");
+
+         temp_name = (char *)alloca (1 + strlen (&dirname[1])
+                                     + (temp_home? strlen (temp_home) : 0));
+         temp_name[0] = '\0';
+         if (temp_home)
+           strcpy (temp_name, temp_home);
+         strcat (temp_name, &dirname[1]);
+         free (dirname);
+         dirname = savestring (temp_name);
+       }
+      else
+       {
+         struct passwd *getpwnam (), *user_entry;
+         char *username = (char *)alloca (257);
+         int i, c;
+
+         for (i = 1; c = dirname[i]; i++)
+           {
+             if (c == '/') break;
+             else username[i - 1] = c;
+           }
+         username[i - 1] = '\0';
+
+         if (!(user_entry = getpwnam (username)))
+           {
+             /* If the calling program has a special syntax for
+                expanding tildes, and we couldn't find a standard
+                expansion, then let them try. */
+             if (rl_tilde_expander)
+               {
+                 char *expansion;
+
+                 expansion = (char *)(*rl_tilde_expander) (username);
+
+                 if (expansion)
+                   {
+                     temp_name = (char *)alloca (1 + strlen (expansion)
+                                                 + strlen (&dirname[i]));
+                     strcpy (temp_name, expansion);
+                     strcat (temp_name, &dirname[i]);
+                     free (expansion);
+                     goto return_name;
+                   }
+               }
+             /*
+              * We shouldn't report errors.
+              */
+           }
+         else
+           {
+             temp_name = (char *)alloca (1 + strlen (user_entry->pw_dir)
+                                         + strlen (&dirname[i]));
+             strcpy (temp_name, user_entry->pw_dir);
+             strcat (temp_name, &dirname[i]);
+           return_name:
+             free (dirname);
+             dirname = savestring (temp_name);
+           }
+       }
+    }
+  return (dirname);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Undo, and Undoing                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero tells rl_delete_text and rl_insert_text to not add to
+   the undo list. */
+int doing_an_undo = 0;
+
+/* The current undo list for THE_LINE. */
+UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
+
+/* Remember how to undo something.  Concatenate some undos if that
+   seems right. */
+rl_add_undo (what, start, end, text)
+     enum undo_code what;
+     int start, end;
+     char *text;
+{
+  UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
+  temp->what = what;
+  temp->start = start;
+  temp->end = end;
+  temp->text = text;
+  temp->next = rl_undo_list;
+  rl_undo_list = temp;
+}
+
+/* Free the existing undo list. */
+free_undo_list ()
+{
+  while (rl_undo_list) {
+    UNDO_LIST *release = rl_undo_list;
+    rl_undo_list = rl_undo_list->next;
+
+    if (release->what == UNDO_DELETE)
+      free (release->text);
+
+    free (release);
+  }
+}
+
+/* Undo the next thing in the list.  Return 0 if there
+   is nothing to undo, or non-zero if there was. */
+int
+rl_do_undo ()
+{
+  UNDO_LIST *release;
+  int waiting_for_begin = 0;
+
+undo_thing:
+  if (!rl_undo_list)
+    return (0);
+
+  doing_an_undo = 1;
+
+  switch (rl_undo_list->what) {
+
+    /* Undoing deletes means inserting some text. */
+  case UNDO_DELETE:
+    rl_point = rl_undo_list->start;
+    rl_insert_text (rl_undo_list->text);
+    free (rl_undo_list->text);
+    break;
+
+    /* Undoing inserts means deleting some text. */
+  case UNDO_INSERT:
+    rl_delete_text (rl_undo_list->start, rl_undo_list->end);
+    rl_point = rl_undo_list->start;
+    break;
+
+    /* Undoing an END means undoing everything 'til we get to
+       a BEGIN. */
+  case UNDO_END:
+    waiting_for_begin++;
+    break;
+
+    /* Undoing a BEGIN means that we are done with this group. */
+  case UNDO_BEGIN:
+    if (waiting_for_begin)
+      waiting_for_begin--;
+    else
+      abort ();
+    break;
+  }
+
+  doing_an_undo = 0;
+
+  release = rl_undo_list;
+  rl_undo_list = rl_undo_list->next;
+  free (release);
+
+  if (waiting_for_begin)
+    goto undo_thing;
+
+  return (1);
+}
+
+/* Begin a group.  Subsequent undos are undone as an atomic operation. */
+rl_begin_undo_group ()
+{
+  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+}
+
+/* End an undo group started with rl_begin_undo_group (). */
+rl_end_undo_group ()
+{
+  rl_add_undo (UNDO_END, 0, 0, 0);
+}
+
+/* Save an undo entry for the text from START to END. */
+rl_modifying (start, end)
+     int start, end;
+{
+  if (start > end)
+    {
+      int t = start;
+      start = end;
+      end = t;
+    }
+
+  if (start != end)
+    {
+      char *temp = rl_copy (start, end);
+      rl_begin_undo_group ();
+      rl_add_undo (UNDO_DELETE, start, end, temp);
+      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
+      rl_end_undo_group ();
+    }
+}
+
+/* Revert the current line to its previous state. */
+rl_revert_line ()
+{
+  if (!rl_undo_list) ding ();
+  else {
+    while (rl_undo_list)
+      rl_do_undo ();
+  }
+}
+
+/* Do some undoing of things that were done. */
+rl_undo_command (count)
+{
+  if (count < 0) return;       /* Nothing to do. */
+
+  while (count)
+    {
+      if (rl_do_undo ())
+       {
+         count--;
+       }
+      else
+       {
+         ding ();
+         break;
+       }
+    }
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Utilities                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* We already have a history library, and that is what we use to control
+   the history features of readline.  However, this is our local interface
+   to the history mechanism. */
+
+/* While we are editing the history, this is the saved
+   version of the original line. */
+HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
+
+/* Set the history pointer back to the last entry in the history. */
+start_using_history ()
+{
+  using_history ();
+  if (saved_line_for_history)
+    free_history_entry (saved_line_for_history);
+
+  saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Free the contents (and containing structure) of a HIST_ENTRY. */
+free_history_entry (entry)
+     HIST_ENTRY *entry;
+{
+  if (!entry) return;
+  if (entry->line)
+    free (entry->line);
+  free (entry);
+}
+
+/* Perhaps put back the current line if it has changed. */
+maybe_replace_line ()
+{
+  HIST_ENTRY *temp = current_history ();
+
+  /* If the current line has changed, save the changes. */
+  if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) {
+    temp = replace_history_entry (where_history (), the_line, rl_undo_list);
+    free (temp->line);
+    free (temp);
+  }
+}
+
+/* Put back the saved_line_for_history if there is one. */
+maybe_unsave_line ()
+{
+  if (saved_line_for_history) {
+    strcpy (the_line, saved_line_for_history->line);
+    rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
+    free_history_entry (saved_line_for_history);
+    saved_line_for_history = (HIST_ENTRY *)NULL;
+    rl_end = rl_point = strlen (the_line);
+  } else {
+    ding ();
+  }
+}
+
+/* Save the current line in saved_line_for_history. */
+maybe_save_line ()
+{
+  if (!saved_line_for_history) {
+    saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+    saved_line_for_history->line = savestring (the_line);
+    saved_line_for_history->data = (char *)rl_undo_list;
+  }
+}
+
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Commands                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Meta-< goes to the start of the history. */
+rl_beginning_of_history ()
+{
+  rl_get_previous_history (1 + where_history ());
+}
+
+/* Meta-> goes to the end of the history.  (The current line). */
+rl_end_of_history ()
+{
+  maybe_replace_line ();
+  using_history ();
+  maybe_unsave_line ();
+}
+
+/* Move down to the next history line. */
+rl_get_next_history (count)
+     int count;
+{
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    {
+      rl_get_previous_history (-count);
+      return;
+    }
+
+  if (!count)
+    return;
+
+  maybe_replace_line ();
+
+  while (count)
+    {
+      temp = next_history ();
+      if (!temp)
+       break;
+      --count;
+    }
+
+  if (!temp)
+    maybe_unsave_line ();
+  else
+    {
+      strcpy (the_line, temp->line);
+      rl_undo_list = (UNDO_LIST *)temp->data;
+      rl_end = rl_point = strlen (the_line);
+    }
+}
+
+/* Get the previous item out of our interactive history, making it the current
+   line.  If there is no previous history, just ding. */
+rl_get_previous_history (count)
+     int count;
+{
+  HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL;
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    {
+      rl_get_next_history (-count);
+      return;
+    }
+
+  if (!count)
+    return;
+
+  /* If we don't have a line saved, then save this one. */
+  maybe_save_line ();
+
+  /* If the current line has changed, save the changes. */
+  maybe_replace_line ();
+
+  while (count)
+    {
+      temp = previous_history ();
+      if (!temp)
+       break;
+      else
+       old_temp = temp;
+      --count;
+    }
+
+  /* If there was a large argument, and we moved back to the start of the
+     history, that is not an error.  So use the last value found. */
+  if (!temp && old_temp)
+    temp = old_temp;
+
+  if (!temp)
+    ding ();
+  else
+    {
+      strcpy (the_line, temp->line);
+      rl_undo_list = (UNDO_LIST *)temp->data;
+      rl_end = rl_point = strlen (the_line);
+#ifdef VI_MODE
+      if (rl_editing_mode == vi_mode)
+       rl_point = 0;
+#endif /* VI_MODE */
+    }
+}
+
+/* There is a command in ksh which yanks into this line, the last word
+   of the previous line.  Here it is.  We left it on M-. */
+rl_yank_previous_last_arg (ignore)
+     int ignore;
+{
+}
+
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     I-Search and Searching                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Search backwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+rl_reverse_search_history (sign, key)
+     int sign;
+     int key;
+{
+  rl_search_history (-sign, key);
+}
+
+/* Search forwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+rl_forward_search_history (sign, key)
+     int sign;
+     int key;
+{
+  rl_search_history (sign, key);
+}
+
+/* Display the current state of the search in the echo-area.
+   SEARCH_STRING contains the string that is being searched for,
+   DIRECTION is zero for forward, or 1 for reverse,
+   WHERE is the history list number of the current line.  If it is
+   -1, then this line is the starting one. */
+rl_display_search (search_string, reverse_p, where)
+     char *search_string;
+     int reverse_p, where;
+{
+  char *message = (char *)NULL;
+
+  message =
+    (char *)alloca (1 + (search_string ? strlen (search_string) : 0) + 30);
+
+  *message = '\0';
+
+#ifdef NEVER
+  if (where != -1)
+    sprintf (message, "[%d]", where + history_base);
+#endif
+
+  strcat (message, "(");
+
+  if (reverse_p)
+    strcat (message, "reverse-");
+
+  strcat (message, "i-search)`");
+
+  if (search_string)
+    strcat (message, search_string);
+
+  strcat (message, "': ");
+  rl_message (message, 0, 0);
+  rl_redisplay ();
+}
+
+/* Search through the history looking for an interactively typed string.
+   This is analogous to i-search.  We start the search in the current line.
+   DIRECTION is which direction to search; > 0 means forward, < 0 means
+   backwards. */
+rl_search_history (direction, invoking_key)
+     int direction;
+     int invoking_key;
+{
+  /* The string that the user types in to search for. */
+  char *search_string = (char *)alloca (128);
+
+  /* The current length of SEARCH_STRING. */
+  int search_string_index;
+
+  /* The list of lines to search through. */
+  char **lines;
+
+  /* The length of LINES. */
+  int hlen;
+
+  /* Where we get LINES from. */
+  HIST_ENTRY **hlist = history_list ();
+
+  int orig_point = rl_point;
+  int orig_line = where_history ();
+  int last_found_line = orig_line;
+  int c, done = 0;
+  register int i = 0;
+
+
+  /* The line currently being searched. */
+  char *sline;
+
+  /* Offset in that line. */
+  int index;
+
+  /* Non-zero if we are doing a reverse search. */
+  int reverse = (direction < 0);
+
+  /* Create an arrary of pointers to the lines that we want to search. */
+
+  maybe_replace_line ();
+  if (hlist)
+    for (i = 0; hlist[i]; i++);
+
+  /* Allocate space for this many lines, +1 for the current input line,
+     and remember those lines. */
+  lines = (char **)alloca ((1 + (hlen = i)) * sizeof (char *));
+  for (i = 0; i < hlen; i++)
+    lines[i] = hlist[i]->line;
+
+  if (saved_line_for_history)
+    lines[i] = saved_line_for_history->line;
+  else
+    {
+      /* So I have to type it in this way instead. */
+      lines[i] = (char *)alloca (1 + strlen (the_line));
+      strcpy (lines[i], &the_line[0]);
+    }
+
+  hlen++;
+
+  /* The line where we start the search. */
+  i = orig_line;
+
+  /* Initialize search parameters. */
+  *search_string = '\0';
+  search_string_index = 0;
+
+  rl_display_search (search_string, reverse, -1);
+
+  sline = the_line;
+  index = rl_point;
+
+  while (!done)
+    {
+      c = rl_read_key ();
+
+      /* Hack C to Do What I Mean. */
+      {
+       Function *f = (Function *)NULL;
+
+       if (keymap[c].type == ISFUNC)
+         f = keymap[c].function;
+
+       if (f == rl_reverse_search_history)
+         c = reverse ? -1 : -2;
+       else if (f == rl_forward_search_history)
+         c =  !reverse ? -1 : -2;
+      }
+
+      switch (c)
+       {
+       case ESC:
+         done = 1;
+         continue;
+
+         /* case invoking_key: */
+       case -1:
+         goto search_again;
+
+         /* switch directions */
+       case -2:
+         direction = -direction;
+         reverse = (direction < 0);
+
+         goto do_search;
+
+       case CTRL ('G'):
+         strcpy (the_line, lines[orig_line]);
+         rl_point = orig_point;
+         rl_end = strlen (the_line);
+         rl_clear_message ();
+         return;
+
+       default:
+         if (c < 32 || c > 126)
+           {
+             rl_execute_next (c);
+             done = 1;
+             continue;
+           }
+         else
+           {
+             search_string[search_string_index++] = c;
+             search_string[search_string_index] = '\0';
+             goto do_search;
+
+           search_again:
+
+             if (!search_string_index)
+               continue;
+             else
+               {
+                 if (reverse)
+                   --index;
+                 else
+                   if (index != strlen (sline))
+                     ++index;
+                   else
+                     ding ();
+               }
+           do_search:
+
+             while (1)
+               {
+                 if (reverse)
+                   {
+                     while (index >= 0)
+                       if (strncmp
+                           (search_string,
+                            sline + index,
+                            search_string_index) == 0)
+                         goto string_found;
+                       else
+                         index--;
+                   }
+                 else
+                   {
+                     register int limit =
+                       (strlen (sline) - search_string_index) + 1;
+
+                     while (index < limit)
+                       {
+                         if (strncmp (search_string,
+                                      sline + index,
+                                      search_string_index) == 0)
+                           goto string_found;
+                         index++;
+                       }
+                   }
+
+               next_line:
+                 i += direction;
+
+                 /* At limit for direction? */
+                 if ((reverse && i < 0) ||
+                     (!reverse && i == hlen))
+                   goto search_failed;
+
+                 sline = lines[i];
+                 if (reverse)
+                   index = strlen (sline);
+                 else
+                   index = 0;
+
+                 /* If the search string is longer than the current
+                    line, no match. */
+                 if (search_string_index > strlen (sline))
+                   goto next_line;
+
+                 /* Start actually searching. */
+                 if (reverse)
+                   index -= search_string_index;
+               }
+
+           search_failed:
+             /* We cannot find the search string.  Ding the bell. */
+             ding ();
+             i = last_found_line;
+             break;
+
+           string_found:
+             /* We have found the search string.  Just display it.  But don't
+                actually move there in the history list until the user accepts
+                the location. */
+             strcpy (the_line, lines[i]);
+             rl_point = index;
+             rl_end = strlen (the_line);
+             last_found_line = i;
+             rl_display_search (search_string, reverse,
+                                (i == orig_line) ? -1 : i);
+           }
+       }
+      continue;
+    }
+  /* The user has won.  They found the string that they wanted.  Now all
+     we have to do is place them there. */
+  {
+    int now = last_found_line;
+
+    /* First put back the original state. */
+    strcpy (the_line, lines[orig_line]);
+
+    if (now < orig_line)
+      rl_get_previous_history (orig_line - now);
+    else
+      rl_get_next_history (now - orig_line);
+
+    rl_point = index;
+    rl_clear_message ();
+  }
+}
+
+/* Make C be the next command to be executed. */
+rl_execute_next (c)
+     int c;
+{
+  rl_pending_input = c;
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Killing Mechanism                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* What we assume for a max number of kills. */
+#define DEFAULT_MAX_KILLS 10
+
+/* The real variable to look at to find out when to flush kills. */
+int rl_max_kills = DEFAULT_MAX_KILLS;
+
+/* Where to store killed text. */
+char **rl_kill_ring = (char **)NULL;
+
+/* Where we are in the kill ring. */
+int rl_kill_index = 0;
+
+/* How many slots we have in the kill ring. */
+int rl_kill_ring_length = 0;
+
+/* How to say that you only want to save a certain amount
+   of kill material. */
+rl_set_retained_kills (num)
+     int num;
+{}
+
+/* The way to kill something.  This appends or prepends to the last
+   kill, if the last command was a kill command.  if FROM is less
+   than TO, then the text is appended, otherwise prepended.  If the
+   last command was not a kill command, then a new slot is made for
+   this kill. */
+rl_kill_text (from, to)
+     int from, to;
+{
+  int slot;
+  char *text = rl_copy (from, to);
+
+  /* Is there anything to kill? */
+  if (from == to) {
+    free (text);
+    last_command_was_kill++;
+    return;
+  }
+
+  /* Delete the copied text from the line. */
+  rl_delete_text (from, to);
+
+  /* First, find the slot to work with. */
+  if (!last_command_was_kill) {
+
+    /* Get a new slot.  */
+    if (!rl_kill_ring) {
+
+      /* If we don't have any defined, then make one. */
+      rl_kill_ring =
+       (char **)xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
+      slot = 1;
+
+    } else {
+
+      /* We have to add a new slot on the end, unless we have exceeded
+        the max limit for remembering kills. */
+      slot = rl_kill_ring_length;
+      if (slot == rl_max_kills) {
+       register int i;
+       free (rl_kill_ring[0]);
+       for (i = 0; i < slot; i++)
+         rl_kill_ring[i] = rl_kill_ring[i + 1];
+      } else {
+       rl_kill_ring =
+         (char **)xrealloc (rl_kill_ring,
+                            ((slot = (rl_kill_ring_length += 1)) + 1)
+                            * sizeof (char *));
+      }
+    }
+    slot--;
+  } else {
+    slot = rl_kill_ring_length - 1;
+  }
+
+  /* If the last command was a kill, prepend or append. */
+  if (last_command_was_kill) {
+    char *old = rl_kill_ring[slot];
+    char *new = (char *)xmalloc (1 + strlen (old) + strlen (text));
+
+    if (from < to) {
+      strcpy (new, old);
+      strcat (new, text);
+    } else {
+      strcpy (new, text);
+      strcat (new, old);
+    }
+    free (old);
+    free (text);
+    rl_kill_ring[slot] = new;
+  } else {
+    rl_kill_ring[slot] = text;
+  }
+  rl_kill_index = slot;
+  last_command_was_kill++;
+}
+
+/* Now REMEMBER!  In order to do prepending or appending correctly, kill
+   commands always make rl_point's original position be the FROM argument,
+   and rl_point's extent be the TO argument. */
+
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Killing Commands                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Delete the word at point, saving the text in the kill ring. */
+rl_kill_word (count)
+     int count;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    rl_backward_kill_word (-count);
+  else
+    {
+      rl_forward_word (count);
+
+      if (rl_point != orig_point)
+       rl_kill_text (orig_point, rl_point);
+
+      rl_point = orig_point;
+    }
+}
+
+/* Rubout the word before point, placing it on the kill ring. */
+rl_backward_kill_word (count)
+     int count;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    rl_kill_word (-count);
+  else
+    {
+      rl_backward_word (count);
+
+      if (rl_point != orig_point)
+       rl_kill_text (orig_point, rl_point);
+    }
+}
+
+/* Kill from here to the end of the line.  If DIRECTION is negative, kill
+   back to the line start instead. */
+rl_kill_line (direction)
+     int direction;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    rl_backward_kill_line (1);
+  else
+    {
+      rl_end_of_line ();
+      if (orig_point != rl_point)
+       rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+    }
+}
+
+/* Kill backwards to the start of the line.  If DIRECTION is negative, kill
+   forwards to the line end instead. */
+rl_backward_kill_line (direction)
+     int direction;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    rl_kill_line (1);
+  else
+    {
+      if (!rl_point)
+       ding ();
+      else
+       {
+         rl_beg_of_line ();
+         rl_kill_text (orig_point, rl_point);
+       }
+    }
+}
+
+/* Yank back the last killed text.  This ignores arguments. */
+rl_yank ()
+{
+  if (!rl_kill_ring) rl_abort ();
+  rl_insert_text (rl_kill_ring[rl_kill_index]);
+}
+
+/* If the last command was yank, or yank_pop, and the text just
+   before point is identical to the current kill item, then
+   delete that text from the line, rotate the index down, and
+   yank back some other text. */
+rl_yank_pop ()
+{
+  int l;
+
+  if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
+      !rl_kill_ring)
+    {
+      rl_abort ();
+    }
+
+  l = strlen (rl_kill_ring[rl_kill_index]);
+  if (((rl_point - l) >= 0) &&
+      (strncmp (the_line + (rl_point - l),
+               rl_kill_ring[rl_kill_index], l) == 0))
+    {
+      rl_delete_text ((rl_point - l), rl_point);
+      rl_point -= l;
+      rl_kill_index--;
+      if (rl_kill_index < 0)
+       rl_kill_index = rl_kill_ring_length - 1;
+      rl_yank ();
+    }
+  else
+    rl_abort ();
+
+}
+
+/* Yank the COUNTth argument from the previous history line. */
+rl_yank_nth_arg (count, ignore)
+     int count;
+{
+  register HIST_ENTRY *entry = previous_history ();
+  char *arg;
+
+  if (entry)
+    next_history ();
+  else
+    {
+      ding ();
+      return;
+    }
+
+  arg = history_arg_extract (count, count, entry->line);
+  if (!arg || !*arg)
+    {
+      ding ();
+      return;
+    }
+
+  rl_begin_undo_group ();
+  if (rl_point && the_line[rl_point - 1] != ' ')
+    rl_insert_text (" ");
+  rl_insert_text (arg);
+  free (arg);
+  rl_end_undo_group ();
+}
+
+/* Vi Mode. */
+#ifdef VI_MODE
+#include "vi_mode.c"
+#endif /* VI_MODE */
+
+/* How to toggle back and forth between editing modes. */
+rl_vi_editing_mode ()
+{
+#ifdef VI_MODE
+  rl_editing_mode = vi_mode;
+  rl_vi_insertion_mode ();
+#endif /* VI_MODE */
+}
+
+rl_emacs_editing_mode ()
+{
+  rl_editing_mode = emacs_mode;
+  keymap = emacs_standard_keymap;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                          Completion                             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means that case is not significant in completion. */
+int completion_case_fold = 0;
+
+/* Return an array of (char *) which is a list of completions for TEXT.
+   If there are no completions, return a NULL pointer.
+   The first entry in the returned array is the substitution for TEXT.
+    The remaining entries are the possible completions.
+   The array is terminated with a NULL pointer.
+
+   ENTRY_FUNCTION is a function of two args, and returns a (char *).
+     The first argument is TEXT.
+     The second is a state argument; it should be zero on the first call, and
+     non-zero on subsequent calls.  It returns a NULL pointer to the caller
+     when there are no more matches.
+ */
+char **
+completion_matches (text, entry_function)
+     char *text;
+     char *(*entry_function) ();
+{
+  /* Number of slots in match_list. */
+  int match_list_size;
+
+  /* The list of matches. */
+  char **match_list =
+    (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *));
+
+  /* Number of matches actually found. */
+  int matches = 0;
+
+  /* Temporary string binder. */
+  char *string;
+
+  match_list[1] = (char *)NULL;
+
+  while (string = (*entry_function) (text, matches))
+    {
+      if (matches + 1 == match_list_size)
+       match_list =
+         (char **)xrealloc (match_list,
+                            ((match_list_size += 10) + 1) * sizeof (char *));
+
+      match_list[++matches] = string;
+      match_list[matches + 1] = (char *)NULL;
+    }
+
+  /* If there were any matches, then look through them finding out the
+     lowest common denominator.  That then becomes match_list[0]. */
+  if (matches)
+    {
+      register int i = 1;
+      int low = 100000;                /* Count of max-matched characters. */
+
+      /* If only one match, just use that. */
+      if (matches == 1)
+       {
+         match_list[0] = match_list[1];
+         match_list[1] = (char *)NULL;
+       }
+      else
+       {
+         /* Otherwise, compare each member of the list with
+            the next, finding out where they stop matching. */
+
+         while (i < matches)
+           {
+             register int c1, c2, si;
+
+             if (completion_case_fold)
+               {
+                 for (si = 0;
+                      (c1 = to_lower(match_list[i][si])) &&
+                      (c2 = to_lower(match_list[i + 1][si]));
+                      si++)
+                   if (c1 != c2) break;
+               }
+             else
+               {
+                 for (si = 0;
+                      (c1 = match_list[i][si]) &&
+                      (c2 = match_list[i + 1][si]);
+                      si++)
+                   if (c1 != c2) break;
+               }
+
+             if (low > si) low = si;
+             i++;
+           }
+         match_list[0] = (char *)xmalloc (low + 1);
+         strncpy (match_list[0], match_list[1], low);
+         match_list[0][low] = '\0';
+       }
+    }
+  else                         /* There were no matches. */
+    {
+      free (match_list);
+      match_list = (char **)NULL;
+    }
+  return (match_list);
+}
+
+/* Okay, now we write the entry_function for filename completion.  In the
+   general case.  Note that completion in the shell is a little different
+   because of all the pathnames that must be followed when looking up the
+   completion for a command. */
+char *
+filename_completion_function (text, state)
+     int state;
+     char *text;
+{
+  static DIR *directory;
+  static char *filename = (char *)NULL;
+  static char *dirname = (char *)NULL;
+  static char *users_dirname = (char *)NULL;
+  static int filename_len;
+
+  struct direct *entry = (struct direct *)NULL;
+
+  /* If we don't have any state, then do some initialization. */
+  if (!state)
+    {
+      char *rindex (), *temp;
+
+      if (dirname) free (dirname);
+      if (filename) free (filename);
+      if (users_dirname) free (users_dirname);
+
+      filename = savestring (text);
+      if (!*text) text = ".";
+      dirname = savestring (text);
+
+      temp = rindex (dirname, '/');
+
+      if (temp)
+       {
+         strcpy (filename, ++temp);
+         *temp = '\0';
+       }
+      else
+       strcpy (dirname, ".");
+
+      /* We aren't done yet.  We also support the "~user" syntax. */
+
+      /* Save the version of the directory that the user typed. */
+      users_dirname = savestring (dirname);
+      {
+       char *tilde_expand (), *temp_dirname = tilde_expand (dirname);
+       free (dirname);
+       dirname = temp_dirname;
+
+       if (rl_symbolic_link_hook)
+         (*rl_symbolic_link_hook) (&dirname);
+      }
+      directory = opendir (dirname);
+      filename_len = strlen (filename);
+
+      rl_filename_completion_desired = 1;
+    }
+
+  /* At this point we should entertain the possibility of hacking wildcarded
+     filenames, like /usr/man*\/te<TAB>.  If the directory name contains
+     globbing characters, then build an array of directories to glob on, and
+     glob on the first one. */
+
+  /* Now that we have some state, we can read the directory. */
+
+  while (directory && (entry = readdir (directory)))
+    {
+      /* Special case for no filename.
+        All entries except "." and ".." match. */
+      if (!filename_len)
+       {
+         if ((strcmp (entry->d_name, ".") != 0) &&
+             (strcmp (entry->d_name, "..") != 0))
+           break;
+       }
+      else
+       {
+         /* Otherwise, if these match upto the length of filename, then
+            it is a match. */
+#ifdef TMB_SYSV
+         if ((strlen (entry->d_name) >= filename_len) &&
+             (strncmp (filename, entry->d_name, filename_len) == 0))
+#else
+           if ((entry->d_namlen >= filename_len) &&
+               (strncmp (filename, entry->d_name, filename_len) == 0))
+#endif /* TMB_SYSV */
+             {
+               break;
+             }
+       }
+    }
+
+  if (!entry)
+    {
+      if (directory)
+       {
+         closedir (directory);
+         directory = (DIR *)NULL;
+       }
+      return (char *)NULL;
+    }
+  else
+    {
+      char *temp;
+
+      if (dirname && (strcmp (dirname, ".") != 0))
+       {
+#ifdef TMB_SYSV
+         temp = (char *)xmalloc (1 + strlen (users_dirname)
+                                 + strlen (entry->d_name));
+#else
+         temp = (char *)xmalloc (1 + strlen (users_dirname)
+                                 + entry->d_namlen);
+#endif /* TMB_SYSV */
+         strcpy (temp, users_dirname);
+         strcat (temp, entry->d_name);
+       }
+      else
+       {
+         temp = (savestring (entry->d_name));
+       }
+      return (temp);
+    }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Binding keys                                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* rl_add_defun (char *name, Function *function, int key)
+   Add NAME to the list of named functions.  Make FUNCTION
+   be the function that gets called.
+   If KEY is not -1, then bind it. */
+rl_add_defun (name, function, key)
+     char *name;
+     Function *function;
+     int key;
+{
+  if (key != -1)
+    rl_bind_key (key, function);
+  rl_add_funmap_entry (name, function);
+}
+
+/* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
+int
+rl_bind_key (key, function)
+     int key;
+     Function *function;
+{
+  if (key < 0)
+    return (key);
+
+  if (key > 127 && key < 256)
+    {
+      if (keymap[ESC].type == ISKMAP)
+       {
+         Keymap escmap = (Keymap)keymap[ESC].function;
+
+         key -= 128;
+         escmap[key].type = ISFUNC;
+         escmap[key].function = function;
+         return (0);
+       }
+      return (key);
+    }
+
+  keymap[key].type = ISFUNC;
+  keymap[key].function = function;
+ return (0);
+}
+
+/* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
+   KEY. */
+int
+rl_bind_key_in_map (key, function, map)
+     int key;
+     Function *function;
+     Keymap map;
+{
+  int result;
+  Keymap oldmap = keymap;
+
+  keymap = map;
+  result = rl_bind_key (key, function);
+  keymap = oldmap;
+  return (result);
+}
+
+/* Make KEY do nothing in the currently selected keymap.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key (key)
+     int key;
+{
+  return (rl_bind_key (key, (Function *)NULL));
+}
+
+/* Make KEY do nothing in MAP.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key_in_map (key, map)
+     int key;
+     Keymap map;
+{
+  return (rl_bind_key_in_map (key, (Function *)NULL, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   FUNCTION.  This makes new keymaps as necessary.  The initial
+   place to do bindings is in MAP. */
+rl_set_key (keyseq, function, map)
+     char *keyseq;
+     Function *function;
+     Keymap map;
+{
+  rl_generic_bind (ISFUNC, keyseq, function, map);
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the string of characters MACRO.  This makes new keymaps as
+   necessary.  The initial place to do bindings is in MAP. */
+rl_macro_bind (keyseq, macro, map)
+     char *keyseq, *macro;
+     Keymap map;
+{
+  char *macro_keys = (char *)xmalloc (2 * (strlen (macro)));
+  int macro_keys_len;
+
+  if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
+    {
+      free (macro_keys);
+      return;
+    }
+  rl_generic_bind (ISMACR, keyseq, macro_keys, map);
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the arbitrary pointer DATA.  TYPE says what kind of data is
+   pointed to by DATA, right now this can be a function (ISFUNC),
+   a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
+   as necessary.  The initial place to do bindings is in MAP. */
+rl_generic_bind (type, keyseq, data, map)
+     int type;
+     char *keyseq, *data;
+     Keymap map;
+{
+  char *keys;
+  int keys_len;
+  register int i;
+
+  /* If no keys to bind to, exit right away. */
+  if (!keyseq || !*keyseq)
+    {
+      if (type == ISMACR)
+       free (data);
+      return;
+    }
+
+  keys = (char *)alloca (1 + (2 * strlen (keyseq)));
+
+  /* Translate the ASCII representation of KEYSEQ into an array
+     of characters.  Stuff the characters into ARRAY, and the
+     length of ARRAY into LENGTH. */
+  if (rl_translate_keyseq (keyseq, keys, &keys_len))
+    return;
+
+  /* Bind keys, making new keymaps as necessary. */
+  for (i = 0; i < keys_len; i++)
+    {
+      if (i + 1 < keys_len)
+       {
+         if (map[keys[i]].type != ISKMAP)
+           {
+             if (map[i].type == ISMACR)
+               free ((char *)map[i].function);
+
+             map[keys[i]].type = ISKMAP;
+             map[keys[i]].function = (Function *)rl_make_bare_keymap ();
+           }
+         map = (Keymap)map[keys[i]].function;
+       }
+      else
+       {
+         if (map[keys[i]].type == ISMACR)
+           free ((char *)map[keys[i]].function);
+
+         map[keys[i]].function = (Function *)data;
+         map[keys[i]].type = type;
+       }
+    }
+}
+
+/* Translate the ASCII representation of SEQ, stuffing the
+   values into ARRAY, an array of characters.  LEN gets the
+   final length of ARRAY.  Return non-zero if there was an
+   error parsing SEQ. */
+rl_translate_keyseq (seq, array, len)
+     char *seq, *array;
+     int *len;
+{
+  register int i, c, l = 0;
+
+  for (i = 0; c = seq[i]; i++)
+    {
+      if (c == '\\')
+       {
+         c = seq[++i];
+
+         if (!c)
+           break;
+
+         if (((c == 'C' || c == 'M') &&  seq[i + 1] == '-') ||
+             (c == 'e'))
+           {
+             /* Handle special case of backwards define. */
+             if (strncmp (&seq[i], "C-\\M-", 5) == 0)
+               {
+                 array[l++] = ESC;
+                 i += 5;
+                 array[l++] = CTRL (to_upper (seq[i]));
+                 if (!seq[i])
+                   i--;
+                 continue;
+               }
+
+             switch (c)
+               {
+               case 'M':
+                 i++;
+                 array[l++] = ESC;
+                 break;
+
+               case 'C':
+                 i += 2;
+                 array[l++] = CTRL (to_upper (seq[i]));
+                 break;
+
+               case 'e':
+                 array[l++] = ESC;
+               }
+
+             continue;
+           }
+       }
+      array[l++] = c;
+    }
+
+  *len = l;
+  array[l] = '\0';
+  return (0);
+}
+
+/* Return a pointer to the function that STRING represents.
+   If STRING doesn't have a matching function, then a NULL pointer
+   is returned. */
+Function *
+rl_named_function (string)
+     char *string;
+{
+  register int i;
+
+  for (i = 0; funmap[i]; i++)
+    if (stricmp (funmap[i]->name, string) == 0)
+      return (funmap[i]->function);
+  return ((Function *)NULL);
+}
+
+/* The last key bindings file read. */
+static char *last_readline_init_file = "~/.inputrc";
+
+/* Re-read the current keybindings file. */
+rl_re_read_init_file (count, ignore)
+     int count, ignore;
+{
+  rl_read_init_file (last_readline_init_file);
+}
+
+/* Do key bindings from a file.  If FILENAME is NULL it defaults
+   to `~/.inputrc'.  If the file existed and could be opened and
+   read, 0 is returned, otherwise errno is returned. */
+int
+rl_read_init_file (filename)
+     char *filename;
+{
+  extern int errno;
+  int line_size, line_index;
+  char *line = (char *)xmalloc (line_size = 100);
+  char *openname;
+  FILE *file;
+
+  int c;
+
+  /* Default the filename. */
+  if (!filename)
+    filename = "~/.inputrc";
+
+  openname = tilde_expand (filename);
+
+  /* Open the file. */
+  file = fopen (openname, "r");
+  free (openname);
+
+  if (!file)
+    return (errno);
+
+  last_readline_init_file = filename;
+
+  /* Loop reading lines from the file.  Lines that start with `#' are
+     comments, all other lines are commands for readline initialization. */
+  while ((c = rl_getc (file)) != EOF)
+    {
+      /* If comment, flush to EOL. */
+      if (c == '#')
+       {
+         while ((c = rl_getc (file)) != EOF && c != '\n');
+         if (c == EOF)
+           goto function_exit;
+         continue;
+       }
+
+      /* Otherwise, this is the start of a line.  Read the
+        line from the file. */
+      line_index = 0;
+      while (c != EOF && c != '\n')
+       {
+         line[line_index++] = c;
+         if (line_index == line_size)
+           line = (char *)xrealloc (line, line_size += 100);
+         c = rl_getc (file);
+       }
+      line[line_index] = '\0';
+
+      /* Parse the line. */
+      rl_parse_and_bind (line);
+    }
+
+function_exit:
+
+  free (line);
+  /* Close up the file and exit. */
+  fclose (file);
+  return (0);
+}
+
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Parser Directives                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Conditionals. */
+
+/* Calling programs set this to have their argv[0]. */
+char *rl_readline_name = "other";
+
+/* Stack of previous values of parsing_conditionalized_out. */
+static unsigned char *if_stack = (unsigned char *)NULL;
+static int if_stack_depth = 0;
+static int if_stack_size = 0;
+
+/* Push parsing_conditionalized_out, and set parser state based on ARGS. */
+parser_if (args)
+     char *args;
+{
+  register int i;
+
+  /* Push parser state. */
+  if (if_stack_depth + 1 >= if_stack_size)
+    {
+      if (!if_stack)
+       if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
+      else
+       if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
+    }
+  if_stack[if_stack_depth++] = parsing_conditionalized_out;
+
+  /* We only check to see if the first word in ARGS is the same as the
+     value stored in rl_readline_name. */
+
+  /* Isolate first argument. */
+  for (i = 0; args[i] && !whitespace (args[i]); i++);
+
+  if (args[i])
+    args[i++] = '\0';
+
+  if (stricmp (args, rl_readline_name) == 0)
+    parsing_conditionalized_out = 0;
+  else
+    parsing_conditionalized_out = 1;
+}
+
+/* Invert the current parser state if there is anything on the stack. */
+parser_else (args)
+     char *args;
+{
+  if (if_stack_depth)
+    parsing_conditionalized_out = !parsing_conditionalized_out;
+  else
+    {
+      /* *** What, no error message? *** */
+    }
+}
+
+/* Terminate a conditional, popping the value of
+   parsing_conditionalized_out from the stack. */
+parser_endif (args)
+     char *args;
+{
+  if (if_stack_depth)
+    parsing_conditionalized_out = if_stack[--if_stack_depth];
+  else
+    {
+      /* *** What, no error message? *** */
+    }
+}
+
+/* Associate textual names with actual functions. */
+static struct {
+  char *name;
+  Function *function;
+} parser_directives [] = {
+  { "if", parser_if },
+  { "endif", parser_endif },
+  { "else", parser_else },
+  { (char *)0x0, (Function *)0x0 }
+};
+
+/* Handle a parser directive.  STATEMENT is the line of the directive
+   without any leading `$'. */
+static int
+handle_parser_directive (statement)
+     char *statement;
+{
+  register int i;
+  char *directive, *args;
+
+  /* Isolate the actual directive. */
+
+  /* Skip whitespace. */
+  for (i = 0; whitespace (statement[i]); i++);
+
+  directive = &statement[i];
+
+  for (; statement[i] && !whitespace (statement[i]); i++);
+
+  if (statement[i])
+    statement[i++] = '\0';
+
+  for (; statement[i] && whitespace (statement[i]); i++);
+
+  args = &statement[i];
+
+  /* Lookup the command, and act on it. */
+  for (i = 0; parser_directives[i].name; i++)
+    if (stricmp (directive, parser_directives[i].name) == 0)
+      {
+       (*parser_directives[i].function) (args);
+       return (0);
+      }
+
+  /* *** Should an error message be output? */
+  return (1);
+}
+
+/* Read the binding command from STRING and perform it.
+   A key binding command looks like: Keyname: function-name\0,
+   a variable binding command looks like: set variable value.
+   A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
+rl_parse_and_bind (string)
+     char *string;
+{
+  extern char *possible_control_prefixes[], *possible_meta_prefixes[];
+  char *rindex (), *funname, *kname;
+  static int substring_member_of_array ();
+  register int c;
+  int key, i;
+
+  if (!string || !*string || *string == '#')
+    return;
+
+  /* If this is a parser directive, act on it. */
+  if (*string == '$')
+    {
+      handle_parser_directive (&string[1]);
+      return;
+    }
+
+  /* If we are supposed to be skipping parsing right now, then do it. */
+  if (parsing_conditionalized_out)
+    return;
+
+  i = 0;
+  /* If this keyname is a complex key expression surrounded by quotes,
+     advance to after the matching close quote. */
+  if (*string == '"')
+    {
+      for (i = 1; c = string[i]; i++)
+       {
+         if (c == '"' && string[i - 1] != '\\')
+           break;
+       }
+    }
+
+  /* Advance to the colon (:) or whitespace which separates the two objects. */
+  for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
+
+  /* Mark the end of the command (or keyname). */
+  if (string[i])
+    string[i++] = '\0';
+
+  /* If this is a command to set a variable, then do that. */
+  if (stricmp (string, "set") == 0)
+    {
+      char *var = string + i;
+      char *value;
+
+      /* Make VAR point to start of variable name. */
+      while (*var && whitespace (*var)) var++;
+
+      /* Make value point to start of value string. */
+      value = var;
+      while (*value && !whitespace (*value)) value++;
+      if (*value)
+       *value++ = '\0';
+      while (*value && whitespace (*value)) value++;
+
+      rl_variable_bind (var, value);
+      return;
+    }
+
+  /* Skip any whitespace between keyname and funname. */
+  for (; string[i] && whitespace (string[i]); i++);
+  funname = &string[i];
+
+  /* Now isolate funname.
+     For straight function names just look for whitespace, since
+     that will signify the end of the string.  But this could be a
+     macro definition.  In that case, the string is quoted, so skip
+     to the matching delimiter. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      int delimiter = string[i++];
+
+      for (; c = string[i]; i++)
+       {
+         if (c == delimiter && string[i - 1] != '\\')
+           break;
+       }
+      if (c)
+       i++;
+    }
+
+  /* Advance to the end of the string.  */
+  for (; string[i] && !whitespace (string[i]); i++);
+
+  /* No extra whitespace at the end of the string. */
+  string[i] = '\0';
+
+  /* If this is a new-style key-binding, then do the binding with
+     rl_set_key ().  Otherwise, let the older code deal with it. */
+  if (*string == '"')
+    {
+      char *seq = (char *)alloca (1 + strlen (string));
+      register int j, k = 0;
+
+      for (j = 1; string[j]; j++)
+       {
+         if (string[j] == '"' && string[j - 1] != '\\')
+           break;
+
+         seq[k++] = string[j];
+       }
+      seq[k] = '\0';
+
+      /* Binding macro? */
+      if (*funname == '\'' || *funname == '"')
+       {
+         j = strlen (funname);
+
+         if (j && funname[j - 1] == *funname)
+           funname[j - 1] = '\0';
+
+         rl_macro_bind (seq, &funname[1], keymap);
+       }
+      else
+       rl_set_key (seq, rl_named_function (funname), keymap);
+
+      return;
+    }
+
+  /* Get the actual character we want to deal with. */
+  kname = rindex (string, '-');
+  if (!kname)
+    kname = string;
+  else
+    kname++;
+
+  key = glean_key_from_name (kname);
+
+  /* Add in control and meta bits. */
+  if (substring_member_of_array (string, possible_control_prefixes))
+    key = CTRL (to_upper (key));
+
+  if (substring_member_of_array (string, possible_meta_prefixes))
+    key = META (key);
+
+  /* Temporary.  Handle old-style keyname with macro-binding. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      char seq[2];
+      int fl = strlen (funname);
+
+      seq[0] = key; seq[1] = '\0';
+      if (fl && funname[fl - 1] == *funname)
+       funname[fl - 1] = '\0';
+
+      rl_macro_bind (seq, &funname[1], keymap);
+    }
+  else
+    rl_bind_key (key, rl_named_function (funname));
+}
+
+rl_variable_bind (name, value)
+     char *name, *value;
+{
+  if (stricmp (name, "editing-mode") == 0)
+    {
+      if (strnicmp (value, "vi", 2) == 0)
+       {
+#ifdef VI_MODE
+         keymap = vi_insertion_keymap;
+         rl_editing_mode = vi_mode;
+#endif /* VI_MODE */
+       }
+      else if (strnicmp (value, "emacs", 5) == 0)
+       {
+         keymap = emacs_standard_keymap;
+         rl_editing_mode = emacs_mode;
+       }
+    }
+  else if (stricmp (name, "horizontal-scroll-mode") == 0)
+    {
+      if (!*value || stricmp (value, "On") == 0)
+       horizontal_scroll_mode = 1;
+      else
+       horizontal_scroll_mode = 0;
+    }
+  else if (stricmp (name, "mark-modified-lines") == 0)
+    {
+      if (!*value || stricmp (value, "On") == 0)
+       mark_modified_lines = 1;
+      else
+       mark_modified_lines = 0;
+    }
+}
+
+/* Return the character which matches NAME.
+   For example, `Space' returns ' '. */
+
+typedef struct {
+  char *name;
+  int value;
+} assoc_list;
+
+assoc_list name_key_alist[] = {
+  { "Space", ' ' },
+  { "SPC", ' ' },
+  { "Rubout", 0x7f },
+  { "DEL", 0x7f },
+  { "Tab", 0x09 },
+  { "Newline", '\n' },
+  { "Return", '\r' },
+  { "RET", '\r' },
+  { "LFD", '\n' },
+  { "Escape", '\033' },
+  { "ESC", '\033' },
+
+  { (char *)0x0, 0 }
+};
+
+int
+glean_key_from_name (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; name_key_alist[i].name; i++)
+    if (stricmp (name, name_key_alist[i].name) == 0)
+      return (name_key_alist[i].value);
+
+  return (*name);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     String Utility Functions                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return non-zero if any members of ARRAY are a substring in STRING. */
+static int
+substring_member_of_array (string, array)
+     char *string, **array;
+{
+  static char *strindex ();
+
+  while (*array)
+    {
+      if (strindex (string, *array))
+       return (1);
+      array++;
+    }
+  return (0);
+}
+
+/* Whoops, Unix doesn't have strnicmp. */
+
+/* Compare at most COUNT characters from string1 to string2.  Case
+   doesn't matter. */
+static int
+strnicmp (string1, string2, count)
+     char *string1, *string2;
+{
+  register char ch1, ch2;
+
+  while (count)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) == to_upper(ch2))
+       count--;
+      else break;
+    }
+  return (count);
+}
+
+/* strcmp (), but caseless. */
+static int
+stricmp (string1, string2)
+     char *string1, *string2;
+{
+  register char ch1, ch2;
+
+  while (*string1 && *string2)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) != to_upper(ch2))
+       return (1);
+    }
+  return (*string1 | *string2);
+}
+
+/* Determine if s2 occurs in s1.  If so, return a pointer to the
+   match in s1.  The compare is case insensitive. */
+static char *
+strindex (s1, s2)
+     register char *s1, *s2;
+{
+  register int i, l = strlen (s2);
+  register int len = strlen (s1);
+
+  for (i = 0; (len - i) >= l; i++)
+    if (strnicmp (&s1[i], s2, l) == 0)
+      return (s1 + i);
+  return ((char *)NULL);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     SYSV Support                                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Since system V reads input differently than we do, I have to
+   make a special version of getc for that. */
+
+#ifdef SYSV
+
+extern int errno;
+#include <sys/errno.h>
+
+int
+rl_getc (stream)
+     FILE *stream;
+{
+  int result;
+  unsigned char c;
+
+  while (1)
+    {
+      result = read (fileno (stream), &c, sizeof (char));
+      if (result == sizeof (char))
+       return (c);
+
+      if (errno != EINTR)
+       return (EOF);
+    }
+}
+#else
+int
+rl_getc (stream)
+     FILE *stream;
+{
+  return (getc (stream));
+}
+#endif
+
+#ifdef STATIC_MALLOC
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Testing Readline                            */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef TEST
+
+main ()
+{
+  HIST_ENTRY **history_list ();
+  char *temp = (char *)NULL;
+  char *prompt = "readline% ";
+  int done = 0;
+
+  while (!done)
+    {
+      temp = readline (prompt);
+
+      /* Test for EOF. */
+      if (!temp)
+       exit (1);
+
+      /* If there is anything on the line, print it and remember it. */
+      if (*temp)
+       {
+         fprintf (stderr, "%s\r\n", temp);
+         add_history (temp);
+       }
+
+      /* Check for `command' that we handle. */
+      if (strcmp (temp, "quit") == 0)
+       done = 1;
+
+      if (strcmp (temp, "list") == 0) {
+       HIST_ENTRY **list = history_list ();
+       register int i;
+       if (list) {
+         for (i = 0; list[i]; i++) {
+           fprintf (stderr, "%d: %s\r\n", i, list[i]->line);
+           free (list[i]->line);
+         }
+         free (list);
+       }
+      }
+      free (temp);
+    }
+}
+
+#endif /* TEST */
+
+\f
+/*
+ * Local variables:
+ * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap"
+ * end:
+ */
diff --git a/readline/readline.h b/readline/readline.h
new file mode 100644 (file)
index 0000000..3e62976
--- /dev/null
@@ -0,0 +1,170 @@
+/* Readline.h -- the names of functions callable from within readline. */
+
+#ifndef _READLINE_H_
+#define _READLINE_H_
+
+#include <readline/keymaps.h>
+
+#ifndef __FUNCTION_DEF
+typedef int Function ();
+#define __FUNCTION_DEF
+#endif
+
+/* The functions for manipulating the text of the line within readline.
+Most of these functions are bound to keys by default. */
+extern int
+rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (),
+rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (),
+rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (),
+rl_quoted_insert (), rl_reverse_search_history (), rl_transpose_chars
+(), rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout
+(), rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (),
+rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
+rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words
+(), rl_complete (), rl_possible_completions (), rl_do_lowercase_version
+(), rl_digit_argument (), rl_universal_argument (), rl_abort (),
+rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
+rl_end_of_history (), rl_forward_search_history (), rl_insert (),
+rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (),
+rl_restart_output (), rl_re_read_init_file ();
+
+/* These are *both* defined even when VI_MODE is not. */
+extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
+
+#ifdef VI_MODE
+/* Things for vi mode. */
+extern int rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
+rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (),
+rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
+rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
+rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
+rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
+rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (), rl_vi_change_char (),
+rl_vi_yank_arg (), rl_vi_search (), rl_vi_search_again (),
+rl_vi_dosearch (), rl_vi_subst (), rl_vi_overstrike (),
+rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (),
+rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (), rl_vi_complete ();
+#endif /* VI_MODE */
+
+/* Keyboard macro commands. */
+extern int
+rl_start_kbd_macro (), rl_end_kbd_macro (), rl_call_last_kbd_macro ();
+
+/* Maintaining the state of undo.  We remember individual deletes and inserts
+   on a chain of things to do. */
+
+/* The actions that undo knows how to undo.  Notice that UNDO_DELETE means
+   to insert some text, and UNDO_INSERT means to delete some text.   I.e.,
+   the code tells undo what to undo, not how to undo it. */
+enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
+
+/* What an element of THE_UNDO_LIST looks like. */
+typedef struct undo_list {
+  struct undo_list *next;
+  int start, end;              /* Where the change took place. */
+  char *text;                  /* The text to insert, if undoing a delete. */
+  enum undo_code what;         /* Delete, Insert, Begin, End. */
+} UNDO_LIST;
+
+/* The current undo list for RL_LINE_BUFFER. */
+extern UNDO_LIST *rl_undo_list;
+
+/* The data structure for mapping textual names to code addresses. */
+typedef struct {
+  char *name;
+  Function *function;
+} FUNMAP;
+
+extern FUNMAP **funmap;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Well Published Variables                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The name of the calling program.  You should initialize this to
+   whatever was in argv[0].  It is used when parsing conditionals. */
+extern char *rl_readline_name;
+
+/* The line buffer that is in use. */
+extern char *rl_line_buffer;
+
+/* The location of point, and end. */
+extern int rl_point, rl_end;
+
+/* The name of the terminal to use. */
+extern char *rl_terminal_name;
+
+/* The input and output streams. */
+extern FILE *rl_instream, *rl_outstream;
+
+/* The basic list of characters that signal a break between words for the
+   completer routine.  The contents of this variable is what breaks words
+   in the shell, i.e. "n\"\\'`@$>". */
+extern char *rl_basic_word_break_characters;
+
+/* The list of characters that signal a break between words for
+   rl_complete_internal.  The default list is the contents of
+   rl_basic_word_break_characters.  */
+extern char *rl_completer_word_break_characters;
+
+/* List of characters that are word break characters, but should be left
+   in TEXT when it is passed to the completion function.  The shell uses
+   this to help determine what kind of completing to do. */
+extern char *rl_special_prefixes;
+
+/* Pointer to the generator function for completion_matches ().
+   NULL means to use filename_entry_function (), the default filename
+   completer. */
+extern Function *rl_completion_entry_function;
+
+/* Pointer to alternative function to create matches.
+   Function is called with TEXT, START, and END.
+   START and END are indices in RL_LINE_BUFFER saying what the boundaries
+   of TEXT are.
+   If this function exists and returns NULL then call the value of
+   rl_completion_entry_function to try to match, otherwise use the
+   array of strings returned. */
+extern Function *rl_attempted_completion_function;
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+extern Function *rl_tilde_expander;
+
+/* If non-zero, then this is the address of a function to call just
+   before readline_internal () prints the first prompt. */
+extern Function *rl_startup_hook;
+
+/* If non-zero, then this is the address of a function to call when
+   completing on a directory name.  The function is called with
+   the address of a string (the current directory name) as an arg. */
+extern Function *rl_symbolic_link_hook;
+
+/* Non-zero means that modified history lines are preceded
+   with an asterisk. */
+extern int rl_show_star;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Well Published Functions                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means none. */
+extern char *readline ();
+
+/* Return an array of strings which are the result of repeatadly calling
+   FUNC with TEXT. */
+extern char **completion_matches ();
+
+/* rl_add_defun (char *name, Function *function, int key)
+   Add NAME to the list of named functions.  Make FUNCTION
+   be the function that gets called.
+   If KEY is not -1, then bind it. */
+extern int rl_add_defun ();
+
+#endif /* _READLINE_H_ */
+
diff --git a/readline/readline.texinfo b/readline/readline.texinfo
new file mode 100755 (executable)
index 0000000..36fe7a9
--- /dev/null
@@ -0,0 +1,434 @@
+\input texinfo    @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename readline.info
+@settitle Line Editing Commands
+@comment %**end of header (This is for running Texinfo on a region.)
+@synindex fn vr
+
+@iftex
+@comment finalout
+@end iftex
+
+@ifinfo
+This document describes the GNU Readline Library, a utility for aiding
+in the consitency of user interface across discrete programs that need
+to provide a command line interface.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare 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 Foundation.
+@end ifinfo
+
+@setchapternewpage odd
+@titlepage
+@sp 11
+@center @titlefont{GNU Readline Library}
+@sp 2
+@center by Brian Fox
+@sp 2
+@center Version 1.0
+@sp 2
+@center February 1989
+
+@comment   Include the Distribution inside the titlepage environment so
+@c that headings are turned off. 
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989 Free Software Foundation, Inc.
+
+@sp 2
+This document describes the GNU Readline Library, a utility for aiding
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+@sp 2
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+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 Foundation.
+
+@end titlepage
+
+@node Top, Readline Top, ,(DIR)
+@chapter GNU Readline Library
+
+@ifinfo
+This document describes the GNU Readline Library, a utility for aiding
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+@end ifinfo
+
+@menu
+* Readline Top::       GNU Readline User's Manual
+* Readline Technical:: GNU Readline Programmer's Manual
+@end menu
+@include inc-readline.texinfo
+@node Readline Technical, , Top, Top
+@chapter Readline Programmer's Manual
+
+This manual describes the interface between the GNU Readline Library and
+user programs.  If you are a programmer, and you wish to include the
+features found in GNU Readline in your own programs, such as completion,
+line editing, and interactive history manipulation, this documentation
+is for you.
+
+@menu
+* Default Behaviour::  Using the default behaviour of Readline.
+* Custom Functions::   Adding your own functions to Readline.
+* Custom Completers::  Supplanting or supplementing Readline's
+                       completion functions.
+* Variable Index::     Index of externally tweakable variables.
+@end menu
+
+@node Default Behaviour, Custom Functions, Readline Technical, Readline Technical
+@section Default Behaviour
+
+Many programs provide a command line interface, such as @code{mail},
+@code{ftp}, and @code{sh}.  For such programs, the default behaviour of
+Readline is sufficient.  This section describes how to use Readline in
+the simplest way possible, perhaps to replace calls in your code to
+@code{gets ()}.
+
+@findex readline ()
+@cindex readline, function
+The function @code{readline} prints a prompt and then reads and returns
+a single line of text from the user.  The line which @code{readline ()}
+returns is allocated with @code{malloc ()}; you should @code{free ()}
+the line when you are done with it.  The declaration in ANSI C is
+
+@example
+@code{char *readline (char *@var{prompt});}
+@end example
+or, preferably,
+@example
+@code{#include <readline/readline.h>}
+@end example
+
+So, one might say
+@example
+@code{char *line = readline ("Enter a line: ");}
+@end example
+in order to read a line of text from the user.
+
+The line which is returned has the final newline removed, so only the
+text of the line remains.
+
+If readline encounters an EOF while reading the line, and the line is
+empty at that point, then @code{(char *)NULL} is returned.  Otherwise,
+the line is ended just as if a newline was typed.
+
+If you want the user to be able to get at the line later, (with
+@key{C-p} for example), you must call @code{add_history ()} to save the
+line away in a @dfn{history} list of such lines.
+
+@example
+@code{add_history (line)};
+@end example
+
+If you use @code{add_history ()}, you should also
+@code{#include <readline/history.h>}
+For full details on the GNU History Library, see the associated manual.
+
+It is polite to avoid saving empty lines on the history list, since
+no one has a burning need to reuse a blank line.  Here is a function
+which usefully replaces the standard @code{gets ()} library function:
+
+@example
+#include <readline/readline.h>
+#include <readline/history.h>
+
+/* A static variable for holding the line. */
+static char *my_gets_line = (char *)NULL;
+
+/* Read a string, and return a pointer to it.  Returns NULL on EOF. */
+char *
+my_gets ()
+@{
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (my_gets_line != (char *)NULL)
+    free (my_gets_line);
+
+  /* Get a line from the user. */
+  my_gets_line = readline ("");
+
+  /* If the line has any text in it, save it on the history. */
+  if (my_get_line && *my_gets_line)
+    add_history (my_gets_line);
+
+  return (my_gets_line);
+@}
+@end example
+
+The above code gives the user the default behaviour of @key{TAB}
+completion: completion on file names.  If you do not want readline to
+complete on filenames, you can change the binding of the @key{TAB} key
+with @code{rl_bind_key ()}.
+
+@findex rl_bind_key ()
+
+@example
+@code{int rl_bind_key (int @var{key}, (int (*)())@var{function});}
+@end example
+
+@code{rl_bind_key ()} takes 2 arguments; @var{key} is the character that
+you want to bind, and @var{function} is the address of the function to
+run when @var{key} is pressed.  Binding @key{TAB} to @code{rl_insert ()}
+makes @key{TAB} just insert itself.
+
+@code{rl_bind_key ()} returns non-zero if @var{key} is not a valid
+ASCII character code (between 0 and 255).
+
+@example
+@code{rl_bind_key ('\t', rl_insert);}
+@end example
+
+@node Custom Functions, Custom Completers, Default Behaviour, Readline Technical
+@section Custom Functions
+
+Readline provides a great many functions for manipulating the text of
+the line.  But it isn't possible to anticipate the needs of all
+programs.  This section describes the various functions and variables
+defined in within the Readline library which allow a user program to add
+customized functionality to Readline.
+
+@menu
+* The Function Type::  C declarations to make code readable.
+* Function Naming::    How to give a function you write a name.
+* Keymaps::            Making keymaps.
+* Binding Keys::       Changing Keymaps.
+* Function Writing::   Variables and calling conventions.
+* Allowing Undoing::   How to make your functions undoable.
+@end menu
+
+@node The Function Type, Function Naming, Custom Functions, Custom Functions
+For the sake of readabilty, we declare a new type of object, called
+@dfn{Function}.  `Function' is a C language function which returns an
+@code{int}.  The type declaration for `Function' is:
+
+@code{typedef int Function ();}
+
+The reason for declaring this new type is to make it easier to discuss
+pointers to C functions.  Let us say we had a variable called @var{func}
+which was a pointer to a function.  Instead of the classic C declaration
+
+@code{int (*)()func;}
+
+we have
+
+@code{Function *func;}
+
+@node Function Naming, Keymaps, The Function Type, Custom Functions
+@subsection Naming a Function
+
+The user can dynamically change the bindings of keys while using
+Readline.  This is done by representing the function with a descriptive
+name.  The user is able to type the descriptive name when referring to
+the function.  Thus, in an init file, one might find
+
+@example
+Meta-Rubout:   backward-kill-word
+@end example
+
+This binds @key{Meta-Rubout} to the function @emph{descriptively} named
+@code{backward-kill-word}.  You, as a programmer, should bind the
+functions you write to descriptive names as well.  Here is how to do
+that.
+
+@defun rl_add_defun (char *name, Function *function, int key)
+Add @var{name} to the list of named functions.  Make @var{function} be
+the function that gets called.  If @var{key} is not -1, then bind it to
+@var{function} using @code{rl_bind_key ()}.
+@end defun
+
+Using this function alone is sufficient for most applications.  It is
+the recommended way to add a few functions to the default functions that
+Readline has built in already.  If you need to do more or different
+things than adding a function to Readline, you may need to use the
+underlying functions described below.
+
+@node Keymaps, Binding Keys, Function Naming, Custom Functions
+@subsection Selecting a Keymap
+
+Key bindings take place on a @dfn{keymap}.  The keymap is the
+association between the keys that the user types and the functions that
+get run.  You can make your own keymaps, copy existing keymaps, and tell
+Readline which keymap to use.
+
+@defun rl_make_bare_keymap ()
+Returns a new, empty keymap.  The space for the keymap is allocated with
+@code{malloc ()}; you should @code{free ()} it when you are done.
+@end defun
+
+@defun rl_copy_keymap (Keymap map)
+Return a new keymap which is a copy of @var{map}.
+@end defun
+
+@defun rl_make_keymap ()
+Return a new keymap with the printing characters bound to rl_insert,
+the lowercase Meta characters bound to run their equivalents, and
+the Meta digits bound to produce numeric arguments.
+@end defun
+
+@node Binding Keys, Function Writing, Keymaps, Custom Functions
+@subsection Binding Keys
+
+You associate keys with functions through the keymap.  Here are
+the functions for doing that.
+
+@defun rl_bind_key (int key, Function *function)
+Binds @var{key} to @var{function} in the currently selected keymap.
+Returns non-zero in the case of an invalid @var{key}.
+@end defun
+
+@defun rl_bind_key_in_map (int key, Function *function, Keymap map)
+Bind @var{key} to @var{function} in @var{map}.  Returns non-zero in the case
+of an invalid @var{key}.
+@end defun
+
+@defun rl_unbind_key (int key)
+Make @var{key} do nothing in the currently selected keymap.
+Returns non-zero in case of error.
+@end defun
+
+@defun rl_unbind_key_in_map (int key, Keymap map)
+Make @var{key} be bound to the null function in @var{map}.
+Returns non-zero in case of error.
+@end defun
+
+@node Function Writing, Allowing Undoing, Binding Keys, Custom Functions
+@subsection Writing a New Function
+
+In order to write new functions for Readline, you need to know the
+calling conventions for keyboard invoked functions, and the names of the
+variables that describe the current state of the line gathered so far.
+
+@defvar char *rl_line_buffer
+This is the line gathered so far.  You are welcome to modify the
+contents of this, but see Undoing, below.
+@end defvar
+
+@defvar int rl_point
+The offset of the current cursor position in @var{rl_line_buffer}.
+@end defvar
+
+@defvar int rl_end
+The number of characters present in @code{rl_line_buffer}.  When
+@code{rl_point} is at the end of the line, then @code{rl_point} and
+@code{rl_end} are equal.
+@end defvar
+
+The calling sequence for a command @code{foo} looks like
+
+@example
+@code{foo (count, key)}
+@end example
+
+where @var{count} is the numeric argument (or 1 if defaulted) and
+@var{key} is the key that invoked this function.
+
+It is completely up to the function as to what should be done with the
+numeric argument; some functions use it as a repeat count, other
+functions as a flag, and some choose to ignore it.  In general, if a
+function uses the numeric argument as a repeat count, it should be able
+to do something useful with a negative argument as well as a positive
+argument.  At the very least, it should be aware that it can be passed a
+negative argument.
+
+@node Allowing Undoing, , Function Writing, Custom Functions
+@subsection Allowing Undoing
+
+Supporting the undo command is a painless thing to do, and makes your
+function much more useful to the end user.  It is certainly easy to try
+something if you know you can undo it.  I could use an undo function for
+the stock market.
+
+If your function simply inserts text once, or deletes text once, and it
+calls @code{rl_insert_text ()} or @code{rl_delete_text ()} to do it, then
+undoing is already done for you automatically, and you can safely skip
+this section.
+
+If you do multiple insertions or multiple deletions, or any combination
+of these operations, you will want to group them together into one
+operation.  This can be done with @code{rl_begin_undo_group ()} and 
+@code{rl_end_undo_group ()}.
+
+@defun rl_begin_undo_group ()
+Begins saving undo information in a group construct.  The undo
+information usually comes from calls to @code{rl_insert_text ()} and
+@code{rl_delete_text ()}, but they could be direct calls to
+@code{rl_add_undo ()}.
+@end defun
+
+@defun rl_end_undo_group ()
+Closes the current undo group started with @code{rl_begin_undo_group
+()}.  There should be exactly one call to @code{rl_end_undo_group ()}
+for every call to @code{rl_begin_undo_group ()}.
+@end defun
+
+Finally, if you neither insert nor delete text, but directly modify the
+existing text (e.g. change its case), you call @code{rl_modifying ()}
+once, just before you modify the text.  You must supply the indices of
+the text range that you are going to modify.
+
+@defun rl_modifying (int start, int end)
+Tell Readline to save the text between @var{start} and @var{end} as a
+single undo unit.  It is assumed that subsequent to this call you will
+modify that range of text in some way.
+@end defun
+
+@subsection An Example
+
+Let us say that we are actually going to put an example here.
+
+@node Custom Completers, Variable Index, Custom Functions, Readline Technical
+
+Typically, a program that reads commands from the user has a way of
+disambiguating between commands and data.  If your program is one of
+these, then it can provide completion for either commands, or data, or
+both commands and data.  The following sections describe how your
+program and Readline cooperate to provide this service to end users.
+
+@menu
+@end menu
+
+@node Variable Index, , Custom Completers, Readline Technical
+@appendix Variable Index
+@printindex vr
+@contents
+
+@bye
+
diff --git a/readline/vi_keymap.c b/readline/vi_keymap.c
new file mode 100644 (file)
index 0000000..81fbb9b
--- /dev/null
@@ -0,0 +1,474 @@
+/* vi_keymap.c -- the keymap for vi_mode in readline (). */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline 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 1, or (at your option) any
+   later version.
+
+   Readline 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 Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef FILE
+#include <stdio.h>
+#endif /* FILE */
+
+#include "readline.h"
+
+extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
+
+/* The keymap arrays for handling vi mode. */
+KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
+
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, (Function *)0x0 },         /* Control-a */
+  { ISFUNC, (Function *)0x0 },         /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, rl_vi_eof_maybe },         /* Control-d */
+  { ISFUNC, rl_emacs_editing_mode },   /* Control-e */
+  { ISFUNC, (Function *)0x0 },         /* Control-f */
+  { ISFUNC, rl_abort },                        /* Control-g */
+  { ISFUNC, rl_backward },             /* Control-h */
+  { ISFUNC, (Function *)0x0 },         /* Control-i */
+  { ISFUNC, rl_newline },              /* Control-j */
+  { ISFUNC, rl_kill_line },            /* Control-k */
+  { ISFUNC, rl_clear_screen },         /* Control-l */
+  { ISFUNC, rl_newline },              /* Control-m */
+  { ISFUNC, rl_get_next_history },     /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, rl_get_previous_history }, /* Control-p */
+  { ISFUNC, rl_quoted_insert },                /* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },      /* Control-t */
+  { ISFUNC, rl_unix_line_discard },    /* Control-u */
+  { ISFUNC, rl_quoted_insert },                /* Control-v */
+  { ISFUNC, rl_unix_word_rubout },     /* Control-w */
+  { ISFUNC, (Function *)0x0 },         /* Control-x */
+  { ISFUNC, rl_yank },                 /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+
+  { ISKMAP, (Function *)vi_escape_keymap }, /* Control-[ */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_forward },              /* SPACE */
+  { ISFUNC, (Function *)0x0 },         /* ! */
+  { ISFUNC, (Function *)0x0 },         /* " */
+  { ISFUNC, rl_vi_comment },           /* # */
+  { ISFUNC, rl_end_of_line },          /* $ */
+  { ISFUNC, rl_vi_match },             /* % */
+  { ISFUNC, (Function *)0x0 },         /* & */
+  { ISFUNC, (Function *)0x0 },         /* ' */
+  { ISFUNC, (Function *)0x0 },         /* ( */
+  { ISFUNC, (Function *)0x0 },         /* ) */
+  { ISFUNC, rl_vi_complete },          /* * */
+  { ISFUNC, rl_get_next_history},      /* + */
+  { ISFUNC, rl_vi_char_search },       /* , */
+  { ISFUNC, rl_get_previous_history }, /* - */
+  { ISFUNC, (Function *)0x0 },         /* . */
+  { ISFUNC, rl_vi_search },            /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_vi_arg_digit },         /* 0 */
+  { ISFUNC, rl_vi_arg_digit },         /* 1 */
+  { ISFUNC, rl_vi_arg_digit },         /* 2 */
+  { ISFUNC, rl_vi_arg_digit },         /* 3 */
+  { ISFUNC, rl_vi_arg_digit },         /* 4 */
+  { ISFUNC, rl_vi_arg_digit },         /* 5 */
+  { ISFUNC, rl_vi_arg_digit },         /* 6 */
+  { ISFUNC, rl_vi_arg_digit },         /* 7 */
+  { ISFUNC, rl_vi_arg_digit },         /* 8 */
+  { ISFUNC, rl_vi_arg_digit },         /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* : */
+  { ISFUNC, rl_vi_char_search },       /* ; */
+  { ISFUNC, (Function *)0x0 },         /* < */
+  { ISFUNC, (Function *)0x0 },         /* = */
+  { ISFUNC, (Function *)0x0 },         /* > */
+  { ISFUNC, rl_vi_search },            /* ? */
+  { ISFUNC, (Function *)0x0 },         /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_vi_append_eol },                /* A */
+  { ISFUNC, rl_vi_prev_word},          /* B */
+  { ISFUNC, rl_vi_change_to },         /* C */
+  { ISFUNC, rl_vi_delete_to },         /* D */
+  { ISFUNC, rl_vi_end_word },          /* E */
+  { ISFUNC, rl_vi_char_search },       /* F */
+  { ISFUNC, (Function *)0x0 },         /* G */
+  { ISFUNC, (Function *)0x0 },         /* H */
+  { ISFUNC, rl_vi_insert_beg },                /* I */
+  { ISFUNC, (Function *)0x0 },         /* J */
+  { ISFUNC, (Function *)0x0 },         /* K */
+  { ISFUNC, (Function *)0x0 },         /* L */
+  { ISFUNC, (Function *)0x0 },         /* M */
+  { ISFUNC, rl_vi_search_again },      /* N */
+  { ISFUNC, (Function *)0x0 },         /* O */
+  { ISFUNC, rl_vi_put },               /* P */
+  { ISFUNC, (Function *)0x0 },         /* Q */
+  { ISFUNC, rl_vi_replace },           /* R */
+  { ISFUNC, rl_vi_subst },             /* S */
+  { ISFUNC, rl_vi_char_search },       /* T */
+  { ISFUNC, rl_revert_line },          /* U */
+  { ISFUNC, (Function *)0x0 },         /* V */
+  { ISFUNC, rl_vi_next_word },         /* W */
+  { ISFUNC, rl_rubout },               /* X */
+  { ISFUNC, rl_vi_yank_to },           /* Y */
+  { ISFUNC, (Function *)0x0 },         /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* [ */
+  { ISFUNC, (Function *)0x0 },         /* \ */
+  { ISFUNC, (Function *)0x0 },         /* ] */
+  { ISFUNC, rl_vi_first_print },       /* ^ */
+  { ISFUNC, rl_vi_yank_arg },          /* _ */
+  { ISFUNC, (Function *)0x0 },         /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_vi_append_mode },       /* a */
+  { ISFUNC, rl_vi_prev_word },         /* b */
+  { ISFUNC, rl_vi_change_to },         /* c */
+  { ISFUNC, rl_vi_delete_to },         /* d */
+  { ISFUNC, rl_vi_end_word },          /* e */
+  { ISFUNC, rl_vi_char_search },       /* f */
+  { ISFUNC, (Function *)0x0 },         /* g */
+  { ISFUNC, rl_backward },             /* h */
+  { ISFUNC, rl_vi_insertion_mode },    /* i */
+  { ISFUNC, rl_get_next_history },     /* j */
+  { ISFUNC, rl_get_previous_history }, /* k */
+  { ISFUNC, rl_forward },              /* l */
+  { ISFUNC, (Function *)0x0 },         /* m */
+  { ISFUNC, rl_vi_search_again },      /* n */
+  { ISFUNC, (Function *)0x0 },         /* o */
+  { ISFUNC, rl_vi_put },               /* p */
+  { ISFUNC, (Function *)0x0 },         /* q */
+  { ISFUNC, rl_vi_change_char },       /* r */
+  { ISFUNC, rl_vi_subst },             /* s */
+  { ISFUNC, rl_vi_char_search },       /* t */
+  { ISFUNC, rl_undo_command },         /* u */
+  { ISFUNC, (Function *)0x0 },         /* v */
+  { ISFUNC, rl_vi_next_word },         /* w */
+  { ISFUNC, rl_vi_delete },            /* x */
+  { ISFUNC, rl_vi_yank_to },           /* y */
+  { ISFUNC, (Function *)0x0 },         /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* { */
+  { ISFUNC, rl_vi_column },            /* | */
+  { ISFUNC, (Function *)0x0 },         /* } */
+  { ISFUNC, rl_vi_change_case },       /* ~ */
+  { ISFUNC, rl_backward }              /* RUBOUT */
+};
+
+
+KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
+
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, rl_insert },               /* Control-a */
+  { ISFUNC, rl_insert },               /* Control-b */
+  { ISFUNC, rl_insert },               /* Control-c */
+  { ISFUNC, rl_vi_eof_maybe },         /* Control-d */
+  { ISFUNC, rl_insert },               /* Control-e */
+  { ISFUNC, rl_insert },               /* Control-f */
+  { ISFUNC, rl_insert },               /* Control-g */
+  { ISFUNC, rl_rubout },               /* Control-h */
+  { ISFUNC, rl_complete },             /* Control-i */
+  { ISFUNC, rl_newline },              /* Control-j */
+  { ISFUNC, rl_insert },               /* Control-k */
+  { ISFUNC, rl_insert },               /* Control-l */
+  { ISFUNC, rl_newline },              /* Control-m */
+  { ISFUNC, rl_insert },               /* Control-n */
+  { ISFUNC, rl_insert },               /* Control-o */
+  { ISFUNC, rl_insert },               /* Control-p */
+  { ISFUNC, rl_insert },               /* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },      /* Control-t */
+  { ISFUNC, rl_unix_line_discard },    /* Control-u */
+  { ISFUNC, rl_quoted_insert },                /* Control-v */
+  { ISFUNC, rl_unix_word_rubout },     /* Control-w */
+  { ISFUNC, rl_insert },               /* Control-x */
+  { ISFUNC, rl_yank },                 /* Control-y */
+  { ISFUNC, rl_insert },               /* Control-z */
+
+  { ISFUNC, rl_vi_movement_mode },     /* Control-[ */
+  { ISFUNC, rl_insert },               /* Control-\ */
+  { ISFUNC, rl_insert },               /* Control-] */
+  { ISFUNC, rl_insert },               /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_insert },               /* SPACE */
+  { ISFUNC, rl_insert },               /* ! */
+  { ISFUNC, rl_insert },               /* " */
+  { ISFUNC, rl_insert },               /* # */
+  { ISFUNC, rl_insert },               /* $ */
+  { ISFUNC, rl_insert },               /* % */
+  { ISFUNC, rl_insert },               /* & */
+  { ISFUNC, rl_insert },               /* ' */
+  { ISFUNC, rl_insert },               /* ( */
+  { ISFUNC, rl_insert },               /* ) */
+  { ISFUNC, rl_insert },               /* * */
+  { ISFUNC, rl_insert },               /* + */
+  { ISFUNC, rl_insert },               /* , */
+  { ISFUNC, rl_insert },               /* - */
+  { ISFUNC, rl_insert },               /* . */
+  { ISFUNC, rl_insert },               /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_insert },               /* 0 */
+  { ISFUNC, rl_insert },               /* 1 */
+  { ISFUNC, rl_insert },               /* 2 */
+  { ISFUNC, rl_insert },               /* 3 */
+  { ISFUNC, rl_insert },               /* 4 */
+  { ISFUNC, rl_insert },               /* 5 */
+  { ISFUNC, rl_insert },               /* 6 */
+  { ISFUNC, rl_insert },               /* 7 */
+  { ISFUNC, rl_insert },               /* 8 */
+  { ISFUNC, rl_insert },               /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, rl_insert },               /* : */
+  { ISFUNC, rl_insert },               /* ; */
+  { ISFUNC, rl_insert },               /* < */
+  { ISFUNC, rl_insert },               /* = */
+  { ISFUNC, rl_insert },               /* > */
+  { ISFUNC, rl_insert },               /* ? */
+  { ISFUNC, rl_insert },               /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_insert },               /* A */
+  { ISFUNC, rl_insert },               /* B */
+  { ISFUNC, rl_insert },               /* C */
+  { ISFUNC, rl_insert },               /* D */
+  { ISFUNC, rl_insert },               /* E */
+  { ISFUNC, rl_insert },               /* F */
+  { ISFUNC, rl_insert },               /* G */
+  { ISFUNC, rl_insert },               /* H */
+  { ISFUNC, rl_insert },               /* I */
+  { ISFUNC, rl_insert },               /* J */
+  { ISFUNC, rl_insert },               /* K */
+  { ISFUNC, rl_insert },               /* L */
+  { ISFUNC, rl_insert },               /* M */
+  { ISFUNC, rl_insert },               /* N */
+  { ISFUNC, rl_insert },               /* O */
+  { ISFUNC, rl_insert },               /* P */
+  { ISFUNC, rl_insert },               /* Q */
+  { ISFUNC, rl_insert },               /* R */
+  { ISFUNC, rl_insert },               /* S */
+  { ISFUNC, rl_insert },               /* T */
+  { ISFUNC, rl_insert },               /* U */
+  { ISFUNC, rl_insert },               /* V */
+  { ISFUNC, rl_insert },               /* W */
+  { ISFUNC, rl_insert },               /* X */
+  { ISFUNC, rl_insert },               /* Y */
+  { ISFUNC, rl_insert },               /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_insert },               /* [ */
+  { ISFUNC, rl_insert },               /* \ */
+  { ISFUNC, rl_insert },               /* ] */
+  { ISFUNC, rl_insert },               /* ^ */
+  { ISFUNC, rl_insert },               /* _ */
+  { ISFUNC, rl_insert },               /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_insert },               /* a */
+  { ISFUNC, rl_insert },               /* b */
+  { ISFUNC, rl_insert },               /* c */
+  { ISFUNC, rl_insert },               /* d */
+  { ISFUNC, rl_insert },               /* e */
+  { ISFUNC, rl_insert },               /* f */
+  { ISFUNC, rl_insert },               /* g */
+  { ISFUNC, rl_insert },               /* h */
+  { ISFUNC, rl_insert },               /* i */
+  { ISFUNC, rl_insert },               /* j */
+  { ISFUNC, rl_insert },               /* k */
+  { ISFUNC, rl_insert },               /* l */
+  { ISFUNC, rl_insert },               /* m */
+  { ISFUNC, rl_insert },               /* n */
+  { ISFUNC, rl_insert },               /* o */
+  { ISFUNC, rl_insert },               /* p */
+  { ISFUNC, rl_insert },               /* q */
+  { ISFUNC, rl_insert },               /* r */
+  { ISFUNC, rl_insert },               /* s */
+  { ISFUNC, rl_insert },               /* t */
+  { ISFUNC, rl_insert },               /* u */
+  { ISFUNC, rl_insert },               /* v */
+  { ISFUNC, rl_insert },               /* w */
+  { ISFUNC, rl_insert },               /* x */
+  { ISFUNC, rl_insert },               /* y */
+  { ISFUNC, rl_insert },               /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, rl_insert },               /* { */
+  { ISFUNC, rl_insert },               /* | */
+  { ISFUNC, rl_insert },               /* } */
+  { ISFUNC, rl_insert },               /* ~ */
+  { ISFUNC, rl_rubout }                        /* RUBOUT */
+};
+
+KEYMAP_ENTRY_ARRAY vi_escape_keymap = {
+
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, (Function *)0x0 },         /* Control-a */
+  { ISFUNC, (Function *)0x0 },         /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, (Function *)0x0 },         /* Control-d */
+  { ISFUNC, (Function *)0x0 },         /* Control-e */
+  { ISFUNC, (Function *)0x0 },         /* Control-f */
+  { ISFUNC, (Function *)0x0 },         /* Control-g */
+  { ISFUNC, (Function *)0x0 },         /* Control-h */
+  { ISFUNC, rl_tab_insert},            /* Control-i */
+  { ISFUNC, rl_emacs_editing_mode},    /* Control-j */
+  { ISFUNC, rl_kill_line },            /* Control-k */
+  { ISFUNC, (Function *)0x0 },         /* Control-l */
+  { ISFUNC, rl_emacs_editing_mode},    /* Control-m */
+  { ISFUNC, (Function *)0x0 },         /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, (Function *)0x0 },         /* Control-p */
+  { ISFUNC, (Function *)0x0 },         /* Control-q */
+  { ISFUNC, (Function *)0x0 },         /* Control-r */
+  { ISFUNC, (Function *)0x0 },         /* Control-s */
+  { ISFUNC, (Function *)0x0 },         /* Control-t */
+  { ISFUNC, (Function *)0x0 },         /* Control-u */
+  { ISFUNC, (Function *)0x0 },         /* Control-v */
+  { ISFUNC, (Function *)0x0 },         /* Control-w */
+  { ISFUNC, (Function *)0x0 },         /* Control-x */
+  { ISFUNC, (Function *)0x0 },         /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+
+  { ISFUNC, rl_vi_movement_mode },     /* Control-[ */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 },         /* SPACE */
+  { ISFUNC, (Function *)0x0 },         /* ! */
+  { ISFUNC, (Function *)0x0 },         /* " */
+  { ISFUNC, (Function *)0x0 },         /* # */
+  { ISFUNC, (Function *)0x0 },         /* $ */
+  { ISFUNC, (Function *)0x0 },         /* % */
+  { ISFUNC, (Function *)0x0 },         /* & */
+  { ISFUNC, (Function *)0x0 },         /* ' */
+  { ISFUNC, (Function *)0x0 },         /* ( */
+  { ISFUNC, (Function *)0x0 },         /* ) */
+  { ISFUNC, (Function *)0x0 },         /* * */
+  { ISFUNC, (Function *)0x0 },         /* + */
+  { ISFUNC, (Function *)0x0 },         /* , */
+  { ISFUNC, (Function *)0x0 },         /* - */
+  { ISFUNC, (Function *)0x0 },         /* . */
+  { ISFUNC, (Function *)0x0 },         /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_vi_arg_digit },         /* 0 */
+  { ISFUNC, rl_vi_arg_digit },         /* 1 */
+  { ISFUNC, rl_vi_arg_digit },         /* 2 */
+  { ISFUNC, rl_vi_arg_digit },         /* 3 */
+  { ISFUNC, rl_vi_arg_digit },         /* 4 */
+  { ISFUNC, rl_vi_arg_digit },         /* 5 */
+  { ISFUNC, rl_vi_arg_digit },         /* 6 */
+  { ISFUNC, rl_vi_arg_digit },         /* 7 */
+  { ISFUNC, rl_vi_arg_digit },         /* 8 */
+  { ISFUNC, rl_vi_arg_digit },         /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* : */
+  { ISFUNC, (Function *)0x0 },         /* ; */
+  { ISFUNC, (Function *)0x0 },         /* < */
+  { ISFUNC, (Function *)0x0 },         /* = */
+  { ISFUNC, (Function *)0x0 },         /* > */
+  { ISFUNC, (Function *)0x0 },         /* ? */
+  { ISFUNC, (Function *)0x0 },         /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version }, /* A */
+  { ISFUNC, rl_do_lowercase_version }, /* B */
+  { ISFUNC, rl_do_lowercase_version }, /* C */
+  { ISFUNC, rl_do_lowercase_version }, /* D */
+  { ISFUNC, rl_do_lowercase_version }, /* E */
+  { ISFUNC, rl_do_lowercase_version }, /* F */
+  { ISFUNC, rl_do_lowercase_version }, /* G */
+  { ISFUNC, rl_do_lowercase_version }, /* H */
+  { ISFUNC, rl_do_lowercase_version }, /* I */
+  { ISFUNC, rl_do_lowercase_version }, /* J */
+  { ISFUNC, rl_do_lowercase_version }, /* K */
+  { ISFUNC, rl_do_lowercase_version }, /* L */
+  { ISFUNC, rl_do_lowercase_version }, /* M */
+  { ISFUNC, rl_do_lowercase_version }, /* N */
+  { ISFUNC, rl_do_lowercase_version }, /* O */
+  { ISFUNC, rl_do_lowercase_version }, /* P */
+  { ISFUNC, rl_do_lowercase_version }, /* Q */
+  { ISFUNC, rl_do_lowercase_version }, /* R */
+  { ISFUNC, rl_do_lowercase_version }, /* S */
+  { ISFUNC, rl_do_lowercase_version }, /* T */
+  { ISFUNC, rl_do_lowercase_version }, /* U */
+  { ISFUNC, rl_do_lowercase_version }, /* V */
+  { ISFUNC, rl_do_lowercase_version }, /* W */
+  { ISFUNC, rl_do_lowercase_version }, /* X */
+  { ISFUNC, rl_do_lowercase_version }, /* Y */
+  { ISFUNC, rl_do_lowercase_version }, /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* [ */
+  { ISFUNC, (Function *)0x0 },         /* \ */
+  { ISFUNC, (Function *)0x0 },         /* ] */
+  { ISFUNC, (Function *)0x0 },         /* ^ */
+  { ISFUNC, (Function *)0x0 },         /* _ */
+  { ISFUNC, (Function *)0x0 },         /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 },         /* a */
+  { ISFUNC, (Function *)0x0 },         /* b */
+  { ISFUNC, (Function *)0x0 },         /* c */
+  { ISFUNC, (Function *)0x0 },         /* d */
+  { ISFUNC, (Function *)0x0 },         /* e */
+  { ISFUNC, (Function *)0x0 },         /* f */
+  { ISFUNC, (Function *)0x0 },         /* g */
+  { ISFUNC, (Function *)0x0 },         /* h */
+  { ISFUNC, (Function *)0x0 },         /* i */
+  { ISFUNC, (Function *)0x0 },         /* j */
+  { ISFUNC, (Function *)0x0 },         /* k */
+  { ISFUNC, (Function *)0x0 },         /* l */
+  { ISFUNC, (Function *)0x0 },         /* m */
+  { ISFUNC, (Function *)0x0 },         /* n */
+  { ISFUNC, (Function *)0x0 },         /* o */
+  { ISFUNC, (Function *)0x0 },         /* p */
+  { ISFUNC, (Function *)0x0 },         /* q */
+  { ISFUNC, (Function *)0x0 },         /* r */
+  { ISFUNC, (Function *)0x0 },         /* s */
+  { ISFUNC, (Function *)0x0 },         /* t */
+  { ISFUNC, (Function *)0x0 },         /* u */
+  { ISFUNC, (Function *)0x0 },         /* v */
+  { ISFUNC, (Function *)0x0 },         /* w */
+  { ISFUNC, (Function *)0x0 },         /* x */
+  { ISFUNC, (Function *)0x0 },         /* y */
+  { ISFUNC, (Function *)0x0 },         /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* { */
+  { ISFUNC, (Function *)0x0 },         /* | */
+  { ISFUNC, (Function *)0x0 },         /* } */
+  { ISFUNC, (Function *)0x0 },         /* ~ */
+  { ISFUNC, rl_backward_kill_word }    /* RUBOUT */
+};
diff --git a/readline/vi_mode.c b/readline/vi_mode.c
new file mode 100644 (file)
index 0000000..478af91
--- /dev/null
@@ -0,0 +1,925 @@
+/* vi_mode.c -- A vi emulation mode for Bash.
+
+   Derived from code written by Jeff Sparkes (jeff1@????).
+ */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     VI Emulation Mode                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Last string searched for from `/' or `?'. */
+static char *vi_last_search = (char *)NULL;
+static int vi_histpos;
+
+/* Non-zero means enter insertion mode. */
+int vi_doing_insert = 0;
+
+/* *** UNCLEAN *** */
+/* Command keys which do movement for xxx_to commands. */
+static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
+
+/* Keymap used for vi replace characters.  Created dynamically since
+   rarely used. */
+static Keymap vi_replace_map = (Keymap)NULL;
+
+/* The number of characters inserted in the last replace operation. */
+static vi_replace_count = 0;
+
+/* Yank the nth arg from the previous line into this line at point. */
+rl_vi_yank_arg (count)
+     int count;
+{
+  rl_yank_nth_arg (count, 0);
+}
+
+/* Search again for the last thing searched for. */
+rl_vi_search_again (ignore, key)
+     int ignore, key;
+{
+  switch (key)
+    {
+    case 'n':
+      rl_vi_dosearch (vi_last_search, -1);
+      break;
+
+    case 'N':
+      rl_vi_dosearch (vi_last_search, 1);
+      break;
+    }
+}
+
+/* Do a vi style search. */
+rl_vi_search (count, key)
+     int count, key;
+{
+  int dir, c, save_pos;
+  char *p;
+
+  switch (key)
+    {
+    case '?':
+      dir = 1;
+      break;
+
+    case '/':
+      dir = -1;
+      break;
+
+    default:
+      ding ();
+      return;
+    }
+
+  vi_histpos = where_history ();
+  maybe_save_line ();
+  save_pos = rl_point;
+
+  /* Reuse the line input buffer to read the search string. */
+  the_line[0] = 0;
+  rl_end = rl_point = 0;
+  p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
+
+  sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);
+
+  rl_message (p, 0, 0);
+
+  while (c = rl_read_key ())
+    {
+      switch (c)
+       {
+       case CTRL('H'):
+       case RUBOUT:
+         if (rl_point == 0)
+           {
+             maybe_unsave_line ();
+             rl_clear_message ();
+             rl_point = save_pos;
+             return;
+           }
+
+       case CTRL('W'):
+       case CTRL('U'):
+         rl_dispatch (c, keymap);
+         break;
+
+       case ESC:
+       case RETURN:
+       case NEWLINE:
+         goto dosearch;
+         break;
+
+       case CTRL('C'):
+         maybe_unsave_line ();
+         rl_clear_message ();
+         rl_point = 0;
+         ding ();
+         return;
+
+       default:
+         rl_insert (1, c);
+         break;
+       }
+      rl_redisplay ();
+    }
+ dosearch:
+  if (vi_last_search)
+    free (vi_last_search);
+
+  vi_last_search = savestring (the_line);
+  rl_vi_dosearch (the_line, dir);
+}
+
+rl_vi_dosearch (string, dir)
+     char *string;
+     int dir;
+{
+  int old, save = vi_histpos;
+  HIST_ENTRY *h;
+
+  if (string == 0 || *string == 0 || vi_histpos < 0)
+    {
+      ding ();
+      return;
+    }
+
+  if ((save = history_search_pos (string, dir, vi_histpos + dir)) == -1)
+    {
+      maybe_unsave_line ();
+      rl_clear_message ();
+      rl_point = 0;
+      ding ();
+      return;
+    }
+
+  vi_histpos = save;
+
+  old = where_history ();
+  history_set_pos (vi_histpos);
+  h = current_history ();
+  history_set_pos (old);
+
+  strcpy (the_line, h->line);
+  rl_undo_list = (UNDO_LIST *)h->data;
+  rl_end = strlen (the_line);
+  rl_point = 0;
+  rl_clear_message ();
+}
+
+/* Completion, from vi's point of view. */
+rl_vi_complete (ignore, key)
+     int ignore, key;
+{
+  if (!whitespace (the_line[rl_point]))
+    {
+      if (!whitespace (the_line[rl_point + 1]))
+       rl_vi_end_word (1, 'E');
+      rl_point++;
+    }
+
+  if (key == '*')
+    rl_complete_internal ('*');
+  else
+    rl_complete (0, key);
+
+  rl_vi_insertion_mode ();
+}
+
+/* Previous word in vi mode. */
+rl_vi_prev_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      rl_vi_next_word (-count, key);
+      return;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_bWord (count);
+  else
+    rl_vi_bword (count);
+}
+
+/* Next word in vi mode. */
+rl_vi_next_word (count, key)
+     int count;
+{
+  if (count < 0)
+    {
+      rl_vi_prev_word (-count, key);
+      return;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_fWord (count);
+  else
+    rl_vi_fword (count);
+}
+
+/* Move to the end of the ?next? word. */
+rl_vi_end_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      ding ();
+      return;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_eWord (count);
+  else
+    rl_vi_eword (count);
+}
+
+/* Move forward a word the way that 'W' does. */
+rl_vi_fWord (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Skip until whitespace. */
+      while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
+       rl_point++;
+
+      /* Now skip whitespace. */
+      while (whitespace (the_line[rl_point]) && rl_point < rl_end)
+       rl_point++;
+    }
+}
+
+rl_vi_bWord (count)
+     int count;
+{
+  while (count-- && rl_point > 0)
+    {
+      while (rl_point-- >= 0 && whitespace (the_line[rl_point]));
+      while (rl_point >= 0 && !whitespace (the_line[rl_point]))
+       rl_point--;
+      rl_point++;
+    }
+}
+
+rl_vi_eWord (count)
+     int count;
+{
+  while (count -- && rl_point < (rl_end - 1))
+    {
+      while (rl_point++ < rl_end && whitespace (the_line[rl_point]));
+      while (rl_point++ < rl_end && !whitespace (the_line[rl_point]));
+      rl_point--;
+    }
+}
+
+rl_vi_fword (count)
+     int count;
+{
+  while (count -- && rl_point < (rl_end - 1))
+    {
+      if (isident (the_line[rl_point]))
+       {
+         while (isident (the_line[rl_point]) && rl_point < rl_end)
+           rl_point += 1;
+       }
+      else if (!whitespace (the_line[rl_point]))
+       {
+         while (!isident (the_line[rl_point]) &&
+                !whitespace (the_line[rl_point]) && rl_point < rl_end)
+           rl_point += 1;
+       }
+
+      while (whitespace (the_line[rl_point]) && rl_point < rl_end)
+       rl_point++;
+    }
+}
+
+rl_vi_bword (count)
+     int count;
+{
+  while (count -- && rl_point > 0)
+    {
+      while (--rl_point > 0 && whitespace (the_line[rl_point]));
+      if (rl_point > 0)
+       {
+         if (isident (the_line[rl_point]))
+           while (--rl_point >= 0 && isident (the_line[rl_point]));
+         else
+           while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
+                  !whitespace (the_line[rl_point]));
+         rl_point++;
+       }
+    }
+}
+
+rl_vi_eword (count)
+     int count;
+{
+  while (count -- && rl_point < rl_end - 1)
+    {
+      while (++rl_point < rl_end && whitespace (the_line[rl_point]));
+
+      if (rl_point < rl_end)
+       {
+         if (isident (the_line[rl_point]))
+           while (++rl_point < rl_end && isident (the_line[rl_point]));
+         else
+           while (++rl_point < rl_end && !isident (the_line[rl_point])
+                  && !whitespace (the_line[rl_point]));
+         rl_point--;
+       }
+    }
+}
+
+rl_vi_insert_beg ()
+{
+  rl_beg_of_line ();
+  rl_vi_insertion_mode ();
+  return 0;
+}
+
+rl_vi_append_mode ()
+{
+  if (rl_point < rl_end)
+    rl_point += 1;
+  rl_vi_insertion_mode ();
+  return 0;
+}
+
+rl_vi_append_eol ()
+{
+  rl_end_of_line ();
+  rl_vi_append_mode ();
+  return 0;
+}
+
+/* What to do in the case of C-d. */
+rl_vi_eof_maybe (count, c)
+     int count, c;
+{
+  rl_newline (1, '\n');
+}
+
+/* Insertion mode stuff. */
+
+/* Switching from one mode to the other really just involves
+   switching keymaps. */
+rl_vi_insertion_mode ()
+{
+  keymap = vi_insertion_keymap;
+}
+
+rl_vi_movement_mode ()
+{
+  if (rl_point > 0)
+    rl_backward (1);
+
+  keymap = vi_movement_keymap;
+  vi_done_inserting ();
+}
+
+vi_done_inserting ()
+{
+  if (vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      vi_doing_insert = 0;
+    }
+}
+
+rl_vi_arg_digit (count, c)
+     int count, c;
+{
+  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
+    rl_beg_of_line ();
+  else
+    rl_digit_argument (count, c);
+}
+
+/* Doesn't take an arg count in vi */
+rl_vi_change_case (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  char c = 0;
+
+  if (uppercase_p (the_line[rl_point]))
+    c = to_lower (the_line[rl_point]);
+  else if (lowercase_p (the_line[rl_point]))
+    c = to_upper (the_line[rl_point]);
+
+  /* Vi is kind of strange here. */
+  if (c)
+    {
+      rl_begin_undo_group ();
+      rl_delete (1, c);
+      rl_insert (1, c);
+      rl_end_undo_group ();
+      rl_vi_check ();
+    }
+  else
+    rl_forward (1);
+}
+
+rl_vi_put (count, key)
+     int count, key;
+{
+  if (!uppercase_p (key))
+    rl_forward (1);
+
+  rl_yank ();
+  rl_backward (1);
+}
+
+rl_vi_check ()
+{
+  if (rl_point && rl_point == rl_end)
+    rl_point--;
+}
+
+rl_vi_column (count)
+{
+  if (count > rl_end)
+    rl_end_of_line ();
+  else
+    rl_point = count - 1;
+}
+
+int
+rl_vi_domove (key, nextkey)
+     int key, *nextkey;
+{
+  int c, save;
+
+  rl_mark = rl_point;
+  c = rl_read_key ();
+  *nextkey = c;
+
+  if (!member (c, vi_motion))
+    {
+      if (digit (c))
+       {
+         save = rl_numeric_arg;
+         rl_digit_loop1 ();
+         rl_numeric_arg *= save;
+       }
+      else if ((key == 'd' && c == 'd') ||
+              (key == 'c' && c == 'c'))
+       {
+         rl_mark = rl_end;
+         rl_beg_of_line ();
+         return (0);
+       }
+      else
+       return (-1);
+    }
+
+  rl_dispatch (c, keymap);
+
+  /* No change in position means the command failed. */
+  if (rl_mark == rl_point)
+    return (-1);
+
+  if ((c == 'w' || c == 'W') && rl_point < rl_end)
+    rl_point--;
+
+  if (rl_mark < rl_point)
+    exchange (rl_point, rl_mark);
+
+  return (0);
+}
+
+/* A simplified loop for vi. Don't dispatch key at end.
+   Don't recognize minus sign? */
+rl_digit_loop1 ()
+{
+  int key, c;
+
+  while (1)
+    {
+      rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg, 0);
+      key = c = rl_read_key ();
+
+      if (keymap[c].type == ISFUNC &&
+         keymap[c].function == rl_universal_argument)
+       {
+         rl_numeric_arg *= 4;
+         continue;
+       }
+      c = UNMETA (c);
+      if (numeric (c))
+       {
+         if (rl_explicit_arg)
+           rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
+         else
+           rl_numeric_arg = (c - '0');
+         rl_explicit_arg = 1;
+       }
+      else
+       {
+         rl_clear_message ();
+         rl_stuff_char (key);
+       }
+    }
+}
+
+rl_vi_delete_to (count, key)
+     int count, key;
+{
+  int c;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return;
+    }
+
+  if ((c != '|') && (c != 'h') && rl_mark < rl_end)
+    rl_mark++;
+
+  rl_kill_text (rl_point, rl_mark);
+}
+
+rl_vi_change_to (count, key)
+     int count, key;
+{
+  int c;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return;
+    }
+
+  if ((c != '|') && (c != 'h') && rl_mark < rl_end)
+    rl_mark++;
+
+  rl_begin_undo_group ();
+  vi_doing_insert = 1;
+  rl_kill_text (rl_point, rl_mark);
+  rl_vi_insertion_mode ();
+}
+
+rl_vi_yank_to (count, key)
+     int count, key;
+{
+  int c, save = rl_point;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return;
+    }
+
+  rl_begin_undo_group ();
+  rl_kill_text (rl_point, rl_mark);
+  rl_end_undo_group ();
+  rl_do_undo ();
+  rl_point = save;
+}
+
+rl_vi_delete (count)
+{
+  if (rl_point >= rl_end - 1)
+    {
+      rl_delete (count, 0);
+      if (rl_point > 0)
+       rl_backward (1);
+    }
+  else
+    rl_delete (count, 0);
+}
+
+/* Turn the current line into a comment in shell history.  A ksh function */
+rl_vi_comment ()
+{
+  rl_beg_of_line ();
+  rl_insert_text (": ");       /* # doesn't work in interactive mode */
+  rl_redisplay ();
+  rl_newline (1, '\010');
+}
+
+rl_vi_first_print ()
+{
+  rl_back_to_indent ();
+}
+
+rl_back_to_indent (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  rl_beg_of_line ();
+  while (rl_point < rl_end && whitespace (the_line[rl_point]))
+    rl_point++;
+}
+
+/* NOTE: it is necessary that opposite directions are inverses */
+#define        FTO      1              /* forward to */
+#define BTO    -1              /* backward to */
+#define FFIND   2              /* forward find */
+#define BFIND  -2              /* backward find */
+
+rl_vi_char_search (count, key)
+     int count, key;
+{
+  static char target;
+  static int orig_dir, dir;
+  int pos;
+
+  if (key == ';' || key == ',')
+    dir = (key == ';' ? orig_dir : -orig_dir);
+  else
+    {
+      target = rl_getc (in_stream);
+
+      switch (key)
+       {
+       case 't':
+         orig_dir = dir = FTO;
+         break;
+
+       case 'T':
+         orig_dir = dir = BTO;
+         break;
+
+       case 'f':
+         orig_dir = dir = FFIND;
+         break;
+
+       case 'F':
+         orig_dir = dir = BFIND;
+         break;
+       }
+    }
+
+  pos = rl_point;
+
+  if (dir < 0)
+    {
+      pos--;
+      do
+       {
+         if (the_line[pos] == target)
+           {
+             if (dir == BTO)
+               rl_point = pos + 1;
+             else
+               rl_point = pos;
+             return;
+           }
+       }
+      while (pos--);
+
+      if (pos < 0)
+       {
+         ding ();
+         return;
+       }
+    }
+  else
+    {                  /* dir > 0 */
+      pos++;
+      do
+       {
+         if (the_line[pos] == target)
+           {
+             if (dir == FTO)
+               rl_point = pos - 1;
+             else
+               rl_point = pos;
+             return;
+           }
+       }
+      while (++pos < rl_end);
+
+      if (pos >= (rl_end - 1))
+       ding ();
+    }
+}
+
+/* Match brackets */
+rl_vi_match ()
+{
+  int count = 1, brack, pos;
+
+  pos = rl_point;
+  if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
+    {
+      while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
+            rl_point < rl_end - 1)
+       rl_forward (1);
+
+      if (brack <= 0)
+       {
+         rl_point = pos;
+         ding ();
+         return;
+       }
+    }
+
+  pos = rl_point;
+
+  if (brack < 0)
+    {
+      while (count)
+       {
+         if (--pos >= 0)
+           {
+             int b = rl_vi_bracktype (the_line[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             ding ();
+             return;
+           }
+       }
+    }
+  else
+    {                  /* brack > 0 */
+      while (count)
+       {
+         if (++pos < rl_end)
+           {
+             int b = rl_vi_bracktype (the_line[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             ding ();
+             return;
+           }
+       }
+    }
+  rl_point = pos;
+}
+
+int
+rl_vi_bracktype (c)
+     int c;
+{
+  switch (c)
+    {
+    case '(': return  1;
+    case ')': return -1;
+    case '[': return  2;
+    case ']': return -2;
+    case '{': return  3;
+    case '}': return -3;
+    default:  return  0;
+    }
+}
+
+rl_vi_change_char ()
+{
+  int c;
+
+  c = rl_getc (in_stream);
+
+  switch (c)
+    {
+    case '\033':
+    case CTRL('C'):
+      return;
+
+    default:
+      rl_begin_undo_group ();
+      rl_delete (1, c);
+      rl_insert (1, c);
+      rl_end_undo_group ();
+      break;
+    }
+}
+
+rl_vi_subst (count, key)
+     int count, key;
+{
+  rl_begin_undo_group ();
+  vi_doing_insert = 1;
+
+  if (uppercase_p (key))
+    {
+      rl_beg_of_line ();
+      rl_kill_line (1);
+    }
+  else
+    rl_delete (1, key);
+
+  rl_vi_insertion_mode ();
+}
+
+rl_vi_overstrike (count, key)
+     int count, key;
+{
+  int i;
+
+  if (vi_doing_insert == 0)
+    {
+      vi_doing_insert = 1;
+      rl_begin_undo_group ();
+    }
+
+  for (i = 0; i < count; i++)
+    {
+      vi_replace_count++;
+      rl_begin_undo_group ();
+
+      if (rl_point < rl_end)
+       {
+         rl_delete (1, key);
+         rl_insert (1, key);
+       }
+      else
+       rl_insert (1, key);
+
+      rl_end_undo_group ();
+    }
+}
+
+rl_vi_overstrike_delete (count)
+     int count;
+{
+  int i, s;
+
+  for (i = 0; i < count; i++)
+    {
+      if (vi_replace_count == 0)
+       {
+         ding ();
+         break;
+       }
+      s = rl_point;
+
+      if (rl_do_undo ())
+       vi_replace_count--;
+
+      if (rl_point == s)
+       rl_backward (1);
+    }
+
+  if (vi_replace_count == 0 && vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      rl_do_undo ();
+      vi_doing_insert = 0;
+    }
+}
+
+rl_vi_replace ()
+{
+  int i;
+
+  vi_replace_count = 0;
+
+  vi_replace_map = rl_make_bare_keymap ();
+
+  for (i = ' '; i < 127; i++)
+    vi_replace_map[i].function = rl_vi_overstrike;
+
+  vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
+  vi_replace_map[ESC].function = rl_vi_movement_mode;
+  vi_replace_map[RETURN].function = rl_newline;
+  vi_replace_map[NEWLINE].function = rl_newline;
+  keymap = vi_replace_map;
+}
+
+/*
+ * Try to complete the word we are standing on or the word that ends with
+ * the previous character. A space matches everything.
+ * Word delimiters are space and ;.
+ */
+rl_vi_possible_completions()
+{
+  int save_pos = rl_point;
+
+  if (!index (" ;", the_line[rl_point]))
+    {
+      while (!index(" ;", the_line[++rl_point]))
+       ;
+    }
+  else if (the_line[rl_point-1] == ';')
+    {
+      ding ();
+      return (0);
+    }
+
+  rl_possible_completions ();
+  rl_point = save_pos;
+
+  return (0);
+}